From 2fc1ec43560b453b4694adbc1aac11f3f23b1761 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Fri, 13 Apr 2012 01:33:24 +0300 Subject: [PATCH 001/294] Initial push of codership-wsrep API implementation for MariaDB. Merge of: lp:maria/5.5, #3334: http://bazaar.launchpad.net/~maria-captains/maria/5.5/revision/3334 lp:codership-mysql/5.5, #3725: http://bazaar.launchpad.net/~codership/codership-mysql/wsrep-5.5/revision/3725 --- BUILD/SETUP.sh | 2 +- CMakeLists.txt | 13 +- cmake/configure.pl | 10 + include/thr_lock.h | 13 + mysys/default.c | 10 + mysys/thr_lock.c | 119 +++ scripts/CMakeLists.txt | 4 + sql/CMakeLists.txt | 20 +- sql/events.cc | 12 + sql/handler.cc | 107 +- sql/handler.h | 14 + sql/item_func.cc | 12 + sql/lock.cc | 50 +- sql/log.cc | 240 ++++- sql/log.h | 26 +- sql/log_event.cc | 151 ++- sql/mdl.cc | 96 +- sql/mysqld.cc | 676 ++++++++++++- sql/mysqld.h | 17 + sql/protocol.cc | 8 + sql/set_var.h | 6 + sql/slave.cc | 8 + sql/sp.cc | 34 + sql/sql_alter.cc | 17 +- sql/sql_base.cc | 33 +- sql/sql_builtin.cc.in | 9 +- sql/sql_class.cc | 251 ++++- sql/sql_class.h | 87 +- sql/sql_connect.cc | 39 +- sql/sql_delete.cc | 12 + sql/sql_insert.cc | 22 + sql/sql_lex.cc | 11 + sql/sql_parse.cc | 1075 ++++++++++++++++++++- sql/sql_plugin.cc | 6 + sql/sql_reload.cc | 13 +- sql/sql_repl.cc | 14 + sql/sql_show.cc | 6 +- sql/sql_table.cc | 11 +- sql/sql_trigger.cc | 52 + sql/sql_truncate.cc | 10 +- sql/sql_update.cc | 12 + sql/sys_vars.cc | 200 ++++ sql/transaction.cc | 48 +- storage/innobase/handler/ha_innodb.cc | 1024 +++++++++++++++++++- storage/innobase/handler/ha_innodb.h | 38 + storage/innobase/handler/handler0alter.cc | 4 + storage/innobase/include/dict0mem.h | 3 + storage/innobase/include/ha_prototypes.h | 12 + storage/innobase/include/lock0lock.h | 1 + storage/innobase/include/rem0rec.h | 7 + storage/innobase/include/srv0srv.h | 4 + storage/innobase/include/trx0sys.h | 30 + storage/innobase/lock/lock0lock.c | 289 +++++- storage/innobase/os/os0file.c | 23 +- storage/innobase/rem/rem0rec.c | 72 ++ storage/innobase/row/row0ins.c | 48 +- storage/innobase/srv/srv0srv.c | 110 +++ storage/innobase/trx/trx0roll.c | 27 + storage/innobase/trx/trx0sys.c | 87 ++ storage/innobase/trx/trx0trx.c | 19 + storage/xtradb/handler/ha_innodb.cc | 1024 +++++++++++++++++++- storage/xtradb/handler/ha_innodb.h | 38 + storage/xtradb/handler/handler0alter.cc | 4 + storage/xtradb/include/dict0mem.h | 3 + storage/xtradb/include/ha_prototypes.h | 13 + storage/xtradb/include/lock0lock.h | 1 + storage/xtradb/include/rem0rec.h | 7 + storage/xtradb/include/srv0srv.h | 4 + storage/xtradb/include/trx0sys.h | 30 + storage/xtradb/lock/lock0lock.c | 289 +++++- storage/xtradb/os/os0file.c | 23 +- storage/xtradb/rem/rem0rec.c | 72 ++ storage/xtradb/row/row0ins.c | 48 +- storage/xtradb/srv/srv0srv.c | 110 +++ storage/xtradb/trx/trx0roll.c | 27 + storage/xtradb/trx/trx0sys.c | 87 ++ storage/xtradb/trx/trx0trx.c | 19 + support-files/CMakeLists.txt | 8 +- support-files/build-tags | 9 +- support-files/mysql.spec.sh | 70 +- 80 files changed, 7196 insertions(+), 64 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index c9eb1ebc03f..b0d6f97284d 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -204,7 +204,7 @@ all_configs="$SSL_LIBRARY --with-plugins=max --with-plugin-ndbcluster --with-emb alpha_cflags="$check_cpu_cflags -Wa,-m$cpu_flag" amd64_cflags="$check_cpu_cflags" amd64_cxxflags="" # If dropping '--with-big-tables', add here "-DBIG_TABLES" -pentium_cflags="$check_cpu_cflags" +pentium_cflags="$check_cpu_cflags -m32" pentium64_cflags="$check_cpu_cflags -m64" ppc_cflags="$check_cpu_cflags" sparc_cflags="" diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b6d1acb45f..1e137382da4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ INCLUDE(plugin) INCLUDE(install_macros) INCLUDE(install_layout) INCLUDE(mysql_add_executable) +INCLUDE(wsrep) # Handle options OPTION(DISABLE_SHARED @@ -176,6 +177,12 @@ MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) OPTION(WITH_FAST_MUTEXES "Compile with fast mutexes" OFF) MARK_AS_ADVANCED(WITH_FAST_MUTEXES) +OPTION(WITH_INNODB_DISALLOW_WRITES "InnoDB freeze writes patch from Google" ${WITH_WSREP}) +IF (WITH_INNODB_DISALLOW_WRITES) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") +ENDIF() + # Set DBUG_OFF and other optional release-only flags for non-debug project types FOREACH(BUILD_TYPE RELEASE RELWITHDEBINFO MINSIZEREL) FOREACH(LANG C CXX) @@ -284,6 +291,9 @@ ADD_SUBDIRECTORY(vio) ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(libmysql) +IF(WITH_WSREP) +ADD_SUBDIRECTORY(wsrep) +ENDIF() ADD_SUBDIRECTORY(extra) IF(NOT WITHOUT_SERVER) @@ -369,7 +379,7 @@ IF(NOT INSTALL_LAYOUT MATCHES "RPM") INSTALL(FILES README DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) INSTALL(FILES ${CMAKE_BINARY_DIR}/Docs/INFO_SRC ${CMAKE_BINARY_DIR}/Docs/INFO_BIN DESTINATION ${INSTALL_DOCDIR}) IF(UNIX) - INSTALL(FILES Docs/INSTALL-BINARY DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) + INSTALL(FILES Docs/INSTALL-BINARY Docs/README-wsrep DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) ENDIF() # MYSQL_DOCS_LOCATON is used in "make dist", points to the documentation directory SET(MYSQL_DOCS_LOCATION "" CACHE PATH "Location from where documentation is copied") @@ -377,6 +387,7 @@ IF(NOT INSTALL_LAYOUT MATCHES "RPM") INSTALL(DIRECTORY Docs/ DESTINATION ${INSTALL_DOCDIR} COMPONENT Documentation PATTERN "INSTALL-BINARY" EXCLUDE + PATTERN "README-wsrep" EXCLUDE PATTERN "Makefile.*" EXCLUDE PATTERN "glibc*" EXCLUDE PATTERN "linuxthreads.txt" EXCLUDE diff --git a/cmake/configure.pl b/cmake/configure.pl index 69f973c41fb..e8cfa0b1261 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -200,6 +200,16 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DMYSQL_DATADIR=".substr($option,14); next; } + if ($option =~ /layout=/) + { + $cmakeargs = $cmakeargs." -DINSTALL_LAYOUT=".substr($option,7); + next; + } + if ($option =~ /with-unix-socket-path=/) + { + $cmakeargs = $cmakeargs." -DMYSQL_UNIX_ADDR=".substr($option,22); + next; + } if ($option =~ /mysql-maintainer-mode/) { $cmakeargs = $cmakeargs." -DMYSQL_MAINTAINER_MODE=" . diff --git a/include/thr_lock.h b/include/thr_lock.h index 3f7a5ca988f..4551a3160ff 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -20,6 +20,15 @@ #ifdef __cplusplus extern "C" { #endif +#ifdef WITH_WSREP +#include + typedef int (* wsrep_thd_is_brute_force_fun)(void *); + typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); + typedef int (* wsrep_on_fun)(void *); + 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); +#endif #include #include @@ -95,6 +104,10 @@ typedef struct st_thr_lock_info { pthread_t thread; my_thread_id thread_id; +#ifdef WITH_WSREP + void *mysql_thd; // THD pointer + my_bool in_lock_tables; // true, if inside locking session +#endif } THR_LOCK_INFO; diff --git a/mysys/default.c b/mysys/default.c index c7ac0d89462..f331668de9f 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -87,6 +87,12 @@ static char my_defaults_extra_file_buffer[FN_REFLEN]; static my_bool defaults_already_read= FALSE; +#ifdef WITH_WSREP +/* The only purpose of this global array is to hold full name of my.cnf + * which seems to be otherwise unavailable */ +char wsrep_defaults_file[FN_REFLEN + 10]={0,}; +#endif /* WITH_WREP */ + /* Which directories are searched for options (and in which order) */ #define MAX_DEFAULT_DIRS 6 @@ -803,6 +809,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler, if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) return 1; /* Ignore wrong files */ +#ifdef WITH_WSREP + strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1); +#endif /* WITH_WSREP */ + while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) { line++; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index e99956f9c8f..2979244962d 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -94,7 +94,24 @@ be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time. my_bool thr_lock_inited=0; ulong locks_immediate = 0L, locks_waited = 0L; enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; +#ifdef WITH_WSREP +static wsrep_thd_is_brute_force_fun wsrep_thd_is_brute_force= NULL; +static wsrep_abort_thd_fun wsrep_abort_thd= NULL; +static my_bool wsrep_debug; +static my_bool wsrep_convert_LOCK_to_trx; +static wsrep_on_fun wsrep_on = NULL; +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 +) { + wsrep_thd_is_brute_force = bf_fun; + wsrep_abort_thd = abort_fun; + wsrep_debug = debug; + wsrep_convert_LOCK_to_trx= convert_LOCK_to_trx; + wsrep_on = on_fun; +} +#endif /* The following constants are only for debug output */ #define MAX_THREADS 1000 #define MAX_LOCKS 1000 @@ -1147,6 +1164,108 @@ static void sort_locks(THR_LOCK_DATA **data,uint count) } } +#ifdef WITH_WSREP +/* + * If brute force applier would need to wait for a thr lock, + * it needs to make sure that it will get the lock without (too much) + * delay. + * We identify here the owners of blocking locks and ask them to + * abort. We then put our lock request in the first place in the + * wait queue. When lock holders abort (one by one) the lock release + * algorithm should grant the lock to us. We rely on this and proceed + * to wait_for_locks(). + * wsrep_break_locks() should be called in all the cases, where lock + * wait would happen. + * + * TODO: current implementation might not cover all possible lock wait + * situations. This needs an review still. + * TODO: lock release, might favor some other lock (instead our bf). + * This needs an condition to check for bf locks first. + * TODO: we still have a debug fprintf, this should be removed + */ +static inline my_bool +wsrep_break_lock( + THR_LOCK_DATA *data, struct st_lock_list *lock_queue1, + struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue) +{ + if (wsrep_on(data->owner->mysql_thd) && + wsrep_thd_is_brute_force && + wsrep_thd_is_brute_force(data->owner->mysql_thd)) + { + THR_LOCK_DATA *holder; + + /* if locking session conversion to transaction has been enabled, + we know that this conflicting lock must be read lock and furthermore, + lock holder is read-only. It is safe to wait for him. + */ +#ifdef TODO + if (wsrep_convert_LOCK_to_trx && + (THD*)(data->owner->mysql_thd)->in_lock_tables) + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n"); + return FALSE; + } +#endif + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n"); + + /* aborting lock holder(s) here */ + for (holder=(lock_queue1) ? lock_queue1->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + for (holder=(lock_queue2) ? lock_queue2->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + + /* Add our lock to the head of the wait queue */ + if (*(wait_queue->last)==wait_queue->data) + { + wait_queue->last=&data->next; + assert(wait_queue->data==0); + } + else + { + assert(wait_queue->data!=0); + wait_queue->data->prev=&data->next; + } + data->next=wait_queue->data; + data->prev=&wait_queue->data; + wait_queue->data=data; + data->cond=get_cond(); + + statistic_increment(locks_immediate,&THR_LOCK_lock); + return TRUE; + } + return FALSE; +} +#endif enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index a454313d966..78456be59d4 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -307,6 +307,9 @@ IF(WIN32) INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/${file}.pl COMPONENT Server_Scripts) ENDFOREACH() ELSE() + IF(WITH_WSREP) + SET(WSREP_BINARIES wsrep_sst_mysqldump wsrep_sst_rsync) + ENDIF() # On Unix, most of the files end up in the bin directory SET(mysql_config_COMPONENT COMPONENT Development) SET(BIN_SCRIPTS @@ -324,6 +327,7 @@ ELSE() mysqldumpslow mysqld_multi mysqld_safe + ${WSREP_BINARIES} ) FOREACH(file ${BIN_SCRIPTS}) IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.sh) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 22c51f3ce23..f74931388bb 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -13,6 +13,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +IF(WITH_WSREP) + SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep) +ENDIF() + INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql @@ -20,6 +24,7 @@ ${CMAKE_SOURCE_DIR}/regex ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql +${WSREP_INCLUDES} ) SET(GEN_SOURCES @@ -35,6 +40,18 @@ ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER -DHAVE_POOL_OF_THREADS) IF(SSL_DEFINES) ADD_DEFINITIONS(${SSL_DEFINES}) ENDIF() +IF(WITH_WSREP) + SET(WSREP_SOURCES + wsrep_check_opts.cc + wsrep_hton.cc + wsrep_mysqld.cc + wsrep_notify.cc + wsrep_sst.cc + wsrep_utils.cc + wsrep_var.cc + ) + SET(WSREP_LIB wsrep) +ENDIF() SET (SQL_SOURCE ../sql-common/client.c derror.cc des_key_file.cc @@ -86,6 +103,7 @@ SET (SQL_SOURCE threadpool_common.cc ../sql-common/mysql_async.c sql_logger.cc + ${WSREP_SOURCES} ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) @@ -105,6 +123,7 @@ DTRACE_INSTRUMENT(sql) TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS} mysys dbug strings vio regex ${LIBWRAP} ${LIBCRYPT} ${LIBDL} + ${WSREP_LIB} ${SSL_LIBRARIES}) IF(WIN32) @@ -200,7 +219,6 @@ IF (NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) ENDIF() ENDIF() - INCLUDE(${CMAKE_SOURCE_DIR}/cmake/bison.cmake) RUN_BISON( ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy diff --git a/sql/events.cc b/sql/events.cc index 8b4bab9e3a6..208914a4e6d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1145,7 +1145,19 @@ end: close_mysql_tables(thd); DBUG_RETURN(ret); } +#ifdef WITH_WSREP +int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len) +{ + String log_query; + if (create_query_string(thd, &log_query)) + { + WSREP_WARN("events create string failed: %s", thd->query()); + return 1; + } + return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); +} +#endif /* WITH_WSREP */ /** @} (End of group Event_Scheduler) */ diff --git a/sql/handler.cc b/sql/handler.cc index 0310180759c..c04759b196f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -52,6 +52,9 @@ #include "../storage/maria/ha_maria.h" #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* While we have legacy_db_type, we have this array to check for dups and to find handlerton from legacy_db_type. @@ -1192,7 +1195,11 @@ int ha_commit_trans(THD *thd, bool all) { /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) - thd->transaction.cleanup(); +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else + thd->transaction.cleanup(); +#endif /* WITH_WSREP */ DBUG_RETURN(0); } @@ -1220,7 +1227,12 @@ int ha_commit_trans(THD *thd, bool all) mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE, MDL_EXPLICIT); +#ifdef WITH_WSREP + if (!WSREP(thd) && + thd->mdl_context.acquire_lock(&mdl_request, +#else if (thd->mdl_context.acquire_lock(&mdl_request, +#endif /* WITH_WSREP */ thd->variables.lock_wait_timeout)) { ha_rollback_trans(thd, all); @@ -1267,6 +1279,19 @@ int ha_commit_trans(THD *thd, bool all) err= ht->prepare(ht, thd, all); status_var_increment(thd->status_var.ha_prepare_count); if (err) +#ifdef WITH_WSREP + if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) + { + error= 1; + /* avoid sending error, if we need to replay */ + if (thd->wsrep_conflict_state!= MUST_REPLAY) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), err); + } + } + else + /* not wsrep hton, bail to native mysql behavior */ +#endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); if (err) @@ -1277,6 +1302,13 @@ int ha_commit_trans(THD *thd, bool all) } DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE();); +#ifdef WITH_WSREP + if (!error && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) + { + // xid was rewritten by wsrep + xid= wsrep_xid_seqno(&thd->transaction.xid_state.xid); + } +#endif // WITH_WSREP if (!is_real_trans) { error= commit_one_phase_2(thd, all, trans, is_real_trans); @@ -1363,6 +1395,18 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) int error= 0; Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; DBUG_ENTER("commit_one_phase_2"); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]= { 0, }; + snprintf (info, sizeof(info) - 1, "ha_commit_one_phase(%lld)", + (long long)thd->wsrep_trx_seqno); +#else + const char info[]="ha_commit_one_phase()"; +#endif /* WSREP_PROC_INFO */ + char* tmp_info= NULL; + if (WSREP(thd)) tmp_info= (char *)thd_proc_info(thd, info); +#endif /* WITH_WSREP */ + if (ha_info) { for (; ha_info; ha_info= ha_info_next) @@ -1391,7 +1435,14 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) } /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else thd->transaction.cleanup(); +#endif /* WITH_WSREP */ +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp_info); +#endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -1466,7 +1517,11 @@ int ha_rollback_trans(THD *thd, bool all) } /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else thd->transaction.cleanup(); +#endif /* WITH_WSREP */ if (all) thd->transaction_rollback_request= FALSE; @@ -1631,7 +1686,13 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, got, hton_name(hton)->str); for (int i=0; i < got; i ++) { +#ifdef WITH_WSREP + my_xid x=(wsrep_is_wsrep_xid(&info->list[i]) ? + wsrep_xid_seqno(&info->list[i]) : + info->list[i].get_my_xid()); +#else my_xid x=info->list[i].get_my_xid(); +#endif /* WITH_WSREP */ if (!x) // not "mine" - that is generated by external TM { #ifndef DBUG_OFF @@ -2635,7 +2696,12 @@ int handler::update_auto_increment() variables->auto_increment_increment); auto_inc_intervals_count++; /* Row-based replication does not need to store intervals in binlog */ +#ifdef WITH_WSREP + if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) && + !thd->is_current_stmt_binlog_format_row()) +#else if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row()) +#endif /* WITH_WSREP */ thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(), auto_inc_interval_for_cur_row.values(), variables->auto_increment_increment); @@ -4821,7 +4887,11 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) return (thd->is_current_stmt_binlog_format_row() && table->s->cached_row_logging_check && (thd->variables.option_bits & OPTION_BIN_LOG) && +#ifdef WITH_WSREP + ((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); +#else mysql_bin_log.is_open()); +#endif } @@ -5142,6 +5212,41 @@ void signal_log_not_needed(struct handlerton, char *log_file) } +#ifdef WITH_WSREP +/** + @details + This function makes the storage engine to force the victim transaction + to abort. Currently, only innodb has this functionality, but any SE + implementing the wsrep API should provide this service to support + multi-master operation. + + @param bf_thd brute force THD asking for the abort + @param victim_thd victim THD to be aborted + + @return + always 0 +*/ + +int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) +{ + DBUG_ENTER("ha_wsrep_abort_transaction"); + if (!WSREP(bf_thd)) { + DBUG_RETURN(0); + } + + handlerton *hton= installed_htons[DB_TYPE_INNODB]; + if (hton && hton->wsrep_abort_transaction) + { + hton->wsrep_abort_transaction(hton, bf_thd, victim_thd, signal); + } + else + { + WSREP_WARN("cannot abort InnoDB transaction"); + } + + DBUG_RETURN(0); +} +#endif /* WITH_WSREP */ #ifdef TRANS_LOG_MGM_EXAMPLE_CODE /* Example of transaction log management functions based on assumption that logs diff --git a/sql/handler.h b/sql/handler.h index d56e3242ddd..4ac7202587e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -355,6 +355,7 @@ enum legacy_db_type DB_TYPE_MARIA, /** Performance schema engine. */ DB_TYPE_PERFORMANCE_SCHEMA, + DB_TYPE_WSREP, DB_TYPE_FIRST_DYNAMIC=42, DB_TYPE_DEFAULT=127 // Must be last }; @@ -1042,6 +1043,10 @@ struct handlerton const char *wild, bool dir, List *files); int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db, const char *name); + int (*wsrep_abort_transaction)(handlerton *hton, THD *bf_thd, + THD *victim_thd, my_bool signal); + int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); + int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); uint32 license; /* Flag for Engine License */ /* Optional clauses in the CREATE/ALTER TABLE @@ -2885,6 +2890,9 @@ bool key_uses_partial_cols(TABLE *table, uint keyno); extern const char *ha_row_type[]; extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[]; extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[]; +#ifdef WITH_WSREP +extern MYSQL_PLUGIN_IMPORT const char *wsrep_binlog_format_names[]; +#endif /* WITH_WSREP */ extern TYPELIB tx_isolation_typelib; extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; @@ -2980,6 +2988,9 @@ int ha_enable_transaction(THD *thd, bool on); int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv); int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); +#ifdef WITH_WSREP +int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); +#endif /* WITH_WSREP */ /* these are called by storage engines */ void trans_register_ha(THD *thd, bool all, handlerton *ht); @@ -3010,6 +3021,9 @@ int ha_binlog_end(THD *thd); #define ha_binlog_wait(a) do {} while (0) #define ha_binlog_end(a) do {} while (0) #endif +#ifdef WITH_WSREP +void wsrep_brute_force_aborts(); +#endif const char *get_canonical_filename(handler *file, const char *path, char *tmp_path); diff --git a/sql/item_func.cc b/sql/item_func.cc index 92431a552c4..c56909d4335 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2583,7 +2583,19 @@ void Item_func_rand::seed_random(Item *arg) TODO: do not do reinit 'rand' for every execute of PS/SP if args[0] is a constant. */ +#ifdef WITH_WSREP + uint32 tmp; + if (WSREP(current_thd)) + { + if (current_thd->wsrep_exec_mode==REPL_RECV) + tmp= current_thd->wsrep_rand; + else + tmp= current_thd->wsrep_rand= (uint32) arg->val_int(); + } else + tmp= (uint32) arg->val_int(); +#else uint32 tmp= (uint32) arg->val_int(); +#endif /* WITH_WSREP */ my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L), (uint32) (tmp*0x10000001L)); } diff --git a/sql/lock.cc b/sql/lock.cc index a7029548493..bbaa51dbbae 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -84,6 +84,10 @@ #include #include +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ + /** @defgroup Locking Locking @{ @@ -314,6 +318,9 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) /* Copy the lock data array. thr_multi_lock() reorders its contents. */ memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks, sql_lock->lock_count * sizeof(*sql_lock->locks)); +#ifdef WITH_WSREP + thd->lock_info.in_lock_tables= thd->in_lock_tables; +#endif /* Lock on the copied half of the lock data array. */ /* Lock on the copied half of the lock data array. */ rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks + sql_lock->lock_count, @@ -323,7 +330,11 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) (void) unlock_external(thd, sql_lock->table, sql_lock->table_count); end: +#ifdef WITH_WSREP + thd_proc_info(thd, "mysql_lock_tables(): unlocking tables II"); +#else /* WITH_WSREP */ thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ if (thd->killed) { @@ -336,6 +347,9 @@ end: my_error(rc, MYF(0)); thd->set_time_after_lock(); +#ifdef WITH_WSREP + thd_proc_info(thd, "exit mysqld_lock_tables()"); +#endif /* WITH_WSREP */ DBUG_RETURN(rc); } @@ -1045,11 +1059,15 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) { thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); m_mdl_blocks_commits_lock= NULL; +#ifdef WITH_WSREP + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + wsrep->resume(wsrep); +#endif /* WITH_WSREP */ } thd->mdl_context.release_lock(m_mdl_global_shared_lock); m_mdl_global_shared_lock= NULL; m_state= GRL_NONE; - + DBUG_VOID_RETURN; } @@ -1077,9 +1095,39 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) If we didn't succeed lock_global_read_lock(), or if we already suceeded make_global_read_lock_block_commit(), do nothing. */ + +#ifdef WITH_WSREP + if (m_mdl_blocks_commits_lock) + { + WSREP_DEBUG("GRL was in block commit mode when entering " + "make_global_read_lock_block_commit"); + thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); + m_mdl_blocks_commits_lock= NULL; + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + wsrep->resume(wsrep); + m_state= GRL_ACQUIRED; + } +#endif /* WITH_WSREP */ + if (m_state != GRL_ACQUIRED) DBUG_RETURN(0); +#ifdef WITH_WSREP + 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)); + + /* m_mdl_blocks_commits_lock is always NULL here */ + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + my_error(ER_LOCK_DEADLOCK, MYF(0)); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); if (thd->mdl_context.acquire_lock(&mdl_request, diff --git a/sql/log.cc b/sql/log.cc index 577297fa1a4..ee7d548d81a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -51,6 +51,9 @@ #include "sql_plugin.h" #include "rpl_handler.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ #include "debug_sync.h" /* max size of the log message */ @@ -486,6 +489,9 @@ private: }; handlerton *binlog_hton; +#ifdef WITH_WSREP +extern handlerton *wsrep_hton; +#endif bool LOGGER::is_log_table_enabled(uint log_table_type) { @@ -500,6 +506,134 @@ bool LOGGER::is_log_table_enabled(uint log_table_type) } } +#ifdef WITH_WSREP +IO_CACHE * get_trans_log(THD * thd) +{ + binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*) + thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + { + return cache_mngr->get_binlog_cache_log(true); + } + else + { + WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id); + return NULL; + } +} + + +bool wsrep_trans_cache_is_empty(THD *thd) +{ + bool res= TRUE; + + if (thd_sql_command((const THD*) thd) != SQLCOM_SELECT) + res= FALSE; + else + { + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + { + res= cache_mngr->trx_cache.empty(); + } + } + return res; +} + +void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end) +{ + thd->binlog_flush_pending_rows_event(stmt_end); +} +void thd_binlog_trx_reset(THD * thd) +{ + /* + todo: fix autocommit select to not call the caller + */ + if (thd_get_ha_data(thd, binlog_hton) != NULL) + { + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) cache_mngr->reset(TRUE, TRUE); + } + thd->clear_binlog_table_maps(); +} + +void thd_binlog_rollback_stmt(THD * thd) +{ + WSREP_DEBUG("thd_binlog_rollback_stmt :%ld", thd->thread_id); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); +} +/* + Write the contents of a cache to memory buffer. + + 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(IO_CACHE *cache, uchar **buf, uint *buf_len) +{ + + if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) + return ER_ERROR_ON_WRITE; + uint length= my_b_bytes_in_cache(cache); + long long total_length = 0; + uchar *buf_ptr = NULL; + + do + { + /* bail out if buffer grows too large + This is a temporary fix to avoid flooding replication + TODO: remove this check for 0.7.4 release + */ + if (total_length > wsrep_max_ws_size) + { + WSREP_WARN("transaction size limit (%lld) exceeded: %lld", + wsrep_max_ws_size, total_length); + if (reinit_io_cache(cache, WRITE_CACHE, 0, 0, 0)) + { + WSREP_WARN("failed to initialize io-cache"); + } + if (buf_ptr) my_free(*buf); + *buf_len = 0; + return ER_ERROR_ON_WRITE; + } + if (total_length > 0) + { + *buf_len += length; + *buf = (uchar *)my_realloc(*buf, total_length+length, MYF(0)); + if (!*buf) + { + WSREP_ERROR("io cache write problem: %d %d", *buf_len, length); + return ER_ERROR_ON_WRITE; + } + buf_ptr = *buf+total_length; + } + else + { + if (buf_ptr != NULL) + { + WSREP_ERROR("io cache alloc error: %d %d", *buf_len, length); + my_free(*buf); + } + if (length > 0) + { + *buf = (uchar *) my_malloc(length, MYF(0)); + buf_ptr = *buf; + *buf_len = length; + } + } + total_length += length; + + memcpy(buf_ptr, cache->read_pos, length); + cache->read_pos=cache->read_end; + } while ((cache->file >= 0) && (length= my_b_fill(cache))); + + return 0; +} +#endif /* Check if a given table is opened log table */ int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, @@ -1536,7 +1670,11 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos) thd->binlog_setup_trx_data(); binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); +#ifdef WITH_WSREP + DBUG_ASSERT((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()); +#else DBUG_ASSERT(mysql_bin_log.is_open()); +#endif *pos= cache_mngr->trx_cache.get_byte_position(); DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos)); DBUG_VOID_RETURN; @@ -1584,7 +1722,16 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos) int binlog_init(void *p) { binlog_hton= (handlerton *)p; +#ifdef WITH_WSREP + if (WSREP_ON) + binlog_hton->state= SHOW_OPTION_YES; + else + { +#endif /* WITH_WSREP */ binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ binlog_hton->db_type=DB_TYPE_BINLOG; binlog_hton->savepoint_offset= sizeof(my_off_t); binlog_hton->close_connection= binlog_close_connection; @@ -1840,6 +1987,9 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) DBUG_ENTER("binlog_commit"); binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); +#ifdef WITH_WSREP + if (!cache_mngr) DBUG_RETURN(0); +#endif /* WITH_WSREP */ DBUG_PRINT("debug", ("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", @@ -1896,6 +2046,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) int error= 0; binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); +#ifdef WITH_WSREP + if (!cache_mngr) DBUG_RETURN(0); +#endif /* WITH_WSREP */ DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", YESNO(all), @@ -1924,8 +2077,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) cache_mngr->reset(false, true); DBUG_RETURN(error); } - +#ifdef WITH_WSREP + if (!wsrep_emulate_bin_log && + mysql_bin_log.check_write_error(thd)) +#else if (mysql_bin_log.check_write_error(thd)) +#endif { /* "all == true" means that a "rollback statement" triggered the error and @@ -1955,12 +2112,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) if (ending_trans(thd, all) && ((thd->variables.option_bits & OPTION_KEEP_LOG) || (trans_has_updated_non_trans_table(thd) && - thd->variables.binlog_format == BINLOG_FORMAT_STMT) || + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT) || (cache_mngr->trx_cache.changes_to_non_trans_temp_table() && - thd->variables.binlog_format == BINLOG_FORMAT_MIXED) || + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) || (trans_has_updated_non_trans_table(thd) && ending_single_stmt_trans(thd,all) && - thd->variables.binlog_format == BINLOG_FORMAT_MIXED))) + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED))) error= binlog_rollback_flush_trx_cache(thd, all, cache_mngr); /* Truncate the cache if: @@ -1974,9 +2131,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) else if (ending_trans(thd, all) || (!(thd->variables.option_bits & OPTION_KEEP_LOG) && (!stmt_has_updated_non_trans_table(thd) || - thd->variables.binlog_format != BINLOG_FORMAT_STMT) && + WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_STMT) && (!cache_mngr->trx_cache.changes_to_non_trans_temp_table() || - thd->variables.binlog_format != BINLOG_FORMAT_MIXED))) + WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_MIXED))) error= binlog_truncate_trx_cache(thd, cache_mngr, all); } @@ -2070,7 +2227,9 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) binlog_trans_log_savepos(thd, (my_off_t*) sv); /* Write it to the binary log */ - +#ifdef WITH_WSREP + if (wsrep_emulate_bin_log) DBUG_RETURN(0); +#endif /* WITH_WSREP */ String log_query; if (log_query.append(STRING_WITH_LEN("SAVEPOINT ")) || log_query.append("`") || @@ -2092,7 +2251,12 @@ 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 + if (!wsrep_emulate_bin_log && + unlikely(trans_has_updated_non_trans_table(thd) || +#else if (unlikely(trans_has_updated_non_trans_table(thd) || +#endif (thd->variables.option_bits & OPTION_KEEP_LOG))) { String log_query; @@ -4720,6 +4884,7 @@ int THD::binlog_setup_trx_data() DBUG_RETURN(0); } + /* Function to start a statement and optionally a transaction for the binary log. @@ -4839,7 +5004,12 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional, table->s->table_map_id)); /* Pre-conditions */ +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + (WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif DBUG_ASSERT(table->s->table_map_id != ULONG_MAX); Table_map_log_event @@ -4976,7 +5146,11 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, bool is_transactional) { DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)"); +#ifdef WITH_WSREP + DBUG_ASSERT(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()); +#else DBUG_ASSERT(mysql_bin_log.is_open()); +#endif DBUG_PRINT("enter", ("event: 0x%lx", (long) event)); int error= 0; @@ -5056,7 +5230,11 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) mostly called if is_open() *was* true a few instructions before, but it could have changed since. */ +#ifdef WITH_WSREP + if ((WSREP(thd) && wsrep_emulate_bin_log) || is_open()) +#else if (likely(is_open())) +#endif { my_off_t UNINIT_VAR(my_org_b_tell); #ifdef HAVE_REPLICATION @@ -5237,6 +5415,35 @@ err: } } +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_incremental_data_collection && + (wsrep_emulate_bin_log || mysql_bin_log.is_open())) + { + DBUG_ASSERT(thd->wsrep_trx_handle.trx_id != (unsigned long)-1); + if (!error) + { + IO_CACHE* cache= get_trans_log(thd); + uchar* buf= NULL; + uint buf_len= 0; + + if (wsrep_emulate_bin_log) + thd->binlog_flush_pending_rows_event(false); + error= wsrep_write_cache(cache, &buf, &buf_len); + if (!error && buf_len > 0) + { + wsrep_status_t rc= wsrep->append_data(wsrep, + &thd->wsrep_trx_handle, + buf, buf_len); + if (rc != WSREP_OK) + { + sql_print_warning("WSREP: append_data() returned %d", rc); + error= 1; + } + } + if (buf_len) my_free(buf); + } + } +#endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -5329,6 +5536,14 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge) { int error= 0; DBUG_ENTER("MYSQL_BIN_LOG::rotate"); +#ifdef WITH_WSREP + if (WSREP_ON && wsrep_to_isolation) + { + WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d", + wsrep_to_isolation); + DBUG_RETURN(0); + } +#endif //todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log); *check_purge= false; @@ -5797,6 +6012,9 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, group_commit_entry entry; DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_to_binlog"); +#ifdef WITH_WSREP + if (wsrep_emulate_bin_log) DBUG_RETURN(0); +#endif /* WITH_WSREP */ entry.thd= thd; entry.cache_mngr= cache_mngr; entry.error= 0; @@ -7426,7 +7644,13 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all, binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - +#ifdef WITH_WSREP + if (!cache_mngr) + { + WSREP_DEBUG("Skipping empty log_xid: %s", thd->query()); + DBUG_RETURN(1); + } +#endif /* WITH_WSREP */ cache_mngr->using_xa= TRUE; cache_mngr->xa_xid= xid; err= binlog_commit_flush_xid_caches(thd, cache_mngr, all, xid); diff --git a/sql/log.h b/sql/log.h index e8f59801683..2bc4d0e49d7 100644 --- a/sql/log.h +++ b/sql/log.h @@ -94,7 +94,7 @@ public: int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) { - DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called */); + //DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called */); return 1; } int unlog(ulong cookie, my_xid xid) { return 0; } @@ -267,6 +267,12 @@ enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; (mmap+fsync is two times faster than write+fsync) */ +#ifdef WITH_WSREP +extern my_bool wsrep_emulate_bin_log; +Log_event* wsrep_read_log_event( + char **arg_buf, size_t *arg_buf_len, + const Format_description_log_event *description_event); +#endif class MYSQL_LOG { public: @@ -846,12 +852,30 @@ public: }; enum enum_binlog_format { + /* + statement-based except for cases where only row-based can work (UUID() + etc): + */ BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected BINLOG_FORMAT_STMT= 1, ///< statement-based BINLOG_FORMAT_ROW= 2, ///< row-based BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed }; +#ifdef WITH_WSREP +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_trx_reset(THD * thd); +void thd_binlog_rollback_stmt(THD * thd); +int wsrep_write_cache(IO_CACHE *cache, uchar **buf, uint *buf_len); + +#define WSREP_FORMAT(my_format) \ + ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ + wsrep_forced_binlog_format : my_format) +#else +#define WSREP_FORMAT(my_format) my_format +#endif int query_error_code(THD *thd, bool not_killed); uint purge_log_get_error_code(int res); diff --git a/sql/log_event.cc b/sql/log_event.cc index cec0785a088..05340fff03a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -46,6 +46,9 @@ #include "transaction.h" #include +#if WITH_WSREP +#include "wsrep_mysqld.h" +#endif #endif /* MYSQL_CLIENT */ #include @@ -2769,7 +2772,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, master_data_written(0) { time_t end_time; - +#ifdef WITH_WSREP + thd->wsrep_PA_safe= false; +#endif /* WITH_WSREP */ memset(&user, 0, sizeof(user)); memset(&host, 0, sizeof(host)); @@ -6983,7 +6988,14 @@ err: end_io_cache(&file); if (fd >= 0) mysql_file_close(fd, MYF(0)); +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "exit Create_file_log_event::do_apply_event()"); + else + thd_proc_info(thd, 0); +#else /* WITH_WSREP */ thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ return error != 0; } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -7154,7 +7166,14 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) err: if (fd >= 0) mysql_file_close(fd, MYF(0)); +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "exit Append_block_log_event::do_apply_event()"); + else + thd_proc_info(thd, 0); +#else /* WITH_WSREP */ thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ DBUG_RETURN(error); } #endif @@ -8097,7 +8116,17 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) if (open_and_lock_tables(thd, rli->tables_to_lock, FALSE, 0)) { +#ifdef WITH_WSREP + uint actual_error= ER_SERVER_SHUTDOWN; + if (WSREP(thd) && !thd->is_fatal_error) + { + sql_print_information("WSREP, BF applier interrupted in log_event.cc"); + } + else + actual_error= thd->stmt_da->sql_errno(); +#else uint actual_error= thd->stmt_da->sql_errno(); +#endif if (thd->is_slave_error || thd->is_fatal_error) { /* @@ -9842,8 +9871,23 @@ int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Write_rows_log_event::write_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Write_rows_log_event::write_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ if (error && !thd->is_error()) { DBUG_ASSERT(0); @@ -10496,14 +10540,39 @@ int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) int error; DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Delete_rows_log_event::find_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Delete_rows_log_event::find_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ if (!(error= find_row(rli))) { /* Delete the record found, located in record[0] */ +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Delete_rows_log_event::ha_delete_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) thd_proc_info(thd,"Delete_rows_log_event::ha_delete_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ error= m_table->file->ha_delete_row(m_table->record[0]); m_table->file->ha_index_or_rnd_end(); } +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ return error; } @@ -10617,6 +10686,18 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Update_rows_log_event::find_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Update_rows_log_event::find_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ int error= find_row(rli); if (error) { @@ -10643,6 +10724,17 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) store_record(m_table,record[1]); m_curr_row= m_curr_row_end; +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Update_rows_log_event::unpack_current_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) + thd_proc_info(thd,"Update_rows_log_event::unpack_current_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ /* this also updates m_curr_row_end */ if ((error= unpack_current_row(rli))) goto err; @@ -10661,10 +10753,23 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength); #endif +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Update_rows_log_event::ha_update_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) thd_proc_info(thd,"Update_rows_log_event::ha_update_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]); if (error == HA_ERR_RECORD_IS_THE_SAME) error= 0; +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ err: m_table->file->ha_index_or_rnd_end(); return error; @@ -10749,6 +10854,50 @@ void Incident_log_event::pack_info(Protocol *protocol) protocol->store(buf, bytes, &my_charset_bin); } #endif +#if WITH_WSREP && !defined(MYSQL_CLIENT) +Format_description_log_event *wsrep_format_desc; // TODO: free them at the end +/* + read the first event from (*buf). The size of the (*buf) is (*buf_len). + 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. +*/ +Log_event* wsrep_read_log_event( + char **arg_buf, size_t *arg_buf_len, + const Format_description_log_event *description_event) +{ + DBUG_ENTER("wsrep_read_log_event"); + char *head= (*arg_buf); + + uint data_len = uint4korr(head + EVENT_LEN_OFFSET); + char *buf= (*arg_buf); + const char *error= 0; + Log_event *res= 0; +#ifndef max_allowed_packet + THD *thd=current_thd; + uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0; +#endif + + if (data_len > max_allowed_packet) + { + error = "Event too big"; + goto err; + } + + res= Log_event::read_log_event(buf, data_len, &error, description_event, FALSE); + +err: + if (!res) + { + DBUG_ASSERT(error != 0); + sql_print_error("Error in Log_event::read_log_event(): " + "'%s', data_len: %d, event_type: %d", + error,data_len,head[EVENT_TYPE_OFFSET]); + } + (*arg_buf)+= data_len; + (*arg_buf_len)-= data_len; + DBUG_RETURN(res); +} +#endif #ifdef MYSQL_CLIENT diff --git a/sql/mdl.cc b/sql/mdl.cc index ca552a540b9..8ff420e4f50 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -20,7 +20,17 @@ #include #include #include +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" char *wsrep_thd_query(THD *thd); +void sql_print_information(const char *format, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); +extern bool +wsrep_grant_mdl_exception(MDL_context *requestor_ctx, + MDL_ticket *ticket); +#endif /* WITH_WSREP */ #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; static PSI_mutex_key key_MDL_wait_LOCK_wait_status; @@ -1222,11 +1232,54 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) called by other threads. */ DBUG_ASSERT(ticket->get_lock()); +#ifdef WITH_WSREP + if ((this == &(ticket->get_lock()->m_waiting)) && + wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->get_thd()))) + { + Ticket_iterator itw(ticket->get_lock()->m_waiting); + Ticket_iterator itg(ticket->get_lock()->m_granted); + + MDL_ticket *waiting, *granted; + MDL_ticket *prev=NULL; + bool added= false; + + while ((waiting= itw++) && !added) + { + if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->get_thd()))) + { + WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", + wsrep_thd_thread_id(waiting->get_ctx()->get_thd()), + wsrep_thd_query(waiting->get_ctx()->get_thd())); + m_list.insert_after(prev, ticket); + added= true; + } + prev= waiting; + } + 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)) + { + WSREP_DEBUG("MDL victim killed at add_ticket"); + } + } + } + } + else + { +#endif /* WITH_WSREP */ /* Add ticket to the *back* of the queue to ensure fairness among requests with the same priority. */ m_list.push_back(ticket); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ m_bitmap|= MDL_BIT(ticket->get_type()); } @@ -1463,7 +1516,6 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] = 0 }; - /** Check if request for the metadata lock can be satisfied given its current state. @@ -1486,6 +1538,9 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, bool can_grant= FALSE; bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg]; bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg]; +#ifdef WITH_WSREP + bool wsrep_can_grant= TRUE; +#endif /* WITH_WSREP */ /* New lock request can be satisfied iff: - There are no incompatible types of satisfied requests @@ -1507,12 +1562,51 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, { if (ticket->get_ctx() != requestor_ctx && ticket->is_incompatible_when_granted(type_arg)) +#ifdef WITH_WSREP + { + if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + key.mdl_namespace() == MDL_key::GLOBAL) + { + WSREP_DEBUG("global lock granted for BF: %lu %s", + wsrep_thd_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)) + { + wsrep_can_grant= FALSE; + } + else + { + can_grant= TRUE; + } + } +#else break; +#endif /* WITH_WSREP */ } +#ifdef WITH_WSREP + if ((ticket == NULL) && wsrep_can_grant) +#else if (ticket == NULL) /* Incompatible locks are our own. */ +#endif /* WITH_WSREP */ + can_grant= TRUE; } } +#ifdef WITH_WSREP + else + { + if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + key.mdl_namespace() == MDL_key::GLOBAL) + { + WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", + wsrep_thd_thread_id(requestor_ctx->get_thd()), + wsrep_thd_query(requestor_ctx->get_thd())); + can_grant = true; + } + } +#endif /* WITH_WSREP */ return can_grant; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7394ce5c931..2251663c94a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -72,6 +72,10 @@ #include "scheduler.h" #include #include "debug_sync.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +ulong wsrep_running_threads = 0; // # of currently running wsrep threads +#endif #include "sql_callback.h" #include "threadpool.h" @@ -360,6 +364,9 @@ static DYNAMIC_ARRAY all_options; /* Global variables */ +#ifdef WITH_WSREP +ulong my_bind_addr; +#endif /* WITH_WSREP */ bool opt_bin_log, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0, opt_abort; ulonglong log_output_options; @@ -452,6 +459,10 @@ ulong opt_binlog_rows_event_max_size; my_bool opt_master_verify_checksum= 0; my_bool opt_slave_sql_verify_checksum= 1; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; +#ifdef WITH_WSREP +const char *wsrep_binlog_format_names[]= + {"MIXED", "STATEMENT", "ROW", "NONE", NullS}; +#endif /*WITH_WSREP */ #ifdef HAVE_INITGROUPS volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */ #endif @@ -671,6 +682,21 @@ pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; +#ifdef WITH_WSREP +mysql_mutex_t LOCK_wsrep_ready; +mysql_cond_t COND_wsrep_ready; +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; +int wsrep_replaying= 0; +static void wsrep_close_threads(THD* thd); +#endif int mysqld_server_started= 0; File_parser_dummy_hook file_parser_dummy_hook; @@ -740,6 +766,11 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc; +#ifdef WITH_WSREP +PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, + key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst, + key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init; +#endif PSI_mutex_key key_RELAYLOG_LOCK_index; PSI_mutex_key key_LOCK_stats, @@ -810,6 +841,16 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, { &key_LOCK_logger_service, "logger_service_file_st::lock", PSI_FLAG_GLOBAL}, +#ifdef WITH_WSREP + { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0}, + { &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0}, + { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL}, +#endif { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} }; @@ -847,6 +888,11 @@ PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, key_BINLOG_COND_queue_busy; +#ifdef WITH_WSREP +PSI_cond_key key_COND_wsrep_rollback, 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; +#endif /* WITH_WSREP */ PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready; PSI_cond_key key_RELAYLOG_COND_queue_busy; PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy; @@ -888,6 +934,15 @@ static PSI_cond_info all_server_conds[]= { &key_user_level_lock_cond, "User_level_lock::cond", 0}, { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL}, { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL}, +#ifdef WITH_WSREP + { &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0}, + { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0}, + { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL}, +#endif { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL} }; @@ -1413,6 +1468,11 @@ static void close_connections(void) if (tmp->slave_thread) continue; +#ifdef WITH_WSREP + /* skip wsrep system threads as well */ + if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) + continue; +#endif tmp->killed= KILL_SERVER_HARD; MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); mysql_mutex_lock(&tmp->LOCK_thd_data); @@ -1475,6 +1535,33 @@ static void close_connections(void) tmp->main_security_ctx.user : "")); close_connection(tmp,ER_SERVER_SHUTDOWN); } +#endif +#ifdef WITH_WSREP + /* + * TODO: this code block may turn out redundant. wsrep->disconnect() + * should terminate slave threads gracefully, and we don't need + * to signal them here. + * 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) + { + sql_print_information("closing wsrep system thread"); + tmp->killed= KILL_CONNECTION; + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + if (tmp->mysys_var) + { + tmp->mysys_var->abort=1; + mysql_mutex_lock(&tmp->mysys_var->mutex); + if (tmp->mysys_var->current_cond) + { + mysql_mutex_lock(tmp->mysys_var->current_mutex); + mysql_cond_broadcast(tmp->mysys_var->current_cond); + mysql_mutex_unlock(tmp->mysys_var->current_mutex); + } + mysql_mutex_unlock(&tmp->mysys_var->mutex); + } + } #endif DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); mysql_mutex_unlock(&LOCK_thread_count); @@ -1636,8 +1723,14 @@ static void __cdecl kill_server(int sig_ptr) } } #endif +#ifdef WITH_WSREP + if (WSREP_ON) wsrep_stop_replication(NULL); +#endif close_connections(); +#ifdef WITH_WSREP + if (WSREP_ON) wsrep_deinit(); +#endif if (sig != MYSQL_KILL_SIGNAL && sig != 0) unireg_abort(1); /* purecov: inspected */ @@ -1732,6 +1825,21 @@ extern "C" void unireg_abort(int exit_code) usage(); if (exit_code) sql_print_error("Aborting\n"); +#ifdef WITH_WSREP + if (wsrep) + { + /* This is an abort situation, we cannot expect to gracefully close all + * wsrep threads here, we can only diconnect from service */ + wsrep_close_client_connections(FALSE); + shutdown_in_progress= 1; + THD* thd(0); + wsrep->disconnect(wsrep); + WSREP_INFO("Service disconnected."); + wsrep_close_threads(thd); /* 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."); + } +#endif // WITH_WSREP clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); mysqld_exit(exit_code); @@ -1932,6 +2040,18 @@ static void clean_up_mutexes() mysql_cond_destroy(&COND_thread_count); mysql_cond_destroy(&COND_thread_cache); mysql_cond_destroy(&COND_flush_thread_cache); +#ifdef WITH_WSREP + (void) mysql_mutex_destroy(&LOCK_wsrep_ready); + (void) mysql_cond_destroy(&COND_wsrep_ready); + (void) mysql_mutex_destroy(&LOCK_wsrep_sst); + (void) mysql_cond_destroy(&COND_wsrep_sst); + (void) mysql_mutex_destroy(&LOCK_wsrep_sst_init); + (void) mysql_cond_destroy(&COND_wsrep_sst_init); + (void) mysql_mutex_destroy(&LOCK_wsrep_rollback); + (void) mysql_cond_destroy(&COND_wsrep_rollback); + (void) mysql_mutex_destroy(&LOCK_wsrep_replaying); + (void) mysql_cond_destroy(&COND_wsrep_replaying); +#endif mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); mysql_mutex_destroy(&LOCK_prepare_ordered); @@ -2350,7 +2470,11 @@ static void network_init(void) @note For the connection that is doing shutdown, this is called twice */ +#ifdef WITH_WSREP +void close_connection(THD *thd, uint sql_errno, bool lock) +#else void close_connection(THD *thd, uint sql_errno) +#endif { DBUG_ENTER("close_connection"); @@ -3477,7 +3601,11 @@ static int init_common_variables() compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 == SQLCOM_END + 8); #endif - +#ifdef WITH_WSREP + /* This is a protection against mutually incompatible option values. */ + if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv)) + return 1; +#endif /* WITH_WSREP */ if (get_options(&remaining_argc, &remaining_argv)) return 1; set_server_version(); @@ -3864,6 +3992,23 @@ static int init_thread_environment() sql_print_error("Can't create thread-keys"); return 1; } +#ifdef WITH_WSREP + mysql_mutex_init(key_LOCK_wsrep_ready, + &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_ready, &COND_wsrep_ready, NULL); + mysql_mutex_init(key_LOCK_wsrep_sst, + &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST); + 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); +#endif return 0; } @@ -4106,7 +4251,12 @@ static int init_server_components() sql_print_warning("You need to use --log-bin to make " "--log-slave-updates work."); } + +#ifdef WITH_WSREP + if (!WSREP_ON && !opt_bin_log && binlog_format_used) +#else if (!opt_bin_log && binlog_format_used) +#endif sql_print_warning("You need to use --log-bin to make " "--binlog-format work."); @@ -4131,6 +4281,31 @@ will be ignored as the --log-bin option is not defined."); } #endif +/* WSREP BEFORE */ +#ifdef WITH_WSREP + // add basedir/bin to PATH to resolve wsrep script names + char* const tmp_path((char*)alloca(strlen(mysql_home) + strlen("/bin") + 1)); + if (tmp_path) + { + strcpy(tmp_path, mysql_home); + strcat(tmp_path, "/bin"); + wsrep_prepend_PATH(tmp_path); + } + else + { + WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); + } + + if (opt_bootstrap) + { + wsrep_provider_init(WSREP_NONE); + if (wsrep_init()) unireg_abort(1); + } + else if (!wsrep_recovery && wsrep_init_first()) + { + wsrep_init_startup(true); + } +#endif /* WITH_WSREP */ if (opt_bin_log) { /* Reports an error and aborts, if the --log-bin's path @@ -4336,11 +4511,30 @@ a file name for --log-bin-index option", opt_binlog_index_name); internal_tmp_table_max_key_segments= myisam_max_key_segments(); #endif +#ifdef WITH_WSREP + if (!opt_bin_log) + { + wsrep_emulate_bin_log= 1; + } +#endif + tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? (TC_LOG *) &mysql_bin_log : +#ifdef WITH_WSREP + (WSREP_ON ? + (TC_LOG *) &tc_log_dummy : + (TC_LOG *) &tc_log_mmap)) : +#else (TC_LOG *) &tc_log_mmap) : - (TC_LOG *) &tc_log_dummy); - +#endif + (TC_LOG *) &tc_log_dummy); +#ifdef WITH_WSREP + WSREP_DEBUG("Initial TC log open: %s", + (tc_log == &mysql_bin_log) ? "binlog" : + (tc_log == &tc_log_mmap) ? "mmap" : + (tc_log == &tc_log_dummy) ? "dummy" : "unknown" + ); +#endif if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) { sql_print_error("Can't init tc log"); @@ -4397,8 +4591,6 @@ a file name for --log-bin-index option", opt_binlog_index_name); init_global_client_stats(); DBUG_RETURN(0); } - - #ifndef EMBEDDED_LIBRARY static void create_shutdown_thread() @@ -4417,6 +4609,397 @@ static void create_shutdown_thread() #endif /* EMBEDDED_LIBRARY */ +#ifdef WITH_WSREP +typedef void (*wsrep_thd_processor_fun)(THD *); + +pthread_handler_t start_wsrep_THD(void *arg) +{ + THD *thd; + wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; + + DBUG_ENTER("start_wsrep_THD"); + if (my_thread_init()) + { + WSREP_ERROR("Could not initialize thread"); + DBUG_RETURN(NULL); + } + + if (!(thd= new THD(true))) + { + DBUG_RETURN(NULL); + } + mysql_mutex_lock(&LOCK_thread_count); + thd->thread_id=thread_id++; + + thd->real_id=pthread_self(); // Keep purify happy + thread_count++; + thread_created++; + threads.append(thd); + + my_net_init(&thd->net,(st_vio*) 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, 1); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + + DBUG_RETURN(NULL); + } + +// + /* + 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, 1); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + delete thd; + + DBUG_RETURN(NULL); + } + + 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->command= COM_SLEEP; + thd->set_time(); + thd->init_for_queries(); + + mysql_mutex_lock(&LOCK_connection_count); + ++connection_count; + mysql_mutex_unlock(&LOCK_connection_count); + + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads++; + mysql_cond_signal(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + processor(thd); + + close_connection(thd, 0, 1); + + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads--; + mysql_cond_signal(&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 + } + DBUG_RETURN(NULL); +} + +void wsrep_create_rollbacker() +{ + if (wsrep_provider && strcasecmp(wsrep_provider, "none")) + { + pthread_t hThread; + /* create rollbacker */ + if (pthread_create( &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_rollback_process)) + WSREP_WARN("Can't create thread to manage wsrep rollback"); + } +} + +void wsrep_create_appliers(long threads) +{ + if (!wsrep_connected) + { + /* 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; + pthread_t hThread; + while (wsrep_threads++ < threads) { + if (pthread_create( + &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_replication_process)) + WSREP_WARN("Can't create thread to manage wsrep replication"); + } +} +/**/ +static bool abort_replicated(THD *thd) +{ + bool ret_code= false; + if (thd->wsrep_query_state== QUERY_COMMITTING) + { + if (wsrep_debug) WSREP_INFO("aborting replicated trx: %lu", thd->real_id); + + (void)wsrep_abort_thd(thd, thd, TRUE); + ret_code= true; + } + return ret_code; +} +/**/ +static inline bool is_client_connection(THD *thd) +{ +#if REMOVE +// REMOVE THIS LATER (lp:777201). Below we had to add an explicit check for +// wsrep_applier since wsrep_exec_mode didn't seem to always work +if (thd->wsrep_applier && thd->wsrep_exec_mode != REPL_RECV) +WSREP_WARN("applier has wsrep_exec_mode = %d", thd->wsrep_exec_mode); + + if ( thd->slave_thread || /* declared as mysql slave */ + thd->system_thread || /* declared as system thread */ + !thd->vio_ok() || /* server internal thread */ + thd->wsrep_exec_mode==REPL_RECV || /* applier or replaying thread */ + thd->wsrep_applier || /* wsrep slave applier */ + !thd->variables.wsrep_on) /* client, but fenced outside wsrep */ + return false; + + return true; +#else + return (thd->wsrep_client_thread && thd->variables.wsrep_on); +#endif /* REMOVE */ +} + +static bool have_client_connections() +{ + THD *tmp; + + I_List_iterator it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION) + { + (void)abort_replicated(tmp); + return true; + } + } + return false; +} + +/* + returns the number of wsrep appliers running. + However, the caller (thd parameter) is not taken in account + */ +static int have_wsrep_appliers(THD *thd) +{ + int ret= 0; + THD *tmp; + + I_List_iterator it(threads); + while ((tmp=it++)) + { + ret+= (tmp != thd && tmp->wsrep_applier); + } + return ret; +} + +static void wsrep_close_thread(THD *thd) +{ + thd->killed= KILL_CONNECTION; + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd)); + if (thd->mysys_var) + { + thd->mysys_var->abort=1; + mysql_mutex_lock(&thd->mysys_var->mutex); + if (thd->mysys_var->current_cond) + { + mysql_mutex_lock(thd->mysys_var->current_mutex); + mysql_cond_broadcast(thd->mysys_var->current_cond); + mysql_mutex_unlock(thd->mysys_var->current_mutex); + } + mysql_mutex_unlock(&thd->mysys_var->mutex); + } +} + +void wsrep_close_client_connections(my_bool wait_to_end) +{ + /* + First signal all threads that it's time to die + */ + + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + bool kill_cached_threads_saved= kill_cached_threads; + kill_cached_threads= true; // prevent future threads caching + mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die + + I_List_iterator it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + /* We skip slave threads & scheduler on this first loop through. */ + if (!is_client_connection(tmp)) + continue; + + /* replicated transactions must be skipped */ + if (abort_replicated(tmp)) + continue; + + WSREP_DEBUG("closing connection %ld", tmp->thread_id); + wsrep_close_thread(tmp); + } + mysql_mutex_unlock(&LOCK_thread_count); + + if (thread_count) + sleep(2); // Give threads time to die + + mysql_mutex_lock(&LOCK_thread_count); + /* + Force remaining threads to die by closing the connection to the client + */ + + I_List_iterator it2(threads); + while ((tmp=it2++)) + { +#ifndef __bsdi__ // Bug in BSDI kernel + if (is_client_connection(tmp) && !abort_replicated(tmp)) + { + WSREP_INFO("SST kill local trx: %ld",tmp->thread_id); + close_connection(tmp,0,0); + } +#endif + } + + DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); + if (wsrep_debug) + WSREP_INFO("waiting for client connections to close: %u", thread_count); + + while (wait_to_end && have_client_connections()) + { + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + DBUG_PRINT("quit",("One thread died (count=%u)", thread_count)); + } + + kill_cached_threads= kill_cached_threads_saved; + + mysql_mutex_unlock(&LOCK_thread_count); + + /* All client connection threads have now been aborted */ +} + +void wsrep_close_applier(THD *thd) +{ + if (wsrep_debug) + WSREP_INFO("closing applier %ld", thd->thread_id); + + wsrep_close_thread(thd); +} + +static void wsrep_close_threads(THD *thd) +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + I_List_iterator it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + /* We skip slave threads & scheduler on this first loop through. */ + if (tmp->wsrep_applier && tmp != thd) + { + if (wsrep_debug) + WSREP_INFO("closing wsrep thread %ld", tmp->thread_id); + wsrep_close_thread (tmp); + + } + } + + mysql_mutex_unlock(&LOCK_thread_count); +} + +void wsrep_wait_appliers_close(THD *thd) +{ + /* Wait for wsrep appliers to gracefully exit */ + mysql_mutex_lock(&LOCK_thread_count); + while (have_wsrep_appliers(thd) > 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. + { + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One applier died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); + /* Now kill remaining wsrep threads: rollbacker */ + wsrep_close_threads (thd); + /* and wait for them to die */ + mysql_mutex_lock(&LOCK_thread_count); + while (have_wsrep_appliers(thd) > 0) + { + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); + + /* All wsrep applier threads have now been aborted. However, if this thread + is also applier, we are still running... + */ +} + +void wsrep_kill_mysql(THD *thd) +{ + if (mysqld_server_started) + { + if (!shutdown_in_progress) + { + WSREP_INFO("starting shutdown"); + kill_mysql(); + } + } + else + { + unireg_abort(1); + } +} +#endif /* WITH_WSREP */ #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) static void handle_connections_methods() @@ -4873,6 +5456,33 @@ int mysqld_main(int argc, char **argv) if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); +/* WSREP AFTER */ +#ifdef WITH_WSREP + wsrep_SE_initialized(); + if (opt_bootstrap) + { + /*! bootstrap wsrep init was taken care of above */ + } + else if (wsrep_recovery) + { + select_thread_in_use= 0; + wsrep_recover(); + unireg_abort(0); + } + else if (wsrep_init_first()) + { + /*! 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 */ + wsrep_sst_continue(); + } + else + { + wsrep_init_startup (false); + } + wsrep_create_appliers(wsrep_slave_threads - 1); +#endif /* WITH_WSREP */ if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work @@ -4929,6 +5539,9 @@ int mysqld_main(int argc, char **argv) #ifndef __WIN__ #ifdef EXTRA_DEBUG2 sql_print_error("Before Lock_thread_count"); +#endif +#ifdef WITH_WSREP + WSREP_DEBUG("Before Lock_thread_count"); #endif mysql_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("Got thread_count mutex")); @@ -5196,6 +5809,9 @@ static void bootstrap(MYSQL_FILE *file) DBUG_ENTER("bootstrap"); THD *thd= new THD; +#ifdef WITH_WSREP + thd->variables.wsrep_on= 0; +#endif thd->bootstrap=1; my_net_init(&thd->net,(st_vio*) 0); thd->max_client_packet_length= thd->net.max_packet; @@ -5320,7 +5936,11 @@ void create_thread_to_handle_connection(THD *thd) my_snprintf(error_message_buff, sizeof(error_message_buff), ER_THD(thd, ER_CANT_CREATE_THREAD), error); net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES ,0); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif /* WITH_WSREP */ mysql_mutex_lock(&LOCK_thread_count); delete thd; mysql_mutex_unlock(&LOCK_thread_count); @@ -5363,7 +5983,11 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); DBUG_PRINT("error",("Too many connections")); + #ifdef WITH_WSREP + close_connection(thd, ER_CON_COUNT_ERROR, 1); +#else close_connection(thd, ER_CON_COUNT_ERROR); +#endif /* WITH_WSREP */ statistic_increment(denied_connections, &LOCK_status); delete thd; DBUG_VOID_RETURN; @@ -5744,7 +6368,11 @@ pthread_handler_t handle_connections_namedpipes(void *arg) if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || my_net_init(&thd->net, thd->net.vio)) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif delete thd; continue; } @@ -5939,7 +6567,11 @@ pthread_handler_t handle_connections_shared_memory(void *arg) event_conn_closed)) || my_net_init(&thd->net, thd->net.vio)) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif errmsg= 0; goto errorconn; } @@ -7021,6 +7653,19 @@ SHOW_VAR status_vars[]= { {"Uptime", (char*) &show_starttime, SHOW_FUNC}, #ifdef ENABLED_PROFILING {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC}, +#endif +#ifdef WITH_WSREP + {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL}, + {"wsrep_ready", (char*) &wsrep_ready, SHOW_BOOL}, + {"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}, + {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG}, + {"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", (char*) &wsrep_show_status, SHOW_FUNC}, #endif {NullS, NullS, SHOW_LONG} }; @@ -7344,6 +7989,10 @@ static int mysql_init_variables(void) if (!(tmpenv = getenv("MY_BASEDIR_VERSION"))) tmpenv = DEFAULT_MYSQL_HOME; (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1); +#endif +#ifdef WITH_WSREP + if (WSREP_ON && wsrep_init_vars()) + return 1; #endif return 0; } @@ -7620,6 +8269,23 @@ mysqld_get_one_option(int optid, case OPT_LOWER_CASE_TABLE_NAMES: lower_case_table_names_used= 1; break; +#ifdef WITH_WSREP + case OPT_WSREP_PROVIDER: + wsrep_provider_init (argument); + break; + case OPT_WSREP_PROVIDER_OPTIONS: + wsrep_provider_options_init (argument); + break; + case OPT_WSREP_CLUSTER_ADDRESS: + wsrep_cluster_address_init (argument); + break; + case OPT_WSREP_START_POSITION: + wsrep_start_position_init (argument); + break; + case OPT_WSREP_SST_AUTH: + wsrep_sst_auth_init (argument); + break; +#endif #if defined(ENABLED_DEBUG_SYNC) case OPT_DEBUG_SYNC_TIMEOUT: /* diff --git a/sql/mysqld.h b/sql/mysqld.h index 988584f779a..99093e1e83b 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -53,7 +53,11 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ some places */ /* Function prototypes */ void kill_mysql(void); +#ifdef WITH_WSREP +void close_connection(THD *thd, uint sql_errno= 0, bool lock=1); +#else void close_connection(THD *thd, uint sql_errno= 0); +#endif void handle_connection_in_main_thread(THD *thd); void create_thread_to_handle_connection(THD *thd); void unlink_thd(THD *thd); @@ -219,6 +223,10 @@ extern pthread_key(MEM_ROOT**,THR_MALLOC); extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool; #endif /* HAVE_MMAP */ +#ifdef WITH_WSREP +extern PSI_mutex_key key_LOCK_wsrep_thd; +extern PSI_cond_key key_COND_wsrep_thd; +#endif /* HAVE_MMAP */ #ifdef HAVE_OPENSSL extern PSI_mutex_key key_LOCK_des_key_file; @@ -406,6 +414,14 @@ enum options_mysqld OPT_WANT_CORE, OPT_ENGINE_CONDITION_PUSHDOWN, OPT_LOG_ERROR, +#ifdef WITH_WSREP + OPT_WSREP_PROVIDER, + OPT_WSREP_PROVIDER_OPTIONS, + OPT_WSREP_CLUSTER_ADDRESS, + OPT_WSREP_START_POSITION, + OPT_WSREP_SST_AUTH, + OPT_WSREP_RECOVER, +#endif OPT_MAX_LONG_DATA_SIZE }; #endif @@ -554,4 +570,5 @@ extern uint internal_tmp_table_max_key_segments; extern uint volatile global_disable_checkpoint; extern my_bool opt_help; + #endif /* MYSQLD_INCLUDED */ diff --git a/sql/protocol.cc b/sql/protocol.cc index 63b945f7078..4a7ea88c402 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -485,6 +485,14 @@ static uchar *net_store_length_fast(uchar *packet, uint length) void Protocol::end_statement() { +#ifdef WITH_WSREP + /*sanity check, can be removed before 1.0 release */ + if (WSREP(thd) && thd->wsrep_conflict_state== REPLAYING) + { + WSREP_ERROR("attempting net_end_statement while replaying"); + return; + } +#endif DBUG_ENTER("Protocol::end_statement"); DBUG_ASSERT(! thd->stmt_da->is_sent); bool error= FALSE; diff --git a/sql/set_var.h b/sql/set_var.h index c074f3f4399..85faaaadd73 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -235,6 +235,9 @@ public: int check(THD *thd); int update(THD *thd); int light_check(THD *thd); +#ifdef WITH_WSREP + int wsrep_store_variable(THD *thd); +#endif }; @@ -315,6 +318,9 @@ extern sys_var *Sys_autocommit_ptr; CHARSET_INFO *get_old_charset_by_name(const char *old_name); +#ifdef WITH_WSREP +int sql_set_wsrep_variables(THD *thd, List *var_list); +#endif int sys_var_init(); int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags); void sys_var_end(void); diff --git a/sql/slave.cc b/sql/slave.cc index 56f9c14703c..833820203b0 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -53,6 +53,9 @@ // Create_file_log_event, // Format_description_log_event +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif #ifdef HAVE_REPLICATION #include "rpl_tblmap.h" @@ -3487,6 +3490,11 @@ pthread_handler_t handle_slave_sql(void *arg) #endif DBUG_ASSERT(rli->sql_thd == thd); +#ifdef WITH_WSREP + thd->wsrep_exec_mode= LOCAL_STATE; + /* synchronize with wsrep replication */ + wsrep_ready_wait (); +#endif DBUG_PRINT("master_info",("log_file_name: %s position: %s", rli->group_master_log_name, llstr(rli->group_master_log_pos,llbuff))); diff --git a/sql/sp.cc b/sql/sp.cc index 29195234a5a..700a8c54fbf 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2277,3 +2277,37 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, thd->lex= old_lex; return sp; } +#ifdef WITH_WSREP +int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len) +{ + String log_query; + sp_head *sp = thd->lex->sphead; + ulong saved_mode= thd->variables.sql_mode; + String retstr(64); + retstr.set_charset(system_charset_info); + + log_query.set_charset(system_charset_info); + + if (sp->m_type == TYPE_ENUM_FUNCTION) + { + sp_returns_type(thd, retstr, sp); + } + + if (!create_string(thd, &log_query, + sp->m_type, + (sp->m_explicit_name ? sp->m_db.str : NULL), + (sp->m_explicit_name ? sp->m_db.length : 0), + sp->m_name.str, sp->m_name.length, + sp->m_params.str, sp->m_params.length, + retstr.c_ptr(), retstr.length(), + sp->m_body.str, sp->m_body.length, + sp->m_chistics, &(thd->lex->definer->user), + &(thd->lex->definer->host), + saved_mode)) + { + WSREP_WARN("SP create string failed: %s", thd->query()); + return 1; + } + return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); +} +#endif /* WITH_WSREP */ diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index c6c02773286..c4468ee8793 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -17,7 +17,9 @@ #include "sql_table.h" // mysql_alter_table, // mysql_exchange_partition #include "sql_alter.h" - +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ bool Alter_table_statement::execute(THD *thd) { LEX *lex= thd->lex; @@ -97,6 +99,17 @@ bool Alter_table_statement::execute(THD *thd) thd->enable_slow_log= opt_log_slow_admin_statements; +#ifdef WITH_WSREP +TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); + + if ((!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, first_table)) && + wsrep_to_isolation_begin(thd, first_table->db, first_table->table_name)) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ result= mysql_alter_table(thd, select_lex->db, lex->name.str, &create_info, first_table, @@ -105,5 +118,7 @@ bool Alter_table_statement::execute(THD *thd) select_lex->order_list.first, lex->ignore, lex->online); +#ifdef WITH_WSREP +#endif /* WITH_WSREP */ DBUG_RETURN(result); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9298d3ccb72..d0404693405 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -60,6 +60,9 @@ #include #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif // WITH_WSREP bool No_such_table_error_handler::handle_condition(THD *, @@ -4218,7 +4221,7 @@ thr_lock_type read_lock_type_for_table(THD *thd, */ bool log_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; ulong binlog_format= thd->variables.binlog_format; - if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) || + if ((log_on == FALSE) || (WSREP_FORMAT(binlog_format) == BINLOG_FORMAT_ROW) || (table_list->table->s->table_category == TABLE_CATEGORY_LOG) || (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || !(is_update_query(prelocking_ctx->sql_command) || @@ -5075,7 +5078,14 @@ restart: } err: +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "exit open_tables()"); + else + thd_proc_info(thd, 0); +#else /* WITH_WSREP */ thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block if (error && *table_to_open) @@ -5518,7 +5528,14 @@ end: trans_rollback_stmt(thd); close_thread_tables(thd); } +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "End opening table"); + else thd_proc_info(thd, 0); +#else /* WITH_WSREP */ + thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ DBUG_RETURN(table); } @@ -5738,7 +5755,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, We can solve these problems in mixed mode by switching to binlogging if at least one updated table is used by sub-statement */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && + if (WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); } @@ -9169,7 +9186,19 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, (e.g. see partitioning code). */ if (!thd_table->needs_reopen()) +#ifdef WITH_WSREP + { + signalled|= mysql_lock_abort_for_thread(thd, thd_table); + if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd)) + { + WSREP_DEBUG("remove_table_from_cache: %llu", + (unsigned long long) thd->real_id); + wsrep_abort_thd((void *)thd, (void *)in_use, FALSE); + } + } +#else signalled|= mysql_lock_abort_for_thread(thd, thd_table); +#endif } mysql_mutex_unlock(&in_use->LOCK_thd_data); } diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in index 63850650ac9..2de475b0a76 100644 --- a/sql/sql_builtin.cc.in +++ b/sql/sql_builtin.cc.in @@ -25,7 +25,11 @@ extern #endif builtin_maria_plugin @mysql_mandatory_plugins@ @mysql_optional_plugins@ - builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin; + builtin_maria_binlog_plugin, +#ifdef WITH_WSREP + builtin_wsrep_plugin@mysql_plugin_defs@, +#endif /* WITH_WSREP */ + builtin_maria_mysql_password_plugin; struct st_maria_plugin *mysql_optional_plugins[]= { @@ -35,5 +39,8 @@ struct st_maria_plugin *mysql_optional_plugins[]= struct st_maria_plugin *mysql_mandatory_plugins[]= { builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin, +#ifdef WITH_WSREP + builtin_wsrep_plugin@mysql_plugin_defs@, +#endif /* WITH_WSREP */ @mysql_mandatory_plugins@ 0 }; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d7d0c8d3f68..5b63201a910 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -62,6 +62,9 @@ #include "debug_sync.h" #include "sql_parse.h" // is_update_query #include "sql_callback.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif #include "sql_connect.h" /* @@ -695,6 +698,137 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, return buffer; } +#ifdef WITH_WSREP +extern "C" int wsrep_on(void *thd) +{ + return (int)(WSREP(((THD*)thd))); +} +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd) +{ + return thd->variables.wsrep_on; +} + +extern "C" bool wsrep_consistency_check(void *thd) +{ + return ((THD*)thd)->wsrep_consistency_check; +} + +extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) +{ + thd->wsrep_exec_mode= mode; +} +extern "C" void wsrep_thd_set_query_state( + THD *thd, enum wsrep_query_state state) +{ + thd->wsrep_query_state= state; +} +extern "C" void wsrep_thd_set_conflict_state( + THD *thd, enum wsrep_conflict_state state) +{ + thd->wsrep_conflict_state= state; +} + + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) +{ + return thd->wsrep_exec_mode; +} +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd) +{ + return thd->wsrep_query_state; +} +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd) +{ + return thd->wsrep_conflict_state; +} + +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd) +{ + return &thd->wsrep_trx_handle; +} + +extern "C"void wsrep_thd_LOCK(THD *thd) +{ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); +} +extern "C"void wsrep_thd_UNLOCK(THD *thd) +{ + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +} +extern "C" time_t wsrep_thd_query_start(THD *thd) +{ + return thd->query_start(); +} +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd) +{ + return thd->wsrep_rand; +} +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd) +{ + return thd->thread_id; +} +extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd) +{ + return thd->wsrep_trx_seqno; +} +extern "C" query_id_t wsrep_thd_query_id(THD *thd) +{ + return thd->query_id; +} +extern "C" char *wsrep_thd_query(THD *thd) +{ + return thd->query(); +} +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) +{ + return thd->wsrep_last_query_id; +} +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) +{ + thd->wsrep_last_query_id= id; +} +extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) +{ + if (signal) + { + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->awake(KILL_QUERY); + mysql_mutex_unlock(&thd->LOCK_thd_data); + } + else + { + mysql_mutex_lock(&LOCK_wsrep_replaying); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } +} + +extern "C" int +wsrep_trx_order_before(void *thd1, void *thd2) +{ + if (((THD*)thd1)->wsrep_trx_seqno < ((THD*)thd2)->wsrep_trx_seqno) { + WSREP_DEBUG("BF conflict, order: %lld %lld\n", + (long long)((THD*)thd1)->wsrep_trx_seqno, + (long long)((THD*)thd2)->wsrep_trx_seqno); + return 1; + } + WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", + (long long)((THD*)thd1)->wsrep_trx_seqno, + (long long)((THD*)thd2)->wsrep_trx_seqno); + return 0; +} +extern "C" int +wsrep_trx_is_aborting(void *thd_ptr) +{ + if (thd_ptr) { + if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) || + (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) { + return 1; + } + } + return 0; +} +#endif /** Implementation of Drop_table_error_handler::handle_condition(). @@ -723,7 +857,11 @@ bool Drop_table_error_handler::handle_condition(THD *thd, } +#ifdef WITH_WSREP +THD::THD(bool is_applier) +#else THD::THD() +#endif :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, /* statement id */ 0), rli_fake(0), @@ -750,6 +888,10 @@ THD::THD() bootstrap(0), derived_tables_processing(FALSE), spcont(NULL), +#ifdef WITH_WSREP + wsrep_applier(is_applier), + wsrep_client_thread(0), +#endif m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) debug_sync_control(0), @@ -849,6 +991,20 @@ THD::THD() command=COM_CONNECT; *scramble= '\0'; +#ifdef WITH_WSREP + mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); + wsrep_trx_handle.trx_id= -1; + wsrep_trx_handle.opaque= NULL; + //wsrep_retry_autocommit= ::wsrep_retry_autocommit; + wsrep_retry_counter= 0; + wsrep_PA_safe = true; + wsrep_seqno_changed= false; + wsrep_retry_query = NULL; + wsrep_retry_query_len = 0; + wsrep_retry_command = COM_CONNECT; + wsrep_consistency_check = false; +#endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -881,6 +1037,13 @@ THD::THD() my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id); substitute_null_with_insert_id = FALSE; thr_lock_info_init(&lock_info); /* safety: will be reset after start */ +#ifdef WITH_WSREP + lock_info.mysql_thd= (void *)this; + lock_info.in_lock_tables= false; +#ifdef WSREP_PROC_INFO + wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */ +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ m_internal_handler= NULL; m_binlog_invoker= FALSE; @@ -1182,7 +1345,19 @@ void THD::init(void) reset_current_stmt_binlog_format_row(); bzero((char *) &status_var, sizeof(status_var)); bzero((char *) &org_status_var, sizeof(org_status_var)); - +#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_seqno= 0; + wsrep_converted_lock_session= false; + wsrep_retry_counter= 0; + wsrep_rli= NULL; + wsrep_PA_safe= true; + wsrep_seqno_changed= false; + wsrep_consistency_check = false; +#endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; else @@ -1376,6 +1551,12 @@ THD::~THD() mysql_mutex_unlock(&LOCK_thd_data); add_to_status(&global_status_var, &status_var); +#ifdef WITH_WSREP + mysql_mutex_lock(&LOCK_wsrep_thd); + mysql_mutex_unlock(&LOCK_wsrep_thd); + mysql_mutex_destroy(&LOCK_wsrep_thd); + if (wsrep_rli) delete wsrep_rli; +#endif /* Close connection */ #ifndef EMBEDDED_LIBRARY if (net.vio) @@ -1790,6 +1971,13 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= FALSE; +#ifdef WITH_WSREP + if (TOTAL_ORDER == wsrep_exec_mode) + { + wsrep_exec_mode = LOCAL_STATE; + } + //wsrep_trx_seqno = 0; +#endif /* WITH_WSREP */ DBUG_VOID_RETURN; } @@ -2205,6 +2393,13 @@ bool sql_exchange::escaped_given(void) bool select_send::send_result_set_metadata(List &list, uint flags) { bool res; +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_retry_query) + { + WSREP_DEBUG("skipping select metadata"); + return FALSE; + } +#endif /* WITH_WSREP */ if (!(res= thd->protocol->send_result_set_metadata(&list, flags))) is_result_set_started= 1; return res; @@ -3911,8 +4106,13 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd) extern "C" int thd_binlog_format(const MYSQL_THD thd) { +#ifdef WITH_WSREP + if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) && + (thd->variables.option_bits & OPTION_BIN_LOG)) +#else if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) - return (int) thd->variables.binlog_format; +#endif + return (int) WSREP_FORMAT(thd->variables.binlog_format); else return BINLOG_FORMAT_UNSPEC; } @@ -4467,7 +4667,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && - !(variables.binlog_format == BINLOG_FORMAT_STMT && + !(WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db))) { /* @@ -4631,7 +4831,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) */ my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0)); } - else if (variables.binlog_format == BINLOG_FORMAT_ROW && + else if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW && sqlcom_can_generate_row_events(this)) { /* @@ -4660,7 +4860,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) else { /* binlog_format = STATEMENT */ - if (variables.binlog_format == BINLOG_FORMAT_STMT) + if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT) { if (lex->is_stmt_row_injection()) { @@ -4677,7 +4877,14 @@ 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 */ +#ifdef WITH_WSREP + if (!WSREP(this) || wsrep_exec_mode == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), ""); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } else if (is_write && (unsafe_flags= lex->get_stmt_unsafe_flags()) != 0) { @@ -4725,7 +4932,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) "and binlog_filter->db_ok(db) = %d", mysql_bin_log.is_open(), (variables.option_bits & OPTION_BIN_LOG), - variables.binlog_format, + WSREP_FORMAT(variables.binlog_format), binlog_filter->db_ok(db))); #endif @@ -4979,7 +5186,13 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) || + mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif /* Pack records into format for transfer. We are allocating more @@ -5009,7 +5222,13 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, const uchar *before_record, const uchar *after_record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif size_t const before_maxlen = max_row_length(table, before_record); size_t const after_maxlen = max_row_length(table, after_record); @@ -5054,7 +5273,13 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif /* Pack records into format for transfer. We are allocating more @@ -5085,7 +5310,11 @@ int THD::binlog_remove_pending_rows_event(bool clear_maps, { DBUG_ENTER("THD::binlog_remove_pending_rows_event"); +#ifdef WITH_WSREP + if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())) +#else if (!mysql_bin_log.is_open()) +#endif DBUG_RETURN(0); mysql_bin_log.remove_pending_rows_event(this, is_transactional); @@ -5104,7 +5333,11 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional) mode: it might be the case that we left row-based mode before flushing anything (e.g., if we have explicitly locked tables). */ +#ifdef WITH_WSREP + if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())) +#else if (!mysql_bin_log.is_open()) +#endif DBUG_RETURN(0); /* @@ -5224,8 +5457,12 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, DBUG_ENTER("THD::binlog_query"); DBUG_PRINT("enter", ("qtype: %s query: '%-.*s'", show_query_type(qtype), (int) query_len, query_arg)); +#ifdef WITH_WSREP + DBUG_ASSERT(query_arg && (WSREP_EMULATE_BINLOG(this) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(query_arg && mysql_bin_log.is_open()); - +#endif /* If we are not in prelocked mode, mysql_unlock_tables() will be called after this binlog_query(), so we have to flush the pending diff --git a/sql/sql_class.h b/sql/sql_class.h index c6c46975076..96a67fccaef 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -20,6 +20,32 @@ #define SQL_CLASS_INCLUDED /* Classes in mysql */ +#ifdef WITH_WSREP +#include "../wsrep/wsrep_api.h" +//#include "wsrep_mysqld.h" + enum wsrep_exec_mode { + LOCAL_STATE, + REPL_RECV, + TOTAL_ORDER, + LOCAL_COMMIT, + }; + enum wsrep_query_state { + QUERY_IDLE, + QUERY_EXEC, + QUERY_COMMITTING, + QUERY_EXITING, + QUERY_ROLLINGBACK, + }; + enum wsrep_conflict_state { + NO_CONFLICT, + MUST_ABORT, + ABORTING, + ABORTED, + MUST_REPLAY, + REPLAYING, + RETRY_AUTOCOMMIT, + }; +#endif #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ @@ -45,6 +71,15 @@ THR_LOCK_INFO */ +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +struct wsrep_thd_shadow { + ulonglong options; + enum wsrep_exec_mode wsrep_exec_mode; + Vio *vio; + ulong tx_isolation; +}; +#endif class Reprepare_observer; class Relay_log_info; @@ -572,6 +607,11 @@ typedef struct system_variables ulong wt_timeout_short, wt_deadlock_search_depth_short; ulong wt_timeout_long, wt_deadlock_search_depth_long; +#ifdef WITH_WSREP + my_bool wsrep_on; + my_bool wsrep_causal_reads; + ulong wsrep_retry_autocommit; +#endif double long_query_time_double; } SV; @@ -965,6 +1005,9 @@ struct st_savepoint { /** State of metadata locks before this savepoint was set. */ MDL_savepoint mdl_savepoint; }; +#ifdef WITH_WSREP +void wsrep_cleanup_transaction(THD *thd); // THD.transactions.cleanup calls it +#endif enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY}; extern const char *xa_state_names[]; @@ -1781,7 +1824,7 @@ public: int is_current_stmt_binlog_format_row() const { DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || current_stmt_binlog_format == BINLOG_FORMAT_ROW); - return current_stmt_binlog_format == BINLOG_FORMAT_ROW; + return (WSREP_FORMAT((ulong)current_stmt_binlog_format) == BINLOG_FORMAT_ROW); } private: @@ -1839,7 +1882,11 @@ public: */ CHANGED_TABLE_LIST* changed_tables; MEM_ROOT mem_root; // Transaction-life memory allocation pool +#ifdef WITH_WSREP + void cleanup(THD *thd) +#else void cleanup() +#endif { changed_tables= 0; savepoints= 0; @@ -1852,6 +1899,11 @@ public: if (!xid_state.rm_error) xid_state.xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); +#ifdef WITH_WSREP + // Todo: convert into a plugin method + // wsrep's post-commit. LOCAL_COMMIT designates wsrep's commit was ok + if (WSREP(thd)) wsrep_cleanup_transaction(thd); +#endif /* WITH_WSREP */ } my_bool is_active() { @@ -2314,6 +2366,31 @@ public: query_id_t first_query_id; } binlog_evt_union; +#ifdef WITH_WSREP + const bool wsrep_applier; /* dedicated slave applier thread */ + bool wsrep_client_thread; /* to identify client threads*/ + 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; + mysql_mutex_t LOCK_wsrep_thd; + mysql_cond_t COND_wsrep_thd; + wsrep_seqno_t wsrep_trx_seqno; + uint32 wsrep_rand; + Relay_log_info* wsrep_rli; + bool wsrep_converted_lock_session; + wsrep_trx_handle_t wsrep_trx_handle; + bool wsrep_seqno_changed; +#ifdef WSREP_PROC_INFO + char wsrep_info[128]; /* string for dynamic proc info */ +#endif /* WSREP_PROC_INFO */ + ulong wsrep_retry_counter; // of autocommit + bool wsrep_PA_safe; + char* wsrep_retry_query; + size_t wsrep_retry_query_len; + enum enum_server_command wsrep_retry_command; + bool wsrep_consistency_check; +#endif /* WITH_WSREP */ /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -2345,7 +2422,11 @@ public: /* Debug Sync facility. See debug_sync.cc. */ struct st_debug_sync_control *debug_sync_control; #endif /* defined(ENABLED_DEBUG_SYNC) */ +#ifdef WITH_WSREP + THD(bool is_applier = false); +#else THD(); +#endif ~THD(); void init(void); @@ -2741,7 +2822,7 @@ public: tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ - if ((variables.binlog_format == BINLOG_FORMAT_MIXED) && + if ((WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) set_current_stmt_binlog_format_row(); @@ -2783,7 +2864,7 @@ public: show_system_thread(system_thread))); if (in_sub_stmt == 0) { - if (variables.binlog_format == BINLOG_FORMAT_ROW) + if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW) set_current_stmt_binlog_format_row(); else if (temporary_tables == NULL) clear_current_stmt_binlog_format_row(); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7157b1b109f..e96068484eb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -44,6 +44,9 @@ HASH global_index_stats; extern mysql_mutex_t LOCK_global_user_client_stats; extern mysql_mutex_t LOCK_global_table_stats; extern mysql_mutex_t LOCK_global_index_stats; +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* Get structure for logging connection data for the current user @@ -97,6 +100,9 @@ int get_or_create_user_conn(THD *thd, const char *user, } thd->user_connect=uc; uc->connections++; +#ifdef WITH_WSREP + thd->wsrep_client_thread= 1; +#endif /* WITH_WSREP */ end: mysql_mutex_unlock(&LOCK_user_conn); return return_val; @@ -977,7 +983,11 @@ bool setup_connection_thread_globals(THD *thd) { if (thd->store_globals()) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return 1; // Error @@ -1050,6 +1060,17 @@ bool login_connection(THD *thd) 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: %lu, code: %d", + thd->thread_id, rcode); + } + } + thd->wsrep_client_thread= 0; +#endif plugin_thdvar_cleanup(thd); if (thd->user_connect) @@ -1205,7 +1226,11 @@ void do_handle_one_connection(THD *thd_arg) if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return; @@ -1254,9 +1279,21 @@ void do_handle_one_connection(THD *thd_arg) break; } end_connection(thd); - + +#ifdef WITH_WSREP + if (WSREP(thd)) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXITING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif end_thread: +#ifdef WITH_WSREP + close_connection(thd, 0, 1); +#else close_connection(thd); +#endif if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ff88bf7c0f8..7fc623daf88 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -410,7 +410,11 @@ cleanup: /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error < 0) @@ -861,7 +865,11 @@ void multi_delete::abort_result_set() /* there is only side effects; to binlog with the error */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); /* possible error of writing binary log is ignored deliberately */ @@ -1037,7 +1045,11 @@ bool multi_delete::send_eof() } if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (local_error == 0) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 54f94ce78c1..a4eb1e8996f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1019,7 +1019,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->transaction.stmt.modified_non_trans_table || was_insert_delayed) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error <= 0) @@ -3113,6 +3117,11 @@ bool Delayed_insert::handle_inserts(void) mysql_cond_broadcast(&cond_client); // If waiting clients } } +#ifdef WITH_WSREP + if (WSREP((&thd))) + thd_proc_info(&thd, "insert done"); + else +#endif /* WITH_WSREP */ thd_proc_info(&thd, 0); mysql_mutex_unlock(&mutex); @@ -3597,8 +3606,13 @@ bool select_insert::send_eof() events are in the transaction cache and will be written when ha_autocommit_or_rollback() is issued below. */ +#ifdef WITH_WSREP + if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) && + (!error || thd->transaction.stmt.modified_non_trans_table)) +#else if (mysql_bin_log.is_open() && (!error || thd->transaction.stmt.modified_non_trans_table)) +#endif { int errcode= 0; if (!error) @@ -3681,7 +3695,11 @@ void select_insert::abort_result_set() { if (!can_rollback_data()) thd->transaction.all.modified_non_trans_table= TRUE; +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); /* error of writing binary log is ignored */ @@ -4072,7 +4090,11 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* show_database */ TRUE); DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); result= thd->binlog_query(THD::STMT_QUERY_TYPE, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b2dfae5ded4..070bcdfcfd4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1548,6 +1548,17 @@ int lex_one_token(void *arg, void *yythd) } else { +#ifdef WITH_WSREP + if (version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE) + { + WSREP_DEBUG("consistency check: %s", thd->query()); + thd->wsrep_consistency_check= TRUE; + lip->yySkipn(5); + lip->set_echo(TRUE); + state=MY_LEX_START; + break; /* Do not treat contents as a comment. */ + } +#endif /* WITH_WSREP */ /* Patch and skip the conditional comment to avoid it being propagated infinitely (eg. to a slave). diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e0b2acd199d..a955b434319 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -103,6 +103,24 @@ #include "../storage/maria/ha_maria.h" #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#include "rpl_rli.h" + +extern Format_description_log_event *wsrep_format_desc; +#define WSREP_MYSQL_DB (char *)"mysql" + +#define WSREP_TO_ISOLATION_BEGIN(db_, table_) \ + if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_)) goto error; + +#define WSREP_TO_ISOLATION_END \ + if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \ + wsrep_to_isolation_end(thd); + +#else +#define WSREP_TO_ISOLATION_BEGIN(db_, table_) +#define WSREP_TO_ISOLATION_END +#endif /* WITH_WSREP */ /** @defgroup Runtime_Environment Runtime Environment @{ @@ -436,6 +454,13 @@ bool is_log_table_write_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0; } +#ifdef WITH_WSREP +bool is_show_query(enum enum_sql_command command) +{ + DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); + return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0; +} +#endif void execute_init_command(THD *thd, LEX_STRING *init_command, mysql_rwlock_t *var_lock) { @@ -617,7 +642,11 @@ void do_handle_bootstrap(THD *thd) if (my_thread_init() || thd->store_globals()) { #ifndef EMBEDDED_LIBRARY +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif #endif thd->fatal_error(); goto end; @@ -692,7 +721,26 @@ bool do_command(THD *thd) NET *net= &thd->net; enum enum_server_command command; DBUG_ENTER("do_command"); +#ifdef WITH_WSREP + if (WSREP(thd)) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_IDLE; + if (thd->wsrep_conflict_state==MUST_ABORT) + { + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* indicator of uninitialized lex => normal flow of errors handling (see my_message_sql) @@ -738,11 +786,57 @@ bool do_command(THD *thd) */ DEBUG_SYNC(thd, "before_do_command_net_read"); +#ifdef WITH_WSREP + if (WSREP(thd)) { + packet_length= my_net_read(net); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + /* 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_wsrep_thd); + my_sleep(1000); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + } + thd->store_globals(); + } + else if (thd->wsrep_conflict_state == ABORTED) + { + thd->store_globals(); + } + + thd->wsrep_query_state= QUERY_EXEC; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + if ((WSREP(thd) && packet_length == packet_error) || + (!WSREP(thd) && (packet_length= my_net_read(net)) == packet_error)) +#else if ((packet_length= my_net_read(net)) == packet_error) +#endif { DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, vio_description(net->vio))); +#ifdef WITH_WSREP + if (WSREP(thd)) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) + { + DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id)); + thd->wsrep_conflict_state= ABORTING; + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* Check if we can continue without closing the connection */ @@ -788,12 +882,54 @@ bool do_command(THD *thd) vio_description(net->vio), command, command_name[command].str)); +#ifdef WITH_WSREP + if (WSREP(thd)) { + /* + * 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->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && + command != COM_QUERY && + command != COM_PING && + command != COM_QUIT && + command != COM_PROCESS_INFO && + command != COM_PROCESS_KILL && + command != COM_SET_OPTION && + command != COM_SHUTDOWN && + command != COM_SLEEP && + command != COM_STATISTICS && + command != COM_TIME && + command != COM_END + ) { + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + "WSREP has not yet prepared node for application use"); + thd->protocol->end_statement(); + return_value= FALSE; + goto out; + } + } +#endif /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); DBUG_ASSERT(packet_length); return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); - +#ifdef WITH_WSREP + if (WSREP(thd)) { + while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + return_value= dispatch_command(command, thd, thd->wsrep_retry_query, + thd->wsrep_retry_query_len); + } + } + if (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 out: DBUG_RETURN(return_value); } @@ -867,6 +1003,34 @@ static my_bool deny_updates_if_read_only_option(THD *thd, 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->command; + thd->wsrep_retry_query_len = thd->query_length(); + thd->wsrep_retry_query = (char *)my_malloc( + thd->wsrep_retry_query_len + 1, MYF(0)); + thd->wsrep_retry_command = thd->command; + strcpy(thd->wsrep_retry_query, thd->query()); + thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; +} +#endif /* WITH_WSREP */ /** Perform one connection-level (COM_XXXX) command. @@ -896,6 +1060,50 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_ENTER("dispatch_command"); DBUG_PRINT("info", ("command: %d", command)); +#ifdef WITH_WSREP + bool is_autocommit= false; + + if (WSREP(thd)) { + if (!thd->in_multi_stmt_transaction_mode()) + { + thd->wsrep_PA_safe= true; + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + thd->wsrep_conflict_state= NO_CONFLICT; + } + + 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); + + if (thd->wsrep_conflict_state== MUST_ABORT) + { + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; + } + if (thd->wsrep_conflict_state== ABORTED) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + WSREP_DEBUG("Deadlock error for: %s", thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + thd->killed= NOT_KILLED; + thd->mysys_var->abort= 0; + goto dispatch_end; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* WITH_WSREP */ #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); #endif @@ -1104,7 +1312,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); +#ifdef WITH_WSREP + if (!WSREP(thd)) + thd->set_time(); /* Reset the query start time. */ +#else thd->set_time(); /* Reset the query start time. */ +#endif parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); @@ -1422,6 +1635,156 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; } +#ifdef WITH_WSREP + dispatch_end: + + if (WSREP(thd)) { + /* wsrep BF abort in query exec phase */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + ha_rollback_trans(thd, 0); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + thd->transaction.stmt.reset(); + WSREP_DEBUG("abort in exec query state, avoiding autocommit"); + goto wsrep_must_abort; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* WITH_WSREP */ + +#ifdef WITH_WSREP + wsrep_must_abort: + if (WSREP(thd)) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + WSREP_DEBUG("in dispatch_command, aborting %s", + (thd->query()) ? thd->query() : "void"); + trans_rollback(thd); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + + if (thd->get_binlog_table_maps()) { + thd->clear_binlog_table_maps(); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) { + if (thd->wsrep_exec_mode!= REPL_RECV) { + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); + + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + + thd_proc_info(thd, "wsrep replaying trx"); + WSREP_DEBUG("replay trx: %s %lld", + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + int rcode = wsrep->replay_trx(wsrep, + &thd->wsrep_trx_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_wsrep_thd); + + switch (rcode) { + case WSREP_OK: + thd->wsrep_conflict_state= NO_CONFLICT; + wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); + WSREP_DEBUG("trx_replay successful for: %ld %llu", + thd->thread_id, (long long)thd->real_id); + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + } + /* setting error code for BF aborted trxs */ + if (thd->wsrep_conflict_state == ABORTED) + { + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + if (is_autocommit && + (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) + { + WSREP_DEBUG("wsrep retrying AC query: %s", + (thd->query()) ? thd->query() : "void"); + thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; + thd->wsrep_retry_counter++; // grow + wsrep_copy_query(thd); + } + else + { + WSREP_DEBUG("BF aborted, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + thd->killed= NOT_KILLED; + thd->wsrep_conflict_state= NO_CONFLICT; + thd->wsrep_retry_counter= 0; // reset + } + } + else + { + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok + } + if ((thd->wsrep_conflict_state != REPLAYING) && + (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) { + + thd->update_server_status(); + thd->protocol->end_statement(); + query_cache_end_of_result(thd); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + } else { /* if (WSREP(thd))... */ + +#endif /* WITH_WSREP */ DBUG_ASSERT(thd->derived_tables == NULL && (thd->open_tables == NULL || (thd->locked_tables_mode == LTM_LOCK_TABLES))); @@ -1430,6 +1793,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->update_server_status(); thd->protocol->end_statement(); query_cache_end_of_result(thd); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ if (!thd->is_error() && !thd->killed_errno()) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); @@ -1446,7 +1812,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->reset_query(); thd->command=COM_SLEEP; dec_thread_running(); +#ifdef WITH_WSREP + if (WSREP(thd)) { + thd_proc_info(thd, "sleeping"); + } else { +#endif /* WITH_WSREP */ thd_proc_info(thd, 0); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ + thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); @@ -2091,7 +2466,45 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION } /* endif unlikely slave */ #endif +#ifdef WITH_WSREP + if (WSREP(thd)) { + /* + change LOCK TABLE WRITE to transaction + */ + if (lex->sql_command== SQLCOM_LOCK_TABLES && wsrep_convert_LOCK_to_trx) + { + for (TABLE_LIST *table= all_tables; table; table= table->next_global) + { + if (table->lock_type >= TL_WRITE_ALLOW_WRITE) + { + lex->sql_command= SQLCOM_BEGIN; + thd->wsrep_converted_lock_session= true; + break; + } + } + } + if (lex->sql_command== SQLCOM_UNLOCK_TABLES && + thd->wsrep_converted_lock_session) + { + thd->wsrep_converted_lock_session= false; + lex->sql_command= SQLCOM_COMMIT; + lex->tx_release= TVL_NO; + } + /* + * bail out if DB snapshot has not been installed. We however, + * allow SET and SHOW queries + */ + if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && + lex->sql_command != SQLCOM_SET_OPTION && + !is_show_query(lex->sql_command)) + { + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + "WSREP has not yet prepared node for application use"); + goto error; + } + } +#endif /* WITH_WSREP */ status_var_increment(thd->status_var.com_stat[lex->sql_command]); thd->progress.report_to_client= test(sql_command_flags[lex->sql_command] & CF_REPORT_PROGRESS); @@ -2134,6 +2547,9 @@ mysql_execute_command(THD *thd) #endif case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))) goto error; @@ -2141,6 +2557,9 @@ mysql_execute_command(THD *thd) break; case SQLCOM_SHOW_STATUS: { +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ execute_show_status(thd, all_tables); break; } @@ -2152,17 +2571,27 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_PLUGINS: case SQLCOM_SHOW_FIELDS: case SQLCOM_SHOW_KEYS: +#ifndef WITH_WSREP case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_PROFILE: +#endif /* WITH_WSREP */ case SQLCOM_SHOW_CLIENT_STATS: case SQLCOM_SHOW_USER_STATS: case SQLCOM_SHOW_TABLE_STATS: case SQLCOM_SHOW_INDEX_STATS: case SQLCOM_SELECT: - { +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + case SQLCOM_SHOW_VARIABLES: + case SQLCOM_SHOW_CHARSETS: + case SQLCOM_SHOW_COLLATIONS: + case SQLCOM_SHOW_STORAGE_ENGINES: + case SQLCOM_SHOW_PROFILE: +#endif /* WITH_WSREP */ + { thd->status_var.last_query_cost= 0.0; /* @@ -2472,7 +2901,7 @@ case SQLCOM_PREPARE: */ if (thd->query_name_consts && mysql_bin_log.is_open() && - thd->variables.binlog_format == BINLOG_FORMAT_STMT && + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT && !mysql_bin_log.is_query_in_union(thd, thd->query_id)) { List_iterator_fast it(select_lex->item_list); @@ -2576,6 +3005,11 @@ case SQLCOM_PREPARE: if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->variables.option_bits|= OPTION_KEEP_LOG; /* regular create */ +#ifdef WITH_WSREP + if (!thd->is_current_stmt_binlog_format_row() || + !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name) +#endif /* WITH_WSREP */ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) { /* CREATE TABLE ... LIKE ... */ @@ -2617,6 +3051,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_one_table_access(thd, INDEX_ACL, all_tables)) goto error; /* purecov: inspected */ + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name) /* Currently CREATE INDEX or DROP INDEX cause a full table rebuild and thus classify as slow administrative statements just like @@ -2674,6 +3109,7 @@ end_with_restore_list: case SQLCOM_RENAME_TABLE: { + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name) if (execute_rename_table(thd, first_table, all_tables)) goto error; break; @@ -2701,6 +3137,10 @@ end_with_restore_list: goto error; #else { +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ + /* Access check: SHOW CREATE TABLE require any privileges on the table level (ie @@ -2756,6 +3196,10 @@ end_with_restore_list: case SQLCOM_CHECKSUM: { DBUG_ASSERT(first_table == all_tables && first_table != 0); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ + if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ @@ -2950,6 +3394,14 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) break; +#ifdef WITH_WSREP + if (lex->sql_command == SQLCOM_INSERT_SELECT && + thd->wsrep_consistency_check) + { + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name); + } + +#endif /* INSERT...SELECT...ON DUPLICATE KEY UPDATE/REPLACE SELECT/ INSERT...IGNORE...SELECT can be unsafe, unless ORDER BY PRIMARY KEY @@ -3113,6 +3565,17 @@ end_with_restore_list: /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ thd->variables.option_bits|= OPTION_KEEP_LOG; } +#ifdef WITH_WSREP + for (TABLE_LIST *table= all_tables; table; table= table->next_global) + { + if (!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, table)) + { + WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name); + break; + } + } +#endif /* WITH_WSREP */ /* DDL and binlog write order are protected by metadata locks. */ res= mysql_rm_table(thd, first_table, lex->drop_if_exists, lex->drop_temporary); @@ -3156,7 +3619,6 @@ end_with_restore_list: if (!mysql_change_db(thd, &db_str, FALSE)) my_ok(thd); - break; } @@ -3299,6 +3761,7 @@ end_with_restore_list: #endif if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL) res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name.str), &create_info, 0); break; @@ -3328,6 +3791,7 @@ end_with_restore_list: #endif if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL) res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } @@ -3356,6 +3820,7 @@ end_with_restore_list: res= 1; break; } + WSREP_TO_ISOLATION_BEGIN(db->str, NULL) res= mysql_upgrade_db(thd, db); if (!res) my_ok(thd); @@ -3388,6 +3853,7 @@ end_with_restore_list: #endif if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(db->str, NULL) res= mysql_alter_db(thd, db->str, &create_info); break; } @@ -3420,6 +3886,7 @@ end_with_restore_list: if (res) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: { @@ -3454,6 +3921,7 @@ end_with_restore_list: lex->spname->m_name); break; case SQLCOM_DROP_EVENT: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (!(res= Events::drop_event(thd, lex->spname->m_db, lex->spname->m_name, lex->drop_if_exists))) @@ -3468,6 +3936,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0)) break; #ifdef HAVE_DLOPEN + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (!(res = mysql_create_function(thd, &lex->udf))) my_ok(thd); #else @@ -3482,6 +3951,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) /* Conditionally writes to binlog */ if (!(res= mysql_create_user(thd, lex->users_list))) my_ok(thd); @@ -3493,6 +3963,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (!(res= mysql_drop_user(thd, lex->users_list))) my_ok(thd); break; @@ -3503,6 +3974,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (!(res= mysql_rename_user(thd, lex->users_list))) my_ok(thd); break; @@ -3517,6 +3989,7 @@ end_with_restore_list: thd->binlog_invoker(); /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (!(res = mysql_revoke_all(thd, lex->users_list))) my_ok(thd); break; @@ -3583,6 +4056,7 @@ end_with_restore_list: lex->type == TYPE_ENUM_PROCEDURE, 0)) goto error; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= mysql_routine_grant(thd, all_tables, lex->type == TYPE_ENUM_PROCEDURE, lex->users_list, grants, @@ -3596,6 +4070,7 @@ end_with_restore_list: all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= mysql_table_grant(thd, all_tables, lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE); @@ -3611,6 +4086,7 @@ end_with_restore_list: } else { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) /* Conditionally writes to binlog */ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, lex->sql_command == SQLCOM_REVOKE, @@ -3749,9 +4225,17 @@ end_with_restore_list: able to open it (with SQLCOM_HA_OPEN) in the first place. */ unit->set_limit(select_lex); +#ifdef WITH_WSREP + { char* tmp_info= NULL; + if (WSREP(thd)) tmp_info = (char *)thd_proc_info(thd, "mysql_ha_read()"); +#endif /* WITH_WSREP */ res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, lex->insert_list, lex->ha_rkey_mode, select_lex->where, unit->select_limit_cnt, unit->offset_limit_cnt); +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp_info); + } +#endif /* WITH_WSREP */ break; case SQLCOM_BEGIN: @@ -3819,8 +4303,20 @@ end_with_restore_list: /* Disconnect the current client connection. */ if (tx_release) thd->killed= KILL_CONNECTION; - my_ok(thd); - break; + #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 */ + break; } case SQLCOM_RELEASE_SAVEPOINT: if (trans_release_savepoint(thd, lex->ident)) @@ -3888,6 +4384,7 @@ end_with_restore_list: if (sp_process_definer(thd)) goto create_sp_error; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= (sp_result= sp_create_routine(thd, lex->sphead->m_type, lex->sphead)); switch (sp_result) { case SP_OK: { @@ -4099,6 +4596,7 @@ create_sp_error: already puts on CREATE FUNCTION. */ /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) sp_result= sp_update_routine(thd, type, lex->spname, &lex->sp_chistics); switch (sp_result) { @@ -4170,6 +4668,7 @@ create_sp_error: if (check_routine_access(thd, ALTER_PROC_ACL, db, name, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) goto error; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) /* Conditionally writes to binlog */ sp_result= sp_drop_routine(thd, type, lex->spname); @@ -4287,6 +4786,7 @@ create_sp_error: Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands as specified through the thd->lex->create_view_mode flag. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= mysql_create_view(thd, first_table, thd->lex->create_view_mode); break; } @@ -4295,12 +4795,14 @@ create_sp_error: if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(NULL, NULL) res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); break; } case SQLCOM_CREATE_TRIGGER: { /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 1); break; @@ -4308,6 +4810,7 @@ create_sp_error: case SQLCOM_DROP_TRIGGER: { /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 0); break; } @@ -4358,11 +4861,13 @@ create_sp_error: my_ok(thd); break; case SQLCOM_INSTALL_PLUGIN: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (! (res= mysql_install_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); break; case SQLCOM_UNINSTALL_PLUGIN: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); @@ -4519,6 +5024,10 @@ finish: /* Free tables */ thd_proc_info(thd, "closing tables"); close_thread_tables(thd); +#ifdef WITH_WSREP + WSREP_TO_ISOLATION_END + thd->wsrep_consistency_check= FALSE; +#endif /* WITH_WSREP */ thd_proc_info(thd, 0); #ifndef DBUG_OFF @@ -5429,6 +5938,21 @@ void THD::reset_for_next_command(bool calculate_userstat) thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; +#ifdef WITH_WSREP + if (WSREP(thd)) { + if (wsrep_auto_increment_control) + { + if (thd->variables.auto_increment_offset != + global_system_variables.auto_increment_offset) + thd->variables.auto_increment_offset= + global_system_variables.auto_increment_offset; + if (thd->variables.auto_increment_increment != + global_system_variables.auto_increment_increment) + thd->variables.auto_increment_increment= + global_system_variables.auto_increment_increment; + } + } +#endif /* WITH_WSREP */ thd->query_start_used= 0; thd->query_start_sec_part_used= 0; thd->is_fatal_error= thd->time_zone_used= 0; @@ -7381,6 +7905,545 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } +#ifdef WITH_WSREP +static enum wsrep_status wsrep_apply_sql( + THD *thd, const char *sql, size_t sql_len, time_t timeval, uint32 randseed) +{ + int error; + enum wsrep_status ret_code= WSREP_OK; + + DBUG_ENTER("wsrep_bf_execute_cb"); + thd->wsrep_exec_mode= REPL_RECV; + thd->net.vio= 0; + thd->start_time= timeval; + thd->wsrep_rand= randseed; + + thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; + + DBUG_PRINT("wsrep", ("SQL: %s", sql)); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + /* preserve replaying mode */ + if (thd->wsrep_conflict_state!= REPLAYING) + thd->wsrep_conflict_state= NO_CONFLICT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if ((error= dispatch_command(COM_QUERY, thd, (char*)sql, sql_len))) { + WSREP_WARN("BF SQL apply failed: %d, %lld", + thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); + DBUG_RETURN(WSREP_FATAL); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state!= NO_CONFLICT && + thd->wsrep_conflict_state!= REPLAYING) { + ret_code= WSREP_FATAL; + WSREP_DEBUG("BF thd ending, with: %d, %lld", + thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + assert(thd->wsrep_exec_mode== REPL_RECV); + DBUG_RETURN(ret_code); +} + +void wsrep_write_rbr_buf( + THD *thd, const void* rbr_buf, size_t buf_len) +{ + char filename[PATH_MAX]= {0}; + int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", + wsrep_data_home_dir, thd->thread_id, + (long long)thd->wsrep_trx_seqno); + if (len >= PATH_MAX) + { + WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); + return; + } + + FILE *of= fopen(filename, "wb"); + if (of) + { + fwrite (rbr_buf, buf_len, 1, of); + fclose(of); + } + else + { + WSREP_ERROR("Failed to open file '%s': %d (%s)", + filename, errno, strerror(errno)); + } +} + +static inline wsrep_status_t wsrep_apply_rbr( + THD *thd, const uchar *rbr_buf, size_t buf_len) +{ + char *buf= (char *)rbr_buf; + int rcode= 0; + int event= 1; + + DBUG_ENTER("wsrep_apply_rbr"); + + if (thd->killed == KILL_CONNECTION) + { + WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", + (long long) thd->wsrep_trx_seqno); + DBUG_RETURN(WSREP_FATAL); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + if (thd->wsrep_conflict_state!= REPLAYING) + thd->wsrep_conflict_state= NO_CONFLICT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", + (long long) thd->wsrep_trx_seqno); + + if ((rcode= trans_begin(thd))) + WSREP_WARN("begin for rbr apply failed: %lld, code: %d", + (long long) thd->wsrep_trx_seqno, rcode); + + while(buf_len) + { + int exec_res; + int error = 0; + Log_event* ev= wsrep_read_log_event(&buf, &buf_len, wsrep_format_desc); + + switch (ev->get_type_code()) { + case WRITE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case DELETE_ROWS_EVENT: + DBUG_ASSERT(buf_len != 0 || + ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)); + break; + default: + break; + } + + thd->server_id = ev->server_id; // use the original server id for logging + thd->set_time(); // time the query + wsrep_xid_init(&thd->transaction.xid_state.xid, + wsrep_cluster_uuid(), + thd->wsrep_trx_seqno); + thd->lex->current_select= 0; + if (!ev->when) + ev->when = time(NULL); + ev->thd = thd; + exec_res = ev->apply_event(thd->wsrep_rli); + DBUG_PRINT("info", ("exec_event result: %d", exec_res)); + + if (exec_res) + { + WSREP_WARN("RBR event %d %s apply warning: %d, %lld", + event, ev->get_type_str(), exec_res, (long long) thd->wsrep_trx_seqno); + rcode= exec_res; + /* stop processing for the first error */ + delete ev; + goto error; + } + 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)thd->wsrep_trx_seqno); + + if (thd->wsrep_conflict_state == MUST_ABORT) { + WSREP_WARN("RBR event apply failed, rolling back: %lld", + (long long) thd->wsrep_trx_seqno); + 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_FATAL); + } + + if (ev->get_type_code() != TABLE_MAP_EVENT && + ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)) + { + // TODO: combine with commit on higher level common for the query ws + + thd->wsrep_rli->cleanup_context(thd, 0); + + if (error == 0) + { + thd->clear_error(); + } + else + WSREP_ERROR("Error in %s event: commit of row events failed: %lld", + ev->get_type_str(), (long long)thd->wsrep_trx_seqno); + } + delete ev; + } + + error: + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_IDLE; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + assert(thd->wsrep_exec_mode== REPL_RECV); + + if (thd->killed == KILL_CONNECTION) + WSREP_INFO("applier aborted: %lld", (long long)thd->wsrep_trx_seqno); + + if (rcode) DBUG_RETURN(WSREP_FATAL); + DBUG_RETURN(WSREP_OK); +} + +wsrep_status_t wsrep_apply_cb(void* const ctx, + const void* const buf, size_t const buf_len, + wsrep_seqno_t const global_seqno) +{ + THD* const thd((THD*)ctx); + + thd->wsrep_trx_seqno= global_seqno; + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "applying write set %lld: %p, %zu", + (long long)thd->wsrep_trx_seqno, buf, buf_len); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "applying write set"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_rbr(thd, (const uchar*)buf, buf_len)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "applied write set %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "applied write set"); +#endif /* WSREP_PROC_INFO */ + + if (WSREP_OK != rcode) wsrep_write_rbr_buf(thd, buf, buf_len); + + return rcode; +} + +#if DELETE // this does not work in 5.5 +/* a common wrapper for end_trans() function - to put all necessary stuff */ +static inline wsrep_status_t +wsrep_end_trans (THD* const thd, enum enum_mysql_completiontype const end) +{ + if (0 == end_trans(thd, end)) + { + return WSREP_OK; + } + else + { + return WSREP_FATAL; + } +} +#endif + +wsrep_status_t wsrep_commit(THD* const thd, wsrep_seqno_t const global_seqno) +{ +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "committing %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "committing"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_sql(thd, "COMMIT", 6, 0, 0)); +// wsrep_status_t const rcode(wsrep_end_trans (thd, COMMIT)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "committed %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "committed"); +#endif /* WSREP_PROC_INFO */ + + if (WSREP_OK == rcode) + { + // TODO: mark snapshot with global_seqno. + } + + return rcode; +} + +wsrep_status_t wsrep_rollback(THD* const thd, wsrep_seqno_t const global_seqno) +{ +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolling back %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "rolling back"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_sql(thd, "ROLLBACK", 8, 0, 0)); +// wsrep_status_t const rcode(wsrep_end_trans (thd, ROLLBACK)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolled back %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "rolled back"); +#endif /* WSREP_PROC_INFO */ + + return rcode; +} + +wsrep_status_t wsrep_commit_cb(void* const ctx, + wsrep_seqno_t const global_seqno, + bool const commit) +{ + THD* const thd((THD*)ctx); + + assert(global_seqno == thd->wsrep_trx_seqno); + + if (commit) + return wsrep_commit(thd, global_seqno); + else + return wsrep_rollback(thd, global_seqno); +} + +Relay_log_info* wsrep_relay_log_init(const char* log_fname) +{ + Relay_log_info* rli= new Relay_log_info(false); + + rli->no_storage= true; + if (!rli->relay_log.description_event_for_exec) + { + rli->relay_log.description_event_for_exec= + new Format_description_log_event(4); + } + + rli->sql_thd= current_thd; + return rli; +} + +void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) +{ + shadow->options = thd->variables.option_bits; + shadow->wsrep_exec_mode = thd->wsrep_exec_mode; + shadow->vio = thd->net.vio; + + if (opt_log_slave_updates) + thd->variables.option_bits|= OPTION_BIN_LOG; + else + thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + if (!thd->wsrep_rli) thd->wsrep_rli= wsrep_relay_log_init("wsrep_relay"); + + thd->wsrep_exec_mode= REPL_RECV; + thd->net.vio= 0; + thd->clear_error(); + + thd->variables.option_bits|= OPTION_NOT_AUTOCOMMIT; + + shadow->tx_isolation = thd->variables.tx_isolation; + thd->variables.tx_isolation = ISO_READ_COMMITTED; + thd->tx_isolation = ISO_READ_COMMITTED; +} + +void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) +{ + thd->variables.option_bits = shadow->options; + thd->wsrep_exec_mode = shadow->wsrep_exec_mode; + thd->net.vio = shadow->vio; + thd->variables.tx_isolation = shadow->tx_isolation; +} + +void wsrep_replication_process(THD *thd) +{ + int rcode; + DBUG_ENTER("wsrep_replication_process"); + + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + + wsrep_format_desc= new Format_description_log_event(4); + + 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); + /* fall through to node shutdown */ + 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; + } + + if (thd->killed != KILL_CONNECTION) + { + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + } + + if (thd->killed != KILL_CONNECTION) + { + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + } + wsrep_return_from_bf_mode(thd, &shadow); + DBUG_VOID_RETURN; +} + +void wsrep_rollback_process(THD *thd) +{ + 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; + + mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); + + WSREP_DEBUG("WSREP rollback thread wakes for signal"); + + 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); + + /* check for false alarms */ + if (!wsrep_aborting_thd) + { + 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_wsrep_thd); + if (aborting->wsrep_conflict_state== ABORTED) + { + WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", + (long long)aborting->real_id, + aborting->wsrep_conflict_state); + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_rollback); + continue; + } + aborting->wsrep_conflict_state= ABORTING; + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + + aborting->store_globals(); + + trans_rollback(aborting); + aborting->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + aborting->mdl_context.release_transactional_locks(); + + mysql_mutex_lock(&aborting->LOCK_wsrep_thd); + aborting->wsrep_conflict_state= ABORTED; + WSREP_DEBUG("WSREP rollbacker aborted thd: %llu", + (long long)aborting->real_id); + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_rollback); + } + } + + mysql_mutex_unlock(&LOCK_wsrep_rollback); + sql_print_information("WSREP: rollbacker thread exiting"); + + DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); + DBUG_VOID_RETURN; +} +extern "C" +int wsrep_thd_is_brute_force(void *thd_ptr) +{ + if (thd_ptr) { + switch (((THD *)thd_ptr)->wsrep_exec_mode) { + case LOCAL_STATE: + { + if (((THD *)thd_ptr)->wsrep_conflict_state== REPLAYING) + { + return 1; + } + return 0; + } + case REPL_RECV: return 1; + case TOTAL_ORDER: return 2; + case LOCAL_COMMIT: return 3; + } + } + return 0; +} +extern "C" +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"); + + if (WSREP(bf_thd) && victim_thd) + { + WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? + (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); + ha_wsrep_abort_transaction(bf_thd, victim_thd, signal); + } + + DBUG_RETURN(1); +} +extern "C" +int wsrep_thd_in_locking_session(void *thd_ptr) +{ + if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { + return 1; + } + return 0; +} +#endif /** Retuns information about user or current user. diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 39f69b2656d..6a1a9221064 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2954,11 +2954,17 @@ void plugin_thdvar_init(THD *thd) thd->variables.dynamic_variables_size= 0; thd->variables.dynamic_variables_ptr= 0; +#ifdef WITH_WSREP + if (!WSREP(thd) || !thd->wsrep_applier) { +#endif mysql_mutex_lock(&LOCK_plugin); thd->variables.table_plugin= my_intern_plugin_lock(NULL, global_system_variables.table_plugin); intern_plugin_unlock(NULL, old_table_plugin); mysql_mutex_unlock(&LOCK_plugin); +#ifdef WITH_WSREP + } +#endif DBUG_VOID_RETURN; } diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index d2f118b62c9..cb33110d9eb 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -224,7 +224,18 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, } if (options & REFRESH_CHECKPOINT) disable_checkpoints(thd); - } +#ifdef WITH_WSREP + /* + We need to do it second time after wsrep appliers were blocked in + make_global_read_lock_block_commit(thd) above since they could have + modified the tables too. + */ + if (WSREP(thd) && + close_cached_tables(thd, tables, (options & REFRESH_FAST) ? + FALSE : TRUE, TRUE)) + result= 1; +#endif /* WITH_WSREP */ + } else { if (thd && thd->locked_tables_mode) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index eb17ef0812c..ecb47324552 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1399,7 +1399,14 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) ER(ER_SLAVE_WAS_NOT_RUNNING)); } unlock_slave_threads(mi); +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "exit stop_slave()"); + else thd_proc_info(thd, 0); +#else /* WITH_WSREP */ + thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ if (slave_errno) { @@ -1832,7 +1839,14 @@ bool change_master(THD* thd, Master_info* mi) err: unlock_slave_threads(mi); +#ifdef WITH_WSREP + if (WSREP(thd)) + thd_proc_info(thd, "exit change_master()"); + else thd_proc_info(thd, 0); +#else /* WITH_WSREP */ + thd_proc_info(thd, 0); +#endif /* WITH_WSREP */ if (ret == FALSE) my_ok(thd); DBUG_RETURN(ret); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d64c7a6df52..da48c7cdc63 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -59,6 +59,9 @@ #include "datadict.h" // dd_frm_type() #include "keycaches.h" +#if !defined(MYSQL_MAX_VARIABLE_VALUE_LEN) +#define MYSQL_MAX_VARIABLE_VALUE_LEN 1024 +#endif // !defined(MYSQL_MAX_VARIABLE_VALUE_LEN) #define STR_OR_NIL(S) ((S) ? (S) : "") #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -8088,7 +8091,8 @@ ST_FIELD_INFO variables_fields_info[]= { {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name", SKIP_OPEN_TABLE}, - {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE}, + {"VARIABLE_VALUE", MYSQL_MAX_VARIABLE_VALUE_LEN, MYSQL_TYPE_STRING, 0, 1, + "Value", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 01832036701..1fdd81de089 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6158,12 +6158,18 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error= 0; break; } - if (error == HA_ERR_WRONG_COMMAND) +#ifdef WITH_WSREP + bool do_log_write(true); +#endif /* WITH_WSREP */ + if (error == HA_ERR_WRONG_COMMAND) { error= 0; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->alias.c_ptr()); +#ifdef WITH_WSREP + WSREP_DEBUG("ignoring DDL failure: %d %s", error, thd->query()); +#endif /* WITH_WSREP */ } if (!error && (new_name != table_name || new_db != db)) @@ -6215,6 +6221,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->alias.c_ptr()); +#ifdef WITH_WSREP + WSREP_DEBUG("ignoring DDL failure: %d %s", error, thd->query()); +#endif /* WITH_WSREP */ } if (!error) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 1ac1d7bbb5e..149c2431324 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2452,3 +2452,55 @@ bool load_table_name_for_trigger(THD *thd, DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP +int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len) +{ + LEX *lex= thd->lex; + String stmt_query; + + LEX_STRING definer_user; + LEX_STRING definer_host; + + if (!lex->definer) + { + if (!thd->slave_thread) + { + if (!(lex->definer= create_default_definer(thd))) + return 1; + } + } + + if (lex->definer) + { + /* SUID trigger. */ + + definer_user= lex->definer->user; + definer_host= lex->definer->host; + } + else + { + /* non-SUID trigger. */ + + definer_user.str= 0; + definer_user.length= 0; + + definer_host.str= 0; + definer_host.length= 0; + } + + stmt_query.append(STRING_WITH_LEN("CREATE ")); + + append_definer(thd, &stmt_query, &definer_user, &definer_host); + + LEX_STRING stmt_definition; + stmt_definition.str= (char*) thd->lex->stmt_definition_begin; + stmt_definition.length= thd->lex->stmt_definition_end + - thd->lex->stmt_definition_begin; + trim_whitespace(thd->charset(), & stmt_definition); + + stmt_query.append(stmt_definition.str, stmt_definition.length); + + return wsrep_to_buf_helper(thd, stmt_query.c_ptr(), stmt_query.length(), + buf, buf_len); +} +#endif /* WITH_WSREP */ diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 67ed608f114..a66b2377fcb 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -24,6 +24,9 @@ #include "sql_acl.h" // DROP_ACL #include "sql_parse.h" // check_one_table_access() #include "sql_truncate.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ /** @@ -515,9 +518,14 @@ bool Truncate_statement::execute(THD *thd) if (check_one_table_access(thd, DROP_ACL, first_table)) DBUG_RETURN(res); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_to_isolation_begin(thd, + first_table->db, + first_table->table_name)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ if (! (res= truncate_table(thd, first_table))) my_ok(thd); - DBUG_RETURN(res); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5fa30c91417..ddb95f09ce2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -902,7 +902,11 @@ int mysql_update(THD *thd, */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error < 0) @@ -2045,7 +2049,11 @@ void multi_update::abort_result_set() The query has to binlog because there's a modified non-transactional table either from the query's list or via a stored routine: bug#13270,23333 */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { /* THD::killed status might not have been set ON at time of an error @@ -2304,7 +2312,11 @@ bool multi_update::send_eof() if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (local_error == 0) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 72e9525db72..dd11f51b212 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3437,6 +3437,206 @@ static Sys_var_tz Sys_time_zone( "time_zone", "time_zone", SESSION_VAR(time_zone), NO_CMD_LINE, DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG); +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" + +static Sys_var_charptr Sys_wsrep_provider( + "wsrep_provider", "Path to replication provider library", + GLOBAL_VAR(wsrep_provider), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER), + IN_FS_CHARSET, DEFAULT(wsrep_provider), + // IN_FS_CHARSET, DEFAULT(wsrep_provider_default), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_provider_check), ON_UPDATE(wsrep_provider_update)); + +static Sys_var_charptr Sys_wsrep_provider_options( + "wsrep_provider_options", "provider specific options", + GLOBAL_VAR(wsrep_provider_options), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER_OPTIONS), + IN_FS_CHARSET, DEFAULT(wsrep_provider_options), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_provider_options_check), + ON_UPDATE(wsrep_provider_options_update)); + +static Sys_var_charptr Sys_wsrep_data_home_dir( + "wsrep_data_home_dir", "home directory for wsrep provider", + READ_ONLY GLOBAL_VAR(wsrep_data_home_dir), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_charptr Sys_wsrep_cluster_name( + "wsrep_cluster_name", "Name for the cluster", + GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_cluster_name), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_cluster_name_check), + ON_UPDATE(wsrep_cluster_name_update)); + +static Sys_var_charptr Sys_wsrep_cluster_address ( + "wsrep_cluster_address", "Address to initially connect to cluster", + GLOBAL_VAR(wsrep_cluster_address), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_CLUSTER_ADDRESS), + IN_FS_CHARSET, DEFAULT(wsrep_cluster_address), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_cluster_address_check), + ON_UPDATE(wsrep_cluster_address_update)); + +static Sys_var_charptr Sys_wsrep_node_name ( + "wsrep_node_name", "Node name", + GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(glob_hostname), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_charptr Sys_wsrep_node_address ( + "wsrep_node_address", "Node address", + GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_node_address), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_node_address_check), + ON_UPDATE(wsrep_node_address_update)); + +static Sys_var_charptr Sys_wsrep_node_incoming_address( + "wsrep_node_incoming_address", "Client connection address", + GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_node_name_check), + ON_UPDATE(wsrep_node_name_update)); + +static Sys_var_ulong Sys_wsrep_slave_threads( + "wsrep_slave_threads", "Number of slave appliers to launch", + GLOBAL_VAR(wsrep_slave_threads), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 512), DEFAULT(1), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_wsrep_dbug_option( + "wsrep_dbug_option", "DBUG options to provider library", + GLOBAL_VAR(wsrep_dbug_option),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_mybool Sys_wsrep_debug( + "wsrep_debug", "To enable debug level logging", + GLOBAL_VAR(wsrep_debug), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_convert_LOCK_to_trx( + "wsrep_convert_LOCK_to_trx", "To convert locking sessions " + "into transactions", + GLOBAL_VAR(wsrep_convert_LOCK_to_trx), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_wsrep_retry_autocommit( + "wsrep_retry_autocommit", "Max number of times to retry " + "a failed autocommit statement", + SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 10000), DEFAULT(1), BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_wsrep_auto_increment_control( + "wsrep_auto_increment_control", "To automatically control the " + "assignment of autoincrement variables", + GLOBAL_VAR(wsrep_auto_increment_control), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_drupal_282555_workaround( + "wsrep_drupal_282555_workaround", "To use a workaround for" + "bad autoincrement value", + GLOBAL_VAR(wsrep_drupal_282555_workaround), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_charptr sys_wsrep_sst_method( + "wsrep_sst_method", "Snapshot transfer method", + GLOBAL_VAR(wsrep_sst_method),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_sst_method), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_method_check), + ON_UPDATE(wsrep_sst_method_update)); + +static Sys_var_charptr Sys_wsrep_sst_receive_address( + "wsrep_sst_receive_address", "Address where node is waiting for " + "SST contact", + GLOBAL_VAR(wsrep_sst_receive_address),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_sst_receive_address), NO_MUTEX_GUARD, + NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_receive_address_check), + ON_UPDATE(wsrep_sst_receive_address_update)); + +static Sys_var_charptr Sys_wsrep_sst_auth( + "wsrep_sst_auth", "Authentication for SST connection", + GLOBAL_VAR(wsrep_sst_auth), CMD_LINE(REQUIRED_ARG, OPT_WSREP_SST_AUTH), + IN_FS_CHARSET, DEFAULT(wsrep_sst_auth), NO_MUTEX_GUARD, + NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_auth_check), + ON_UPDATE(wsrep_sst_auth_update)); + +static Sys_var_charptr Sys_wsrep_sst_donor( + "wsrep_sst_donor", "preferred donor node for the SST", + GLOBAL_VAR(wsrep_sst_donor),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_donor_check), + ON_UPDATE(wsrep_sst_donor_update)); + +static Sys_var_mybool Sys_wsrep_on ( + "wsrep_on", "To enable wsrep replication ", + SESSION_VAR(wsrep_on), + CMD_LINE(OPT_ARG), DEFAULT(TRUE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_on_update)); + +static Sys_var_charptr Sys_wsrep_start_position ( + "wsrep_start_position", "global transaction position to start from ", + GLOBAL_VAR(wsrep_start_position), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_START_POSITION), + IN_FS_CHARSET, DEFAULT(wsrep_start_position), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_start_position_check), + ON_UPDATE(wsrep_start_position_update)); + +static Sys_var_ulonglong Sys_wsrep_max_ws_size ( + "wsrep_max_ws_size", "Max write set size (bytes)", + GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, 4294967296ULL), DEFAULT(1073741824ULL), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_wsrep_max_ws_rows ( + "wsrep_max_ws_rows", "Max number of rows in write set", + GLOBAL_VAR(wsrep_max_ws_rows), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 1048576), DEFAULT(131072), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_wsrep_notify_cmd( + "wsrep_notify_cmd", "", + GLOBAL_VAR(wsrep_notify_cmd),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_mybool Sys_wsrep_certify_nonPK( + "wsrep_certify_nonPK", "Certify tables with no primary key", + GLOBAL_VAR(wsrep_certify_nonPK), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_causal_reads( + "wsrep_causal_reads", "Enable \"strictly synchronous\" semantics for read operations", + SESSION_VAR(wsrep_causal_reads), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + // ON_UPDATE(wsrep_causal_reads_update)); + +static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; +static Sys_var_enum Sys_wsrep_OSU_method( + "wsrep_OSU_method", "Method for Online Schema Upgrade", + GLOBAL_VAR(wsrep_OSU_method_options), CMD_LINE(OPT_ARG), + wsrep_OSU_method_names, DEFAULT(WSREP_OSU_TOI), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(0)); + +static Sys_var_enum Sys_wsrep_forced_binlog_format( + "wsrep_forced_binlog_format", "binlog format to take effect over user's choice", + GLOBAL_VAR(wsrep_forced_binlog_format), + CMD_LINE(REQUIRED_ARG, OPT_BINLOG_FORMAT), + wsrep_binlog_format_names, DEFAULT(BINLOG_FORMAT_UNSPEC), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(0)); + +static Sys_var_mybool Sys_wsrep_recover_datadir( + "wsrep_recover", "Recover database state after crash and exit", + READ_ONLY GLOBAL_VAR(wsrep_recovery), + CMD_LINE(OPT_ARG, OPT_WSREP_RECOVER), DEFAULT(FALSE)); + + +#endif /* WITH_WSREP */ static Sys_var_ulong Sys_sp_cache_size( "stored_program_cache", diff --git a/sql/transaction.cc b/sql/transaction.cc index 94a32200274..2b23b5e19f1 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -96,6 +96,9 @@ static bool xa_trans_force_rollback(THD *thd) by ha_rollback()/THD::transaction::cleanup(). */ thd->transaction.xid_state.rm_error= 0; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ if (ha_rollback_trans(thd, true)) { my_error(ER_XAER_RMERR, MYF(0)); @@ -134,6 +137,9 @@ bool trans_begin(THD *thd, uint flags) (thd->variables.option_bits & OPTION_TABLE_LOCK)) { thd->variables.option_bits&= ~OPTION_TABLE_LOCK; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= test(ha_commit_trans(thd, TRUE)); } @@ -150,6 +156,12 @@ bool trans_begin(THD *thd, uint flags) */ thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP + thd->wsrep_PA_safe= true; + if (thd->wsrep_client_thread && wsrep_causal_wait(thd)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ + thd->variables.option_bits|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; @@ -177,6 +189,9 @@ bool trans_commit(THD *thd) if (trans_check(thd)) DBUG_RETURN(TRUE); +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit_trans(thd, TRUE); if (res) @@ -220,6 +235,9 @@ 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; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= test(ha_commit_trans(thd, TRUE)); } @@ -251,11 +269,16 @@ bool trans_commit_implicit(THD *thd) bool trans_rollback(THD *thd) { int res; - DBUG_ENTER("trans_rollback"); - - if (trans_check(thd)) + DBUG_ENTER("trans_rollback"); +#ifdef WITH_WSREP + thd->wsrep_PA_safe= true; +#endif /* WITH_WSREP */ + if (trans_check(thd)) DBUG_RETURN(TRUE); +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_rollback_trans(thd, TRUE); RUN_HOOK(transaction, after_rollback, (thd, FALSE)); @@ -296,6 +319,9 @@ bool trans_commit_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, FALSE); +#endif /* WITH_WSREP */ res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; @@ -338,9 +364,19 @@ bool trans_rollback_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, FALSE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, FALSE); if (thd->transaction_rollback_request && !thd->in_sub_stmt) +#ifdef WITH_WSREP + { + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, TRUE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ if (! thd->in_active_multi_stmt_transaction()) thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; } @@ -681,6 +717,9 @@ bool trans_xa_commit(THD *thd) } else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ int r= ha_commit_trans(thd, TRUE); if ((res= test(r))) my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); @@ -702,6 +741,9 @@ bool trans_xa_commit(THD *thd) if (thd->mdl_context.acquire_lock(&mdl_request, thd->variables.lock_wait_timeout)) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, TRUE); my_error(ER_XAER_RMERR, MYF(0)); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9fb7dd79f3d..705eeaf5f9c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -89,6 +89,12 @@ extern "C" { #include "ha_prototypes.h" #include "ut0mem.h" #include "ibuf0ibuf.h" +#ifdef WITH_WSREP +#include "../storage/innobase/include/ut0byte.h" +#ifndef EXTRA_DEBUG + //#include "../storage/innobase/include/ut0byte.ic" +#endif /* EXTRA_DEBUG */ +#endif /* WITH_WSREP */ } #include "ha_innodb.h" @@ -98,6 +104,32 @@ extern "C" { # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ +#ifdef WITH_WSREP +#include +#include +extern my_bool wsrep_certify_nonPK; +class binlog_trx_data; +extern handlerton *binlog_hton; + +extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; +extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; + +static inline wsrep_trx_handle_t* +wsrep_trx_handle(THD* thd, const trx_t* trx) { + return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), + (wsrep_trx_id_t)trx->id); +} + +extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len); + +#endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ @@ -851,6 +883,15 @@ thd_to_trx( { return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr)); } +#ifdef WITH_WSREP +ulonglong +thd_to_trx_id( +/*=======*/ + THD* thd) /*!< in: MySQL thread */ +{ + return(thd_to_trx(thd)->id); +} +#endif /********************************************************************//** Call this function when mysqld passes control to the client. That is to @@ -881,6 +922,13 @@ innobase_release_temporary_latches( return(0); } +#ifdef 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 /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -1327,6 +1375,9 @@ int innobase_mysql_tmpfile(void) /*========================*/ { +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_wait(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ int fd2 = -1; File fd = mysql_tmpfile("ib"); if (fd >= 0) { @@ -2241,6 +2292,11 @@ innobase_init( innobase_hton->flags=HTON_NO_FLAGS; innobase_hton->release_temporary_latches=innobase_release_temporary_latches; innobase_hton->alter_table_flags = innobase_alter_table_flags; +#ifdef WITH_WSREP + innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; + innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; + innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; +#endif /* WITH_WSREP */ ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -2670,6 +2726,27 @@ innobase_commit_low( trx_commit_for_mysql(trx); } +#ifdef WITH_WSREP + THD* thd = (THD*)trx->mysql_thd; + const char* tmp = 0; + if (wsrep_on((void*)thd)) { +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, + "innobase_commit_low():trx_commit_for_mysql(%lld)", + (long long) wsrep_thd_trx_seqno(thd)); + tmp = thd_proc_info(thd, info); + +#else + tmp = thd_proc_info(thd, "innobase_commit_low()"); +#endif /* WSREP_PROC_INFO */ + } +#endif /* WITH_WSREP */ + trx_commit_for_mysql(trx); +#ifdef WITH_WSREP + if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } +#endif /* WITH_WSREP */ } /*****************************************************************//** @@ -3286,7 +3363,11 @@ ha_innobase::max_supported_key_length() const therefore set to slightly less than 1 / 4 of page size which is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ +#ifdef WITH_WSREP return(3500); +#else + return(3500); +#endif } /****************************************************************//** @@ -4272,7 +4353,96 @@ innobase_mysql_cmp( return(0); } +#ifdef WITH_WSREP +extern "C" UNIV_INTERN +void +wsrep_innobase_mysql_sort( +/*===============*/ + /* out: str contains sort string */ + int mysql_type, /* in: MySQL type */ + uint charset_number, /* in: number of the charset */ + unsigned char* str, /* in: data field */ + unsigned int str_length) /* in: data field length, + not UNIV_SQL_NULL */ +{ + CHARSET_INFO* charset; + enum_field_types mysql_tp; + DBUG_ASSERT(str_length != UNIV_SQL_NULL); + + mysql_tp = (enum_field_types) mysql_type; + + switch (mysql_tp) { + + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + { + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN]; + uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; + + /* Use the charset number to pick the right charset struct for + the comparison. Since the MySQL function get_charset may be + slow before Bar removes the mutex operation there, we first + look at 2 common charsets directly. */ + + if (charset_number == default_charset_info->number) { + charset = default_charset_info; + } else if (charset_number == my_charset_latin1.number) { + charset = &my_charset_latin1; + } else { + charset = get_charset(charset_number, MYF(MY_WME)); + + if (charset == NULL) { + sql_print_error("InnoDB needs charset %lu for doing " + "a comparison, but MySQL cannot " + "find that charset.", + (ulong) charset_number); + ut_a(0); + } + } + + ut_a(str_length <= tmp_length); + memcpy(tmp_str, str, str_length); + + tmp_length = charset->coll->strnxfrm(charset, str, str_length, + tmp_str, tmp_length); + DBUG_ASSERT(tmp_length == str_length); + + break; + } + case MYSQL_TYPE_DECIMAL : + case MYSQL_TYPE_TINY : + case MYSQL_TYPE_SHORT : + case MYSQL_TYPE_LONG : + case MYSQL_TYPE_FLOAT : + case MYSQL_TYPE_DOUBLE : + case MYSQL_TYPE_NULL : + case MYSQL_TYPE_TIMESTAMP : + case MYSQL_TYPE_LONGLONG : + case MYSQL_TYPE_INT24 : + case MYSQL_TYPE_DATE : + case MYSQL_TYPE_TIME : + case MYSQL_TYPE_DATETIME : + case MYSQL_TYPE_YEAR : + case MYSQL_TYPE_NEWDATE : + case MYSQL_TYPE_NEWDECIMAL : + case MYSQL_TYPE_ENUM : + case MYSQL_TYPE_SET : + case MYSQL_TYPE_GEOMETRY : + break; + default: + break; + } + + return; +} +#endif // WITH_WSREP /**************************************************************//** Converts a MySQL type to an InnoDB type. Note that this function returns the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1 @@ -4391,6 +4561,256 @@ innobase_read_from_2_little_endian( /*******************************************************************//** Stores a key value for a row to a buffer. @return key value length as stored in buff */ +#ifdef WITH_WSREP +UNIV_INTERN +uint +wsrep_store_key_val_for_row( +/*===============================*/ + TABLE* table, + uint keynr, /*!< in: key number */ + char* buff, /*!< in/out: buffer for the key value (in MySQL + format) */ + uint buff_len,/*!< in: buffer length */ + const uchar* record, + ibool* key_is_null)/*!< out: full key was null */ +{ + KEY* key_info = table->key_info + keynr; + KEY_PART_INFO* key_part = key_info->key_part; + KEY_PART_INFO* end = key_part + key_info->key_parts; + char* buff_start = buff; + enum_field_types mysql_type; + Field* field; + + DBUG_ENTER("store_key_val_for_row"); + + bzero(buff, buff_len); + *key_is_null = TRUE; + + for (; key_part != end; key_part++) { + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; + ibool part_is_null = FALSE; + + if (key_part->null_bit) { + if (record[key_part->null_offset] & + key_part->null_bit) { + *buff = 1; + part_is_null = TRUE; + } else { + *buff = 0; + } + buff++; + } + if (!part_is_null) *key_is_null = FALSE; + + field = key_part->field; + mysql_type = field->type(); + + if (mysql_type == MYSQL_TYPE_VARCHAR) { + /* >= 5.0.3 true VARCHAR */ + ulint lenlen; + ulint len; + const byte* data; + ulint key_len; + ulint true_len; + CHARSET_INFO* cs; + int error=0; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + cs = field->charset(); + + lenlen = (ulint) + (((Field_varstring*)field)->length_bytes); + + data = row_mysql_read_true_varchar(&len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + lenlen); + + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* In a column prefix index, we may need to truncate + the stored value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the true VARCHAR in the key value, though + only len first bytes after the 2 length bytes contain + actual data. The rest of the space was reset to zero + in the bzero() call above. */ + + buff += key_len; + + } else if (mysql_type == MYSQL_TYPE_TINY_BLOB + || mysql_type == MYSQL_TYPE_MEDIUM_BLOB + || mysql_type == MYSQL_TYPE_BLOB + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { + + CHARSET_INFO* cs; + ulint key_len; + ulint true_len; + int error=0; + ulint blob_len; + const byte* blob_data; + + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + + cs = field->charset(); + + blob_data = row_mysql_read_blob_ref(&blob_len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + (ulint) field->pack_length()); + + true_len = blob_len; + + ut_a(get_field_offset(table, field) + == key_part->offset); + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* All indexes on BLOB and TEXT are column prefix + indexes, and we may need to truncate the data to be + stored in the key value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, blob_data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + memcpy(buff, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the BLOB prefix in the key value. */ + + buff += key_len; + } else { + /* Here we handle all other data types except the + true VARCHAR, BLOB and TEXT. Note that the column + value we store may be also in a column prefix + index. */ + + CHARSET_INFO* cs; + ulint true_len; + ulint key_len; + const uchar* src_start; + int error=0; + enum_field_types real_type; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len; + + continue; + } + + src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; + + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != MYSQL_TYPE_ENUM + && real_type != MYSQL_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + memcpy(sorted, src_start, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + memcpy(buff, sorted, true_len); + } else { + memcpy(buff, src_start, true_len); + } + buff += true_len; + + /* Pad the unused space with spaces. */ + + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + ut_a(!(pad_len % cs->mbminlen)); + + cs->cset->fill(cs, buff, pad_len, + 0x20 /* space */); + buff += pad_len; + } + } + } + + ut_a(buff <= buff_start + buff_len); + + DBUG_RETURN((uint)(buff - buff_start)); +} +#endif /* WITH_WSREP */ UNIV_INTERN uint ha_innobase::store_key_val_for_row( @@ -4994,6 +5414,9 @@ ha_innobase::write_row( ulint error = 0; int error_result= 0; ibool auto_inc_used= FALSE; +#ifdef WITH_WSREP + ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ +#endif ulint sql_command; trx_t* trx = thd_to_trx(user_thd); @@ -5024,8 +5447,14 @@ ha_innobase::write_row( if ((sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX +#ifdef WITH_WSREP + || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) +#endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { +#ifdef WITH_WSREP + WSREP_DEBUG("forced commit: %s", wsrep_thd_query(user_thd)); +#endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. As this method will be called on a temporary table where the @@ -5097,7 +5526,9 @@ no_commit: /* Reset the error code before calling innobase_get_auto_increment(). */ prebuilt->autoinc_error = DB_SUCCESS; - +#ifdef WITH_WSREP + auto_inc_inserted= (table->next_number_field->val_int() == 0); +#endif if ((error = update_auto_increment())) { /* We don't want to mask autoinc overflow errors. */ @@ -5177,6 +5608,30 @@ no_commit: case SQLCOM_REPLACE_SELECT: goto set_max_autoinc; +#ifdef WITH_WSREP + /* workaround for LP bug #355000, retrying the insert */ + case SQLCOM_INSERT: + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + !thd_test_options(current_thd, + OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)) { + WSREP_DEBUG( + "retrying insert: %s", + (*wsrep_thd_query(current_thd)) ? + wsrep_thd_query(current_thd) : + (char *)"void"); + error= DB_SUCCESS; + wsrep_thd_set_conflict_state( + current_thd, MUST_ABORT); + innodb_srv_conc_exit_innodb(prebuilt->trx); + /* jump straight to func exit over + * later wsrep hooks */ + goto func_exit; + } + break; +#endif default: break; } @@ -5224,6 +5679,20 @@ report_error: error_result = convert_error_code_to_mysql((int) error, prebuilt->table->flags, user_thd); +#ifdef WITH_WSREP + if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && + (sql_command != SQLCOM_LOAD || + thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif func_exit: innobase_active_small(); @@ -5505,6 +5974,20 @@ ha_innobase::update_row( innobase_active_small(); +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + DBUG_PRINT("wsrep", ("update row key")); + + if (wsrep_append_keys(user_thd, false, old_row, new_row)) { + DBUG_PRINT("wsrep", ("row key failed")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -5548,6 +6031,18 @@ ha_innobase::delete_row( innobase_active_small(); +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("delete fail")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -6333,7 +6828,240 @@ ha_innobase::rnd_pos( DBUG_RETURN(error); } +#ifdef WITH_WSREP +extern "C" { +ulint +wsrep_append_foreign_key( +/*===========================*/ + trx_t* trx, /*!< in: trx */ + dict_foreign_t* foreign, /*!< in: foreign key constraint */ + const rec_t* clust_rec, /*!mysql_thd; + ulint rcode = DB_SUCCESS; + char cache_key[512] = {'\0'}; + if (!wsrep_on(trx->mysql_thd) || + wsrep_thd_exec_mode(thd) != LOCAL_STATE) + return DB_SUCCESS; + + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; + + if (!dict_index_is_clust(clust_index)) { + WSREP_ERROR("clustered index not passed for FK append"); + return DB_ERROR; + } + + key[0] = '\0'; + rcode = wsrep_rec_get_primary_key( + &key[1], &len, clust_rec, clust_index); + if (rcode != DB_SUCCESS) { + WSREP_ERROR("FK key set failed: %lu", rcode); + return rcode; + } +#ifdef WSREP_DEBUG_PRINT + ulint i; + fprintf(stderr, "FK parent key, len: %lu ", len+1); + for (i=0; iforeign_table->name, 512); + char *p = strchr(cache_key, '/'); + if (p) { + *p = '\0'; + } else { + WSREP_WARN("unexpected foreign key table %s", + foreign->foreign_table->name); + } + + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)cache_key, + strlen(foreign->foreign_table->name) + 1, + (const uchar*)key, len+1, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + return DB_ERROR; + } + + return DB_SUCCESS; +} +} + +static int +wsrep_append_key( +/*==================*/ + THD *thd, + trx_t *trx, + TABLE_SHARE *table_share, + TABLE *table, + const char* key, + uint16_t key_len, + bool shared +) +{ + DBUG_ENTER("wsrep_append_key"); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + (shared) ? "Shared" : "Exclusive", + wsrep_thd_thread_id(thd), trx->id, key_len, + table_share->table_name.str); + for (int i=0; itable_cache_key.str, + table_share->table_cache_key.length, + (const uchar*)key, key_len, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } + + int rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + DBUG_RETURN(rcode); + } + DBUG_RETURN(0); +} +int +ha_innobase::wsrep_append_keys( +/*==================*/ + THD *thd, + bool shared, + const uchar* record0, /* in: row in MySQL format */ + const uchar* record1) /* in: row in MySQL format */ +{ + DBUG_ENTER("wsrep_append_keys"); + trx_t *trx = thd_to_trx(thd); + + /* if no PK, calculate hash of full row, to be the key value */ + if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + MY_MD5_HASH(digest, (uchar *)record0, table->s->reclength); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + if (record1) { + MY_MD5_HASH(digest, (uchar *)record1, table->s->reclength); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + } else if (wsrep_protocol_version == 0) { + uint len; + char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key = &keyval[0]; + KEY *key_info = table->key_info; + ibool is_null; + + len = wsrep_store_key_val_for_row( + table, 0, key, key_info->key_length, record0, &is_null); + + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, keyval, + len, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped (proto 0): %s", + wsrep_thd_query(thd)); + } + } else { + ut_a(table->s->keys <= 256); + uint i; + for (i=0; is->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; + + keyval0[0] = (char)i; + keyval1[0] = (char)i; + + if (key_info->flags & HA_NOSAME) { + len = wsrep_store_key_val_for_row( + table, i, key0, key_info->key_length, + record0, &is_null); + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, + keyval0, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } + if (record1) { + len = wsrep_store_key_val_for_row( + table, i, key1, key_info->key_length, + record1, &is_null); + if (!is_null && memcmp(key0, key1, len)) { + int rcode = wsrep_append_key( + thd, trx, table_share, + table, + keyval1, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + } + } + } + } + DBUG_RETURN(0); +} +#endif /*********************************************************************//** Stores a reference to the current row to 'ref' field of the handle. Note that in the case where we have generated the clustered index for the @@ -9192,11 +9920,18 @@ ha_innobase::external_lock( /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = 1;); if (!skip) { +#ifdef WITH_WSREP + if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when " "transaction isolation level is " "READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } } @@ -11229,6 +11964,256 @@ static SHOW_VAR innodb_status_variables_export[]= { static struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +#ifdef WITH_WSREP +void +wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) +{ + WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " + "caused by:\n\t" + "1) unsupported configuration options combination, please check documentation.\n\t" + "2) a bug in the code.\n\t" + "3) a database corruption.\n Node consistency compromized, " + "need to abort. Restart the node to resync with cluster.", + (long long)bf_seqno, (long long)victim_seqno); + abort(); +} +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) +{ + DBUG_ENTER("wsrep_innobase_kill_one_trx"); + THD *thd = (THD *) victim_trx->mysql_thd; + THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + + if (!thd) { + DBUG_PRINT("wsrep", ("no thd for conflicting lock")); + WSREP_WARN("no THD for trx: %llu", victim_trx->id); + DBUG_RETURN(1); + } + + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", + signal, (long long)bf_seqno, + wsrep_thd_thread_id(thd), + victim_trx->id); + + WSREP_DEBUG("Aborting query: %s", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); + + wsrep_thd_LOCK(thd); + + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { + WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + } + if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + WSREP_DEBUG("withdraw for BF trx: %llu, state: %d", + victim_trx->id, + wsrep_thd_conflict_state(thd)); + } + + switch (wsrep_thd_conflict_state(thd)) { + case NO_CONFLICT: + wsrep_thd_set_conflict_state(thd, MUST_ABORT); + break; + case MUST_ABORT: + WSREP_DEBUG("victim %llu 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 %llu in state %d", + victim_trx->id, wsrep_thd_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 trx QUERY_COMMITTING for %llu", + victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } else { + rcode = wsrep->abort_pre_commit( + wsrep, bf_seqno, + (wsrep_trx_id_t)victim_trx->id + ); + + switch (rcode) { + case WSREP_WARNING: + WSREP_DEBUG("cancel commit warning: %llu", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(1); + break; + case WSREP_OK: + break; + default: + WSREP_ERROR( + "cancel commit bad exit: %d %llu", + rcode, + victim_trx->id); + /* unable to interrupt, must abort */ + /* note: kill_mysql() will block, if we cannot. + * kill the lock holder first. + */ + abort(); + break; + } + } + 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 %llu", victim_trx->id); + + victim_trx->was_chosen_as_deadlock_victim= TRUE; + if (victim_trx->wait_lock) { + WSREP_DEBUG("victim has wait flag: %ld", + wsrep_thd_thread_id(thd)); + lock_t* wait_lock = victim_trx->wait_lock; + if (wait_lock) { + WSREP_DEBUG("canceling wait lock"); + victim_trx->was_chosen_as_deadlock_victim= TRUE; + lock_cancel_waiting_and_release(wait_lock); + } + + wsrep_thd_awake(thd, signal); + } else { + /* abort currently executing query */ + DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(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: + { + bool skip_abort= false; + wsrep_aborting_thd_t abortees; + + WSREP_DEBUG("kill IDLE for %llu", 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); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + + abortees = wsrep_aborting_thd; + while (abortees && !skip_abort) { + /* check if we have a kill message for this already */ + if (abortees->aborting_thd == thd) { + skip_abort = true; + WSREP_WARN("duplicate thd aborter %lu", + wsrep_thd_thread_id(thd)); + } + abortees = abortees->next; + } + if (!skip_abort) { + 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; + DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("enqueuing trx abort for (%lu)", + wsrep_thd_thread_id(thd)); + } + + DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); + WSREP_DEBUG("signaling aborter"); + mysql_cond_signal(&COND_wsrep_rollback); + mysql_mutex_unlock(&LOCK_wsrep_rollback); + + break; + } + default: + WSREP_WARN("bad wsrep query state: %d", + wsrep_thd_query_state(thd)); + break; + } + wsrep_thd_UNLOCK(thd); + + DBUG_RETURN(0); +} +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal) +{ + DBUG_ENTER("wsrep_innobase_abort_thd"); + 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", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd)); + + if (victim_trx) + { + mutex_enter(&kernel_mutex); + int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, + signal); + mutex_exit(&kernel_mutex); + 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); + } + DBUG_RETURN(-1); +} + +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + if (wsrep_is_wsrep_xid(xid)) { + mtr_t mtr; + mtr_start(&mtr); + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return 0; + } else { + return 1; + } +} + +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + trx_sys_read_wsrep_checkpoint(xid); + return 0; +} + +#endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -11560,6 +12545,40 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, NULL, NULL, 0, 0, 1, 0); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES +/******************************************************* + * innobase_disallow_writes variable definition * + *******************************************************/ + +/* Must always init to FALSE. */ +static my_bool innobase_disallow_writes = FALSE; + +/************************************************************************** +An "update" method for innobase_disallow_writes variable. */ +static +void +innobase_disallow_writes_update( +/*============================*/ + THD* thd, /* in: thread handle */ + st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* var_ptr, /* out: pointer to dynamic + variable */ + const void* save) /* in: temporary storage */ +{ + *(my_bool*)var_ptr = *(my_bool*)save; + ut_a(srv_allow_writes_event); + if (*(my_bool*)var_ptr) + os_event_reset(srv_allow_writes_event); + else + os_event_set(srv_allow_writes_event); +} + +static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, + PLUGIN_VAR_NOCMDOPT, + "Tell InnoDB to stop any writes to disk", + NULL, innobase_disallow_writes_update, FALSE); +#endif /* WITH_INNODB_DISALLOW_WRITES */ static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, "Whether to use read ahead for random access within an extent.", @@ -11641,6 +12660,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG MYSQL_SYSVAR(change_buffering_debug), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES + MYSQL_SYSVAR(disallow_writes), +#endif /* WITH_INNODB_DISALLOW_WRITES */ MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 7cce0c4a16c..8b3b63bd9fb 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -112,6 +112,10 @@ class ha_innobase: public handler dict_index_t* innobase_get_index(uint keynr); int info_low(uint flag, bool called_from_analyze); +#ifdef WITH_WSREP + int wsrep_append_keys(THD *thd, bool shared, + const uchar* record0, const uchar* record1); +#endif /* Init values for the class: */ public: ha_innobase(handlerton *hton, TABLE_SHARE *table_arg); @@ -290,6 +294,37 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd); */ extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); +#ifdef WITH_WSREP +#include +//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); + +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(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_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +#endif typedef struct trx_struct trx_t; /********************************************************************//** @file handler/ha_innodb.h @@ -330,3 +365,6 @@ innobase_index_name_is_reserved( ulint num_of_keys); /*!< in: Number of indexes to be created. */ +#ifdef WITH_WSREP +extern "C" int wsrep_trx_is_aborting(void *thd_ptr); +#endif diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 7d89979fd1f..f05bcb844d5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -36,6 +36,10 @@ extern "C" { #include "handler0alter.h" } +#ifdef WITH_WSREP +//#include "wsrep_api.h" +#include // PROCESS_ACL +#endif #include "ha_innodb.h" /*************************************************************//** diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 9ded0dba39b..3389c7d72b3 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -343,6 +343,9 @@ barracuda format, the length could be REC_VERSION_56_MAX_INDEX_COL_LEN /** Defines the maximum fixed length column size */ #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN +#ifdef WITH_WSREP +#define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500 +#endif /* WITH_WSREP */ /** Data structure for a field in an index */ struct dict_field_struct{ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index edf7a1a28c1..4ac365d5c40 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -285,6 +285,18 @@ thd_set_lock_wait_time( void* thd, /*!< in: thread handle (THD*) */ ulint value); /*!< in: time waited for the lock */ +#ifdef WITH_WSREP +UNIV_INTERN +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal); +int wsrep_thd_is_brute_force(void *thd_ptr); +int wsrep_trx_order_before(void *thd1, void *thd2); +void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length); +int +wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); +#endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from mysqld.cc. We do a dirty read because for one there is no synchronization diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 29fdc3bbe97..e5a61e599bc 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -797,6 +797,7 @@ lock_rec_get_page_no( remains set when the waiting lock is granted, or if the lock is inherited to a neighboring record */ +#define WSREP_BF 4096 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION)&LOCK_MODE_MASK # error #endif diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 10b74d18c13..ab390f4fb3a 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -832,6 +832,13 @@ are given in one byte (resp. two byte) format. */ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) +#ifdef WITH_WSREP +int wsrep_rec_get_primary_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index); /* in: record descriptor */ +#endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" #endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index dfe7397d189..edfea04bed3 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -141,6 +141,10 @@ extern ulint srv_log_buffer_size; extern ulong srv_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +#ifdef WITH_INNODB_DISALLOW_WRITES +/* When this event is reset we do not allow any file writes to take place. */ +extern os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ /* If this flag is TRUE, then we will load the indexes' (and tables') metadata even if they are marked as "corrupted". Mostly it is for DBA to process corrupted index and table */ diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 3913792d594..7a27342b44d 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -41,6 +41,9 @@ Created 3/26/1996 Heikki Tuuri #include "ut0bh.h" #include "read0types.h" #include "page0types.h" +#ifdef WITH_WSREP +#include "trx0xa.h" +#endif /* WITH_WSREP */ /** In a MySQL replication slave, in crash recovery we store the master log file name and position here. */ @@ -316,6 +319,17 @@ UNIV_INTERN void trx_sys_print_mysql_binlog_offset(void); /*===================================*/ +#ifdef WITH_WSREP +/** Update WSREP checkpoint XID in sys header. */ +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: WSREP XID */ + mtr_t* mtr); /*!< in: mtr */ +void +/** Read WSREP checkpoint XID from sys header. */ +trx_sys_read_wsrep_checkpoint( + XID* xid); /*!< out: WSREP XID */ +#endif /* WITH_WSREP */ /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ @@ -521,6 +535,22 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ +#ifdef WITH_WSREP +/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused + otherwise (see comments for MySQL bug #34058). */ +/** */ +#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO +#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 +#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 + +/* XID field: formatID, gtrid_len, bqual_len, xid_data */ +#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) +#define TRX_SYS_WSREP_XID_FORMAT 4 +#define TRX_SYS_WSREP_XID_GTRID_LEN 8 +#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 +#define TRX_SYS_WSREP_XID_DATA 16 +#endif /* WITH_WSREP*/ + /** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 263516ab5fd..35cbb228e05 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -40,6 +40,9 @@ Created 5/7/1996 Heikki Tuuri #include "trx0sys.h" #include "btr0btr.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -921,6 +924,11 @@ lock_rec_has_to_wait( if (trx != lock2->trx && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, lock_get_mode(lock2))) { +#ifdef WITH_WSREP + if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { + return FALSE; + } +#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1450,6 +1458,11 @@ lock_rec_has_expl( return(NULL); } +#ifdef WITH_WSREP +static +void +lock_rec_discard(lock_t* in_lock); +#endif #ifdef UNIV_DEBUG /*********************************************************************//** Checks if some other transaction has a lock request in the queue. @@ -1499,6 +1512,27 @@ lock_rec_other_has_expl_req( } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP +static void +wsrep_kill_victim(trx_t *trx, lock_t *lock) { + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = + wsrep_thd_is_brute_force(lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd))) { + + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: BF victim waiting\n"); + /* cannot release lock, until our lock + is in the queue*/ + } else if (lock->trx != trx) { + wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE); + } + } +} +#endif /*********************************************************************//** Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. @@ -1528,6 +1562,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, TRUE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1538,6 +1575,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, FALSE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1669,6 +1709,9 @@ static lock_t* lock_rec_create( /*============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and replaced by LOCK_REC */ @@ -1714,6 +1757,11 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock->type_mode |= WSREP_BF; + } +#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1728,8 +1776,56 @@ lock_rec_create( /* Set the bit corresponding to rec */ lock_rec_set_nth_bit(lock, heap_no); +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock_t *hash = c_lock->hash; + lock_t *prev = NULL; + + while (hash && + wsrep_thd_is_brute_force(hash->trx->mysql_thd) && + wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){ + prev = hash; + hash = hash->hash; + } + lock->hash = hash; + if (prev) { + prev->hash = lock; + } else { + c_lock->hash = lock; + } + /* + * delayed conflict resolution '...kill_one_trx' was not called, + * if victim was waiting for some other lock + */ + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + trx->que_state = TRX_QUE_LOCK_WAIT; + lock_set_lock_and_trx_wait(lock, trx); + + lock_cancel_waiting_and_release(c_lock->trx->wait_lock); + + /* trx might not wait for c_lock, but some other lock */ + if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + } + if (c_lock->trx->wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) + fprintf(stderr, "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + /* have to bail out here to avoid lock_set_lock... */ + return(lock); + } + } else { + HASH_INSERT(lock_t, hash, lock_sys->rec_hash, + lock_rec_fold(space, page_no), lock); + } +#else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); +#endif if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { lock_set_lock_and_trx_wait(lock, trx); @@ -1749,6 +1845,9 @@ static enum db_err lock_rec_enqueue_waiting( /*=====================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode this transaction is requesting: LOCK_S or LOCK_X, possibly @@ -1800,8 +1899,16 @@ lock_rec_enqueue_waiting( } /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_rec_create(c_lock, type_mode | LOCK_WAIT, + block, heap_no, index, trx); +#else lock = lock_rec_create(type_mode | LOCK_WAIT, block, heap_no, index, trx); +#endif /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ @@ -1879,7 +1986,19 @@ lock_rec_add_to_queue( lock_t* other_lock = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT, block, heap_no, trx); +#ifdef WITH_WSREP + /* this can potentionally assert with wsrep */ + if (wsrep_on(trx->mysql_thd)) { + if (wsrep_debug && other_lock) { + fprintf(stderr, + "WSREP: InnoDB assert ignored\n"); + } + } else { + ut_a(!other_lock); + } +#else ut_a(!other_lock); +#endif /* WITH_WSREP */ } #endif /* UNIV_DEBUG */ @@ -1932,7 +2051,11 @@ lock_rec_add_to_queue( } somebody_waits: +#ifdef WITH_WSREP + return(lock_rec_create(NULL, type_mode, block, heap_no, index, trx)); +#else return(lock_rec_create(type_mode, block, heap_no, index, trx)); +#endif } /** Record locking request status */ @@ -1982,6 +2105,10 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); lock = lock_rec_get_first_on_page(block); @@ -1990,7 +2117,11 @@ lock_rec_lock_fast( if (lock == NULL) { if (!impl) { +#ifdef WITH_WSREP + lock_rec_create(NULL, mode, block, heap_no, index, trx); +#else lock_rec_create(mode, block, heap_no, index, trx); +#endif } return(LOCK_REC_SUCCESS_CREATED); @@ -2046,6 +2177,9 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S @@ -2056,6 +2190,10 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2064,14 +2202,24 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ +#ifdef WITH_WSREP + } else if ((c_lock = lock_rec_other_has_conflicting( + mode, block, heap_no, trx))) { +#else } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { +#endif /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the record, we have to wait. */ +#ifdef WITH_WSREP + return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no, + index, thr)); +#else return(lock_rec_enqueue_waiting(mode, block, heap_no, index, thr)); +#endif } else if (!impl) { /* Set the requested lock on the record */ @@ -2117,8 +2265,16 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); - +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { + mode |= WSREP_BF; + } +#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3487,6 +3643,34 @@ lock_deadlock_recursive( stderr); } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP + if (wsrep_debug) + fputs("WSREP: Deadlock detected\n", ef); + if (wsrep_thd_is_brute_force(start->mysql_thd) && + wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd) && + (start != wait_lock->trx)) { + + if (wsrep_trx_order_before( + start->mysql_thd, + wait_lock->trx->mysql_thd)) { + + wait_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(wait_lock); + return(LOCK_VICTIM_IS_OTHER); + } else { + return(LOCK_VICTIM_IS_START); + } + } +#endif + if (too_far) { + + fputs("TOO DEEP OR LONG SEARCH" + " IN THE LOCK TABLE" + " WAITS-FOR GRAPH\n", ef); + + return(LOCK_VICTIM_IS_START); + } if (trx_weight_ge(wait_lock->trx, start)) { /* Our recursion starting point @@ -3494,8 +3678,21 @@ lock_deadlock_recursive( choose 'start' as the victim and roll back it */ +#ifdef WITH_WSREP + if (!wsrep_thd_is_brute_force( + start->mysql_thd)) { + return(LOCK_VICTIM_IS_START); + } +#else + return(LOCK_VICTIM_IS_START); +#endif + } +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd)) { return(LOCK_VICTIM_IS_START); } +#endif lock_deadlock_found = TRUE; @@ -3580,6 +3777,9 @@ UNIV_INLINE lock_t* lock_table_create( /*==============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif dict_table_t* table, /*!< in: database table in dictionary cache */ ulint type_mode,/*!< in: lock mode possibly ORed with LOCK_WAIT */ @@ -3615,7 +3815,25 @@ lock_table_create( lock->un_member.tab_lock.table = table; +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + UT_LIST_INSERT_AFTER( + un_member.tab_lock.locks, table->locks, c_lock, lock); + } else { + UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); + } + + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", + (ulonglong) lock->trx->id); + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(c_lock); + } + +#else UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); +#endif if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -3761,6 +3979,9 @@ static ulint lock_table_enqueue_waiting( /*=======================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint mode, /*!< in: lock mode this transaction is requesting */ dict_table_t* table, /*!< in: table */ @@ -3802,7 +4023,14 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx); +#else lock = lock_table_create(table, mode | LOCK_WAIT, trx); +#endif /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ @@ -3861,7 +4089,32 @@ lock_table_other_has_incompatible( && (!lock_mode_compatible(lock_get_mode(lock), mode)) && (wait || !(lock_get_wait(lock)))) { +#ifdef WITH_WSREP + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = wsrep_thd_is_brute_force( + lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && + wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd) + ) + ) { + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) fprintf(stderr, + "WSREP: BF victim waiting"); + return(lock); + } else { + if (bf_this && bf_other) + wsrep_innobase_kill_one_trx( + (trx_t *)trx, lock->trx, TRUE); + return(lock); + } + } else { + return(lock); + } +#else return(lock); +#endif } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); @@ -3884,6 +4137,9 @@ lock_table( enum lock_mode mode, /*!< in: lock mode */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + lock_t *c_lock; +#endif trx_t* trx; ulint err; @@ -3912,19 +4168,32 @@ lock_table( /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ +#ifdef WITH_WSREP + if ((c_lock = (lock_t *)lock_table_other_has_incompatible( + trx, LOCK_WAIT, table, mode))) { +#else if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) { +#endif /* Another trx has a request on the table in an incompatible mode: this trx may have to wait */ +#ifdef WITH_WSREP + err = lock_table_enqueue_waiting(c_lock, mode | flags, table, thr); +#else err = lock_table_enqueue_waiting(mode | flags, table, thr); +#endif lock_mutex_exit_kernel(); return(err); } +#ifdef WITH_WSREP + lock_table_create(c_lock, table, mode | flags, trx); +#else lock_table_create(table, mode | flags, trx); +#endif ut_a(!flags || mode == LOCK_S || mode == LOCK_X); @@ -4840,6 +5109,7 @@ lock_rec_queue_validate( if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { +#ifndef WITH_WSREP enum lock_mode mode; if (lock_get_mode(lock) == LOCK_S) { @@ -4849,6 +5119,7 @@ lock_rec_queue_validate( } ut_a(!lock_rec_other_has_expl_req( mode, 0, 0, block, heap_no, lock->trx)); +#endif /* WITH_WSREP */ } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { @@ -5089,6 +5360,9 @@ lock_rec_insert_check_and_lock( lock_t* lock; ulint err; ulint next_rec_heap_no; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(block->frame == page_align(rec)); @@ -5141,15 +5415,28 @@ lock_rec_insert_check_and_lock( had to wait for their insert. Both had waiting gap type lock requests on the successor, which produced an unnecessary deadlock. */ +#ifdef WITH_WSREP + if ((c_lock = lock_rec_other_has_conflicting( + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF, + block, next_rec_heap_no, trx))) { +#else if (lock_rec_other_has_conflicting( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, trx)) { +#endif /* Note that we may get DB_SUCCESS also here! */ +#ifdef WITH_WSREP + err = lock_rec_enqueue_waiting(c_lock, LOCK_X | LOCK_GAP + | LOCK_INSERT_INTENTION, + block, next_rec_heap_no, + index, thr); +#else err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, index, thr); +#endif } else { err = DB_SUCCESS; } diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 502cb44a0fa..a9069708e98 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -89,6 +89,12 @@ UNIV_INTERN os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES]; /* In simulated aio, merge at most this many consecutive i/os */ #define OS_AIO_MERGE_N_CONSECUTIVE 64 +#ifdef WITH_INNODB_DISALLOW_WRITES +#define WAIT_ALLOW_WRITES() os_event_wait(srv_allow_writes_event) +#else +#define WAIT_ALLOW_WRITES() do { } while (0) +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /********************************************************************** InnoDB AIO Implementation: @@ -724,7 +730,9 @@ os_file_create_tmpfile(void) /*========================*/ { FILE* file = NULL; - int fd = innobase_mysql_tmpfile(); + int fd; + WAIT_ALLOW_WRITES(); + fd = innobase_mysql_tmpfile(); if (fd >= 0) { file = fdopen(fd, "w+b"); @@ -1043,6 +1051,7 @@ os_file_create_directory( return (TRUE); #else int rcode; + WAIT_ALLOW_WRITES(); rcode = mkdir(pathname, 0770); @@ -1144,6 +1153,8 @@ try_again: os_file_t file; int create_flag; ibool retry; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); try_again: ut_a(name); @@ -1276,6 +1287,8 @@ os_file_create_simple_no_error_handling_func( int create_flag; ut_a(name); + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); if (create_mode == OS_FILE_OPEN) { if (access_type == OS_FILE_READ_ONLY) { @@ -1509,6 +1522,8 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); try_again: ut_a(name); @@ -1665,6 +1680,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1728,6 +1744,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1768,6 +1785,7 @@ os_file_rename_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); ret = rename(oldpath, newpath); @@ -2031,6 +2049,7 @@ os_file_set_eof( HANDLE h = (HANDLE) _get_osfhandle(fileno(file)); return(SetEndOfFile(h)); #else /* __WIN__ */ + WAIT_ALLOW_WRITES(); return(!ftruncate(fileno(file), ftell(file))); #endif /* __WIN__ */ } @@ -2125,6 +2144,7 @@ os_file_flush_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); #if defined(HAVE_DARWIN_THREADS) # ifndef F_FULLFSYNC @@ -2817,6 +2837,7 @@ retry: return(FALSE); #else ssize_t ret; + WAIT_ALLOW_WRITES(); ret = os_file_pwrite(file, buf, n, offset, offset_high); diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 30fc28561fa..9ba1c646d9d 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -31,6 +31,9 @@ Created 5/30/1994 Heikki Tuuri #include "mtr0mtr.h" #include "mtr0log.h" +#ifdef WITH_WSREP +#include +#endif /* WITH_WSREP */ /* PHYSICAL RECORD (OLD STYLE) =========================== @@ -1772,3 +1775,72 @@ rec_print( } } #endif /* !UNIV_HOTBACKUP */ +#ifdef WITH_WSREP +int +wsrep_rec_get_primary_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index) /* in: record descriptor */ +{ + const byte* data; + ulint len; + ulint key_len = 0; + ulint i; + uint key_parts; + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + + ut_ad(index); + key_parts = dict_index_get_n_unique_in_tree(index); + *offsets_ = (sizeof offsets_) / sizeof *offsets_; + + rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + ut_ad(rec_offs_validate(rec, NULL, offsets_)); + + ut_ad(rec); + + for (i = 0; i < key_parts; i++) { + dict_field_t* field = dict_index_get_nth_field(index, i); + const dict_col_t* col = dict_field_get_col(field); + + data = rec_get_nth_field(rec, offsets_, i, &len); + if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? + *buf_len : *buf_len - 1)) { + fprintf (stderr, + "WSREP: FK key len exceeded %lu %lu %lu\n", + key_len, len, *buf_len); + goto err_out; + } + + if (len == UNIV_SQL_NULL) { + ut_a(!(col->prtype & DATA_NOT_NULL)); + *buf++ = 1; + key_len++; + } else { + if (!(col->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col->prtype), + buf, len); + key_len += len; + buf += len; + } + } + + rec_validate(rec, offsets_); + *buf_len = key_len; + return DB_SUCCESS; + + err_out: + return DB_ERROR; +} +#endif // WITH_WSREP diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 67846ab6f69..19da93f55eb 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -752,6 +752,13 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); mem_free(buf); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool shared); +#endif /* WITH_WSREP */ /*********************************************************************//** Perform referential actions or checks when a parent row is deleted or updated @@ -1068,6 +1075,16 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); +#ifdef WITH_WSREP + if (err == DB_SUCCESS) { + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE); + } +#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" @@ -1397,7 +1414,14 @@ run_again: if (check_ref) { err = DB_SUCCESS; - +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + TRUE); +#endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE @@ -1649,6 +1673,9 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + trx_t* trx = thr_get_trx(thr); +#endif ulint n_unique; ulint i; int cmp; @@ -1702,7 +1729,14 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + /* slave applier must not get duplicate error */ + if (allow_duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (allow_duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1820,7 +1854,13 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1864,7 +1904,13 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index bda086f4778..04370e8fe13 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -86,6 +86,10 @@ Created 10/8/1995 Heikki Tuuri #include "mysql/plugin.h" #include "mysql/service_thd_wait.h" +#ifdef WITH_WSREP +extern int wsrep_debug; +extern int wsrep_trx_is_aborting(void *thd_ptr); +#endif /* The following counter is incremented whenever there is some user activity in the server */ UNIV_INTERN ulint srv_activity_count = 0; @@ -198,6 +202,10 @@ srv_printf_innodb_monitor() will request mutex acquisition with mutex_enter(), which will wait until it gets the mutex. */ #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) +#ifdef WITH_INNODB_DISALLOW_WRITES +UNIV_INTERN os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /** The sort order table of the MySQL latin1_swedish_ci character set collation */ UNIV_INTERN const byte* srv_latin1_ordering; @@ -368,6 +376,9 @@ struct srv_conc_slot_struct{ free to proceed; but reserved may still be TRUE at that point */ +#ifdef WITH_WSREP + void *thd; /*!< to see priority */ +#endif UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /*!< queue node */ }; @@ -1075,8 +1086,20 @@ srv_init(void) conc_slot->reserved = FALSE; conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); +#ifdef WITH_WSREP + conc_slot->thd = NULL; +#endif /* WITH_WSREP */ } +#ifdef WITH_INNODB_DISALLOW_WRITES + /* Writes have to be enabled on init or else we hang. Thus, we + always set the event here regardless of innobase_disallow_writes. + That flag will always be 0 at this point because it isn't settable + via my.cnf or command line arg. */ + srv_allow_writes_event = os_event_create(NULL); + os_event_set(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); } @@ -1162,6 +1185,18 @@ srv_conc_enter_innodb( return; } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } +#endif os_fast_mutex_lock(&srv_conc_mutex); retry: if (trx->declared_to_be_inside_innodb) { @@ -1254,6 +1289,9 @@ retry: /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; +#ifdef WITH_WSREP + slot->thd = trx->mysql_thd; +#endif UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); @@ -1286,6 +1324,9 @@ retry: incremented the thread counter on behalf of this thread */ slot->reserved = FALSE; +#ifdef WITH_WSREP + slot->thd = NULL; +#endif UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); @@ -1356,6 +1397,9 @@ srv_conc_force_exit_innodb( trx->n_tickets_to_enter_innodb = 0; if (srv_conc_n_threads < (lint)srv_thread_concurrency) { +#ifdef WITH_WSREP + srv_conc_slot_t* wsrep_slot; +#endif /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ @@ -1365,6 +1409,19 @@ srv_conc_force_exit_innodb( slot = UT_LIST_GET_NEXT(srv_conc_queue, slot); } +#ifdef WITH_WSREP + /* look for aborting trx, they must be released asap */ + wsrep_slot= slot; + while (wsrep_slot && (wsrep_slot->wait_ended == TRUE || + !wsrep_trx_is_aborting(wsrep_slot->thd))) { + wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot); + } + if (wsrep_slot) { + slot = wsrep_slot; + if (wsrep_debug) + fprintf(stderr, "WSREP: releasing aborting thd\n"); + } +#endif if (slot != NULL) { slot->wait_ended = TRUE; @@ -1737,7 +1794,20 @@ srv_suspend_mysql_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + fprintf(stderr, + "WSREP: BF long lock wait ended after %.f sec\n", + wait_time); + srv_print_innodb_monitor = FALSE; + srv_print_innodb_lock_monitor = FALSE; + } else { +#endif trx->error_state = DB_LOCK_WAIT_TIMEOUT; +#ifdef WITH_WSREP + } +#endif } if (trx_is_interrupted(trx)) { @@ -2256,6 +2326,27 @@ exit_func: OS_THREAD_DUMMY_RETURN; } +#ifdef WITH_WSREP +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + srv_slot_t* slot) /* in: lock slot to check for lock priority */ +{ + if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && + wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_lock_timeout_thread_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ /*********************************************************************//** A thread which wakes up threads whose lock wait may have lasted too long. @return a dummy parameter */ @@ -2324,8 +2415,14 @@ loop: granted: in that case do nothing */ if (trx->wait_lock) { +#ifdef WITH_WSREP + if (!wsrep_is_BF_lock_timeout(slot)) { +#endif lock_cancel_waiting_and_release( trx->wait_lock); +#ifdef WITH_WSREP + } +#endif } } } @@ -2442,7 +2539,20 @@ loop: if (sync_array_print_long_waits(&waiter, &sema) && sema == old_sema && os_thread_eq(waiter, old_waiter)) { +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + if (srv_allow_writes_event->is_set) { +#endif /* WITH_WSREP */ fatal_cnt++; +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + } else { + fprintf(stderr, + "WSREP: avoiding InnoDB self crash due to long " + "semaphore wait of > %lu seconds\n" + "Server is processing SST donor operation, " + "fatal_cnt now: %lu", + (ulong) srv_fatal_semaphore_wait_threshold, fatal_cnt); + } +#endif /* WITH_WSREP */ if (fatal_cnt > 10) { fprintf(stderr, diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index b55471959ce..3db63469cbe 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -42,6 +42,9 @@ Created 3/26/1996 Heikki Tuuri #include "row0mysql.h" #include "lock0lock.h" #include "pars0pars.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" +#endif /* WITH_WSREP */ /** This many pages must be undone before a truncate is tried within rollback */ @@ -147,6 +150,12 @@ trx_rollback_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -174,6 +183,12 @@ trx_rollback_last_sql_stat_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -1123,6 +1138,12 @@ trx_rollback( srv_que_task_enqueue_low(thr); /* srv_que_task_enqueue_low(thr2); */ } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /****************************************************************//** @@ -1281,6 +1302,12 @@ trx_finish_rollback_off_kernel( sig = next_sig; } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /*********************************************************************//** diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index c0283448d10..5d8c967e323 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -44,6 +44,10 @@ Created 3/26/1996 Heikki Tuuri #include "os0file.h" #include "read0read.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" /* wsrep_is_wsrep_xid() */ +#endif /* */ + /** The file format tag structure with id and name. */ struct file_format_struct { ulint id; /*!< id of the file format */ @@ -791,6 +795,89 @@ trx_sys_print_mysql_binlog_offset(void) mtr_commit(&mtr); } +#ifdef WITH_WSREP + +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: transaction XID */ + mtr_t* mtr) /*!< in: mtr */ +{ + trx_sysf_t* sys_header; + + ut_ad(xid && mtr); + ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); + + sys_header = trx_sysf_get(mtr); + if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD) + != TRX_SYS_WSREP_XID_MAGIC_N) { + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD, + TRX_SYS_WSREP_XID_MAGIC_N, + MLOG_4BYTES, mtr); + } + + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_FORMAT, + (int)xid->formatID, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_GTRID_LEN, + (int)xid->gtrid_length, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_BQUAL_LEN, + (int)xid->bqual_length, + MLOG_4BYTES, mtr); + mlog_write_string(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_DATA, + (const unsigned char*) xid->data, + XIDDATASIZE, mtr); + +} + +void +trx_sys_read_wsrep_checkpoint(XID* xid) +/*===================================*/ +{ + trx_sysf_t* sys_header; + mtr_t mtr; + ulint magic; + + ut_ad(xid); + + mtr_start(&mtr); + + sys_header = trx_sysf_get(&mtr); + + if ((magic = mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + != TRX_SYS_WSREP_XID_MAGIC_N) { + memset(xid, 0, sizeof(*xid)); + xid->formatID = -1; + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return; + } + + xid->formatID = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_FORMAT); + xid->gtrid_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_GTRID_LEN); + xid->bqual_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_BQUAL_LEN); + ut_memcpy(xid->data, + sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA, + XIDDATASIZE); + + mtr_commit(&mtr); +} + +#endif /* WITH_WSREP */ + /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index ab7677b5b35..82f54b8295a 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -714,6 +714,11 @@ trx_start_low( trx->id = trx_sys_get_new_trx_id(); +#ifdef WITH_WSREP + memset(&trx->xid, 0, sizeof(trx->xid)); + trx->xid.formatID = -1; +#endif /* WITH_WSREP */ + /* The initial value for trx->no: IB_ULONGLONG_MAX is used in read_view_open_now: */ @@ -867,6 +872,14 @@ trx_write_serialisation_history( mutex_exit(&rseg->mutex); +#ifdef WITH_WSREP + /* Update latest MySQL wsrep XID in trx sys header. */ + if (wsrep_is_wsrep_xid(&trx->xid)) + { + trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + } +#endif /* WITH_WSREP */ + /* Update the latest MySQL binlog name and offset info in trx sys header if MySQL binlogging is on or the database server is a MySQL replication slave */ @@ -1064,6 +1077,12 @@ trx_commit_off_kernel( ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0); ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0); +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 7a51ecd8d2d..ae16bb24adf 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -97,6 +97,12 @@ extern "C" { #include "ha_prototypes.h" #include "ut0mem.h" #include "ibuf0ibuf.h" +#ifdef WITH_WSREP +#include "../storage/innobase/include/ut0byte.h" +#ifndef EXTRA_DEBUG + //#include "../storage/innobase/include/ut0byte.ic" +#endif /* EXTRA_DEBUG */ +#endif /* WITH_WSREP */ } #include "ha_innodb.h" @@ -114,6 +120,32 @@ extern ib_int64_t trx_sys_mysql_relay_log_pos; # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ +#ifdef WITH_WSREP +#include +#include +extern my_bool wsrep_certify_nonPK; +class binlog_trx_data; +extern handlerton *binlog_hton; + +extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; +extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; + +static inline wsrep_trx_handle_t* +wsrep_trx_handle(THD* thd, const trx_t* trx) { + return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), + (wsrep_trx_id_t)trx->id); +} + +extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len); + +#endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; static ulong commit_threads = 0; @@ -1018,6 +1050,15 @@ thd_to_trx( { return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr)); } +#ifdef WITH_WSREP +ulonglong +thd_to_trx_id( +/*=======*/ + THD* thd) /*!< in: MySQL thread */ +{ + return(thd_to_trx(thd)->id); +} +#endif /********************************************************************//** Call this function when mysqld passes control to the client. That is to @@ -1048,6 +1089,13 @@ innobase_release_temporary_latches( return(0); } +#ifdef 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 /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -1497,6 +1545,9 @@ int innobase_mysql_tmpfile(void) /*========================*/ { +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_wait(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ int fd2 = -1; File fd = mysql_tmpfile("ib"); if (fd >= 0) { @@ -2459,6 +2510,11 @@ innobase_init( innobase_hton->flags=HTON_NO_FLAGS; innobase_hton->release_temporary_latches=innobase_release_temporary_latches; innobase_hton->alter_table_flags = innobase_alter_table_flags; +#ifdef WITH_WSREP + innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; + innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; + innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; +#endif /* WITH_WSREP */ ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -3146,6 +3202,27 @@ innobase_commit_low( trx_commit_for_mysql(trx); } +#ifdef WITH_WSREP + THD* thd = (THD*)trx->mysql_thd; + const char* tmp = 0; + if (wsrep_on((void*)thd)) { +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, + "innobase_commit_low():trx_commit_for_mysql(%lld)", + (long long) wsrep_thd_trx_seqno(thd)); + tmp = thd_proc_info(thd, info); + +#else + tmp = thd_proc_info(thd, "innobase_commit_low()"); +#endif /* WSREP_PROC_INFO */ + } +#endif /* WITH_WSREP */ + trx_commit_for_mysql(trx); +#ifdef WITH_WSREP + if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } +#endif /* WITH_WSREP */ } /*****************************************************************//** @@ -3765,7 +3842,11 @@ ha_innobase::max_supported_key_length() const therefore set to slightly less than 1 / 4 of page size which is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ +#ifdef WITH_WSREP return(3500); +#else + return(3500); +#endif } /****************************************************************//** @@ -4694,7 +4775,96 @@ innobase_mysql_cmp( return(0); } +#ifdef WITH_WSREP +extern "C" UNIV_INTERN +void +wsrep_innobase_mysql_sort( +/*===============*/ + /* out: str contains sort string */ + int mysql_type, /* in: MySQL type */ + uint charset_number, /* in: number of the charset */ + unsigned char* str, /* in: data field */ + unsigned int str_length) /* in: data field length, + not UNIV_SQL_NULL */ +{ + CHARSET_INFO* charset; + enum_field_types mysql_tp; + DBUG_ASSERT(str_length != UNIV_SQL_NULL); + + mysql_tp = (enum_field_types) mysql_type; + + switch (mysql_tp) { + + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + { + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN]; + uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; + + /* Use the charset number to pick the right charset struct for + the comparison. Since the MySQL function get_charset may be + slow before Bar removes the mutex operation there, we first + look at 2 common charsets directly. */ + + if (charset_number == default_charset_info->number) { + charset = default_charset_info; + } else if (charset_number == my_charset_latin1.number) { + charset = &my_charset_latin1; + } else { + charset = get_charset(charset_number, MYF(MY_WME)); + + if (charset == NULL) { + sql_print_error("InnoDB needs charset %lu for doing " + "a comparison, but MySQL cannot " + "find that charset.", + (ulong) charset_number); + ut_a(0); + } + } + + ut_a(str_length <= tmp_length); + memcpy(tmp_str, str, str_length); + + tmp_length = charset->coll->strnxfrm(charset, str, str_length, + tmp_str, tmp_length); + DBUG_ASSERT(tmp_length == str_length); + + break; + } + case MYSQL_TYPE_DECIMAL : + case MYSQL_TYPE_TINY : + case MYSQL_TYPE_SHORT : + case MYSQL_TYPE_LONG : + case MYSQL_TYPE_FLOAT : + case MYSQL_TYPE_DOUBLE : + case MYSQL_TYPE_NULL : + case MYSQL_TYPE_TIMESTAMP : + case MYSQL_TYPE_LONGLONG : + case MYSQL_TYPE_INT24 : + case MYSQL_TYPE_DATE : + case MYSQL_TYPE_TIME : + case MYSQL_TYPE_DATETIME : + case MYSQL_TYPE_YEAR : + case MYSQL_TYPE_NEWDATE : + case MYSQL_TYPE_NEWDECIMAL : + case MYSQL_TYPE_ENUM : + case MYSQL_TYPE_SET : + case MYSQL_TYPE_GEOMETRY : + break; + default: + break; + } + + return; +} +#endif // WITH_WSREP /**************************************************************//** Converts a MySQL type to an InnoDB type. Note that this function returns the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1 @@ -4848,6 +5018,256 @@ innobase_read_from_2_little_endian( /*******************************************************************//** Stores a key value for a row to a buffer. @return key value length as stored in buff */ +#ifdef WITH_WSREP +UNIV_INTERN +uint +wsrep_store_key_val_for_row( +/*===============================*/ + TABLE* table, + uint keynr, /*!< in: key number */ + char* buff, /*!< in/out: buffer for the key value (in MySQL + format) */ + uint buff_len,/*!< in: buffer length */ + const uchar* record, + ibool* key_is_null)/*!< out: full key was null */ +{ + KEY* key_info = table->key_info + keynr; + KEY_PART_INFO* key_part = key_info->key_part; + KEY_PART_INFO* end = key_part + key_info->key_parts; + char* buff_start = buff; + enum_field_types mysql_type; + Field* field; + + DBUG_ENTER("store_key_val_for_row"); + + bzero(buff, buff_len); + *key_is_null = TRUE; + + for (; key_part != end; key_part++) { + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; + ibool part_is_null = FALSE; + + if (key_part->null_bit) { + if (record[key_part->null_offset] & + key_part->null_bit) { + *buff = 1; + part_is_null = TRUE; + } else { + *buff = 0; + } + buff++; + } + if (!part_is_null) *key_is_null = FALSE; + + field = key_part->field; + mysql_type = field->type(); + + if (mysql_type == MYSQL_TYPE_VARCHAR) { + /* >= 5.0.3 true VARCHAR */ + ulint lenlen; + ulint len; + const byte* data; + ulint key_len; + ulint true_len; + CHARSET_INFO* cs; + int error=0; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + cs = field->charset(); + + lenlen = (ulint) + (((Field_varstring*)field)->length_bytes); + + data = row_mysql_read_true_varchar(&len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + lenlen); + + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* In a column prefix index, we may need to truncate + the stored value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the true VARCHAR in the key value, though + only len first bytes after the 2 length bytes contain + actual data. The rest of the space was reset to zero + in the bzero() call above. */ + + buff += key_len; + + } else if (mysql_type == MYSQL_TYPE_TINY_BLOB + || mysql_type == MYSQL_TYPE_MEDIUM_BLOB + || mysql_type == MYSQL_TYPE_BLOB + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { + + CHARSET_INFO* cs; + ulint key_len; + ulint true_len; + int error=0; + ulint blob_len; + const byte* blob_data; + + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + + cs = field->charset(); + + blob_data = row_mysql_read_blob_ref(&blob_len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + (ulint) field->pack_length()); + + true_len = blob_len; + + ut_a(get_field_offset(table, field) + == key_part->offset); + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* All indexes on BLOB and TEXT are column prefix + indexes, and we may need to truncate the data to be + stored in the key value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, blob_data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + memcpy(buff, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the BLOB prefix in the key value. */ + + buff += key_len; + } else { + /* Here we handle all other data types except the + true VARCHAR, BLOB and TEXT. Note that the column + value we store may be also in a column prefix + index. */ + + CHARSET_INFO* cs; + ulint true_len; + ulint key_len; + const uchar* src_start; + int error=0; + enum_field_types real_type; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len; + + continue; + } + + src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; + + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != MYSQL_TYPE_ENUM + && real_type != MYSQL_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + memcpy(sorted, src_start, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + memcpy(buff, sorted, true_len); + } else { + memcpy(buff, src_start, true_len); + } + buff += true_len; + + /* Pad the unused space with spaces. */ + + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + ut_a(!(pad_len % cs->mbminlen)); + + cs->cset->fill(cs, buff, pad_len, + 0x20 /* space */); + buff += pad_len; + } + } + } + + ut_a(buff <= buff_start + buff_len); + + DBUG_RETURN((uint)(buff - buff_start)); +} +#endif /* WITH_WSREP */ UNIV_INTERN uint ha_innobase::store_key_val_for_row( @@ -5658,6 +6078,9 @@ ha_innobase::write_row( ulint error = 0; int error_result= 0; ibool auto_inc_used= FALSE; +#ifdef WITH_WSREP + ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ +#endif ulint sql_command; trx_t* trx = thd_to_trx(user_thd); @@ -5692,8 +6115,14 @@ ha_innobase::write_row( if ((sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX +#ifdef WITH_WSREP + || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) +#endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { +#ifdef WITH_WSREP + WSREP_DEBUG("forced commit: %s", wsrep_thd_query(user_thd)); +#endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. As this method will be called on a temporary table where the @@ -5765,7 +6194,9 @@ no_commit: /* Reset the error code before calling innobase_get_auto_increment(). */ prebuilt->autoinc_error = DB_SUCCESS; - +#ifdef WITH_WSREP + auto_inc_inserted= (table->next_number_field->val_int() == 0); +#endif if ((error = update_auto_increment())) { /* We don't want to mask autoinc overflow errors. */ @@ -5849,6 +6280,30 @@ no_commit: case SQLCOM_REPLACE_SELECT: goto set_max_autoinc; +#ifdef WITH_WSREP + /* workaround for LP bug #355000, retrying the insert */ + case SQLCOM_INSERT: + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + !thd_test_options(current_thd, + OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)) { + WSREP_DEBUG( + "retrying insert: %s", + (*wsrep_thd_query(current_thd)) ? + wsrep_thd_query(current_thd) : + (char *)"void"); + error= DB_SUCCESS; + wsrep_thd_set_conflict_state( + current_thd, MUST_ABORT); + innodb_srv_conc_exit_innodb(prebuilt->trx); + /* jump straight to func exit over + * later wsrep hooks */ + goto func_exit; + } + break; +#endif default: break; } @@ -5896,6 +6351,20 @@ report_error: error_result = convert_error_code_to_mysql((int) error, prebuilt->table->flags, user_thd); +#ifdef WITH_WSREP + if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && + (sql_command != SQLCOM_LOAD || + thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif func_exit: innobase_active_small(); @@ -6181,6 +6650,20 @@ ha_innobase::update_row( DBUG_RETURN(HA_ERR_CRASHED); } +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + DBUG_PRINT("wsrep", ("update row key")); + + if (wsrep_append_keys(user_thd, false, old_row, new_row)) { + DBUG_PRINT("wsrep", ("row key failed")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -6236,6 +6719,18 @@ ha_innobase::delete_row( DBUG_RETURN(HA_ERR_CRASHED); } +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("delete fail")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -7054,7 +7549,240 @@ ha_innobase::rnd_pos( DBUG_RETURN(error); } +#ifdef WITH_WSREP +extern "C" { +ulint +wsrep_append_foreign_key( +/*===========================*/ + trx_t* trx, /*!< in: trx */ + dict_foreign_t* foreign, /*!< in: foreign key constraint */ + const rec_t* clust_rec, /*!mysql_thd; + ulint rcode = DB_SUCCESS; + char cache_key[512] = {'\0'}; + if (!wsrep_on(trx->mysql_thd) || + wsrep_thd_exec_mode(thd) != LOCAL_STATE) + return DB_SUCCESS; + + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; + + if (!dict_index_is_clust(clust_index)) { + WSREP_ERROR("clustered index not passed for FK append"); + return DB_ERROR; + } + + key[0] = '\0'; + rcode = wsrep_rec_get_primary_key( + &key[1], &len, clust_rec, clust_index); + if (rcode != DB_SUCCESS) { + WSREP_ERROR("FK key set failed: %lu", rcode); + return rcode; + } +#ifdef WSREP_DEBUG_PRINT + ulint i; + fprintf(stderr, "FK parent key, len: %lu ", len+1); + for (i=0; iforeign_table->name, 512); + char *p = strchr(cache_key, '/'); + if (p) { + *p = '\0'; + } else { + WSREP_WARN("unexpected foreign key table %s", + foreign->foreign_table->name); + } + + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)cache_key, + strlen(foreign->foreign_table->name) + 1, + (const uchar*)key, len+1, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + return DB_ERROR; + } + + return DB_SUCCESS; +} +} + +static int +wsrep_append_key( +/*==================*/ + THD *thd, + trx_t *trx, + TABLE_SHARE *table_share, + TABLE *table, + const char* key, + uint16_t key_len, + bool shared +) +{ + DBUG_ENTER("wsrep_append_key"); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + (shared) ? "Shared" : "Exclusive", + wsrep_thd_thread_id(thd), trx->id, key_len, + table_share->table_name.str); + for (int i=0; itable_cache_key.str, + table_share->table_cache_key.length, + (const uchar*)key, key_len, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } + + int rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + DBUG_RETURN(rcode); + } + DBUG_RETURN(0); +} +int +ha_innobase::wsrep_append_keys( +/*==================*/ + THD *thd, + bool shared, + const uchar* record0, /* in: row in MySQL format */ + const uchar* record1) /* in: row in MySQL format */ +{ + DBUG_ENTER("wsrep_append_keys"); + trx_t *trx = thd_to_trx(thd); + + /* if no PK, calculate hash of full row, to be the key value */ + if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + MY_MD5_HASH(digest, (uchar *)record0, table->s->reclength); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + if (record1) { + MY_MD5_HASH(digest, (uchar *)record1, table->s->reclength); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + } else if (wsrep_protocol_version == 0) { + uint len; + char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key = &keyval[0]; + KEY *key_info = table->key_info; + ibool is_null; + + len = wsrep_store_key_val_for_row( + table, 0, key, key_info->key_length, record0, &is_null); + + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, keyval, + len, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped (proto 0): %s", + wsrep_thd_query(thd)); + } + } else { + ut_a(table->s->keys <= 256); + uint i; + for (i=0; is->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; + + keyval0[0] = (char)i; + keyval1[0] = (char)i; + + if (key_info->flags & HA_NOSAME) { + len = wsrep_store_key_val_for_row( + table, i, key0, key_info->key_length, + record0, &is_null); + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, + keyval0, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } + if (record1) { + len = wsrep_store_key_val_for_row( + table, i, key1, key_info->key_length, + record1, &is_null); + if (!is_null && memcmp(key0, key1, len)) { + int rcode = wsrep_append_key( + thd, trx, table_share, + table, + keyval1, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + } + } + } + } + DBUG_RETURN(0); +} +#endif /*********************************************************************//** Stores a reference to the current row to 'ref' field of the handle. Note that in the case where we have generated the clustered index for the @@ -10012,11 +10740,18 @@ ha_innobase::external_lock( /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = 1;); if (!skip) { +#ifdef WITH_WSREP + if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when " "transaction isolation level is " "READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } } @@ -12139,6 +12874,256 @@ static SHOW_VAR innodb_status_variables_export[]= { static struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +#ifdef WITH_WSREP +void +wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) +{ + WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " + "caused by:\n\t" + "1) unsupported configuration options combination, please check documentation.\n\t" + "2) a bug in the code.\n\t" + "3) a database corruption.\n Node consistency compromized, " + "need to abort. Restart the node to resync with cluster.", + (long long)bf_seqno, (long long)victim_seqno); + abort(); +} +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) +{ + DBUG_ENTER("wsrep_innobase_kill_one_trx"); + THD *thd = (THD *) victim_trx->mysql_thd; + THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + + if (!thd) { + DBUG_PRINT("wsrep", ("no thd for conflicting lock")); + WSREP_WARN("no THD for trx: %llu", victim_trx->id); + DBUG_RETURN(1); + } + + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", + signal, (long long)bf_seqno, + wsrep_thd_thread_id(thd), + victim_trx->id); + + WSREP_DEBUG("Aborting query: %s", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); + + wsrep_thd_LOCK(thd); + + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { + WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + } + if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + WSREP_DEBUG("withdraw for BF trx: %llu, state: %d", + victim_trx->id, + wsrep_thd_conflict_state(thd)); + } + + switch (wsrep_thd_conflict_state(thd)) { + case NO_CONFLICT: + wsrep_thd_set_conflict_state(thd, MUST_ABORT); + break; + case MUST_ABORT: + WSREP_DEBUG("victim %llu 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 %llu in state %d", + victim_trx->id, wsrep_thd_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 trx QUERY_COMMITTING for %llu", + victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } else { + rcode = wsrep->abort_pre_commit( + wsrep, bf_seqno, + (wsrep_trx_id_t)victim_trx->id + ); + + switch (rcode) { + case WSREP_WARNING: + WSREP_DEBUG("cancel commit warning: %llu", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(1); + break; + case WSREP_OK: + break; + default: + WSREP_ERROR( + "cancel commit bad exit: %d %llu", + rcode, + victim_trx->id); + /* unable to interrupt, must abort */ + /* note: kill_mysql() will block, if we cannot. + * kill the lock holder first. + */ + abort(); + break; + } + } + 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 %llu", victim_trx->id); + + victim_trx->was_chosen_as_deadlock_victim= TRUE; + if (victim_trx->wait_lock) { + WSREP_DEBUG("victim has wait flag: %ld", + wsrep_thd_thread_id(thd)); + lock_t* wait_lock = victim_trx->wait_lock; + if (wait_lock) { + WSREP_DEBUG("canceling wait lock"); + victim_trx->was_chosen_as_deadlock_victim= TRUE; + lock_cancel_waiting_and_release(wait_lock); + } + + wsrep_thd_awake(thd, signal); + } else { + /* abort currently executing query */ + DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(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: + { + bool skip_abort= false; + wsrep_aborting_thd_t abortees; + + WSREP_DEBUG("kill IDLE for %llu", 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); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + + abortees = wsrep_aborting_thd; + while (abortees && !skip_abort) { + /* check if we have a kill message for this already */ + if (abortees->aborting_thd == thd) { + skip_abort = true; + WSREP_WARN("duplicate thd aborter %lu", + wsrep_thd_thread_id(thd)); + } + abortees = abortees->next; + } + if (!skip_abort) { + 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; + DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("enqueuing trx abort for (%lu)", + wsrep_thd_thread_id(thd)); + } + + DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); + WSREP_DEBUG("signaling aborter"); + mysql_cond_signal(&COND_wsrep_rollback); + mysql_mutex_unlock(&LOCK_wsrep_rollback); + + break; + } + default: + WSREP_WARN("bad wsrep query state: %d", + wsrep_thd_query_state(thd)); + break; + } + wsrep_thd_UNLOCK(thd); + + DBUG_RETURN(0); +} +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal) +{ + DBUG_ENTER("wsrep_innobase_abort_thd"); + 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", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd)); + + if (victim_trx) + { + mutex_enter(&kernel_mutex); + int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, + signal); + mutex_exit(&kernel_mutex); + 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); + } + DBUG_RETURN(-1); +} + +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + if (wsrep_is_wsrep_xid(xid)) { + mtr_t mtr; + mtr_start(&mtr); + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return 0; + } else { + return 1; + } +} + +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + trx_sys_read_wsrep_checkpoint(xid); + return 0; +} + +#endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -12570,6 +13555,40 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, NULL, NULL, 0, 0, 1, 0); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES +/******************************************************* + * innobase_disallow_writes variable definition * + *******************************************************/ + +/* Must always init to FALSE. */ +static my_bool innobase_disallow_writes = FALSE; + +/************************************************************************** +An "update" method for innobase_disallow_writes variable. */ +static +void +innobase_disallow_writes_update( +/*============================*/ + THD* thd, /* in: thread handle */ + st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* var_ptr, /* out: pointer to dynamic + variable */ + const void* save) /* in: temporary storage */ +{ + *(my_bool*)var_ptr = *(my_bool*)save; + ut_a(srv_allow_writes_event); + if (*(my_bool*)var_ptr) + os_event_reset(srv_allow_writes_event); + else + os_event_set(srv_allow_writes_event); +} + +static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, + PLUGIN_VAR_NOCMDOPT, + "Tell InnoDB to stop any writes to disk", + NULL, innobase_disallow_writes_update, FALSE); +#endif /* WITH_INNODB_DISALLOW_WRITES */ static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, "Whether to use read ahead for random access within an extent.", @@ -12848,6 +13867,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG MYSQL_SYSVAR(change_buffering_debug), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES + MYSQL_SYSVAR(disallow_writes), +#endif /* WITH_INNODB_DISALLOW_WRITES */ MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 7e11e72b7c1..5d0b4f75a3f 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -112,6 +112,10 @@ class ha_innobase: public handler dict_index_t* innobase_get_index(uint keynr); int info_low(uint flag, bool called_from_analyze); +#ifdef WITH_WSREP + int wsrep_append_keys(THD *thd, bool shared, + const uchar* record0, const uchar* record1); +#endif /* Init values for the class: */ public: ha_innobase(handlerton *hton, TABLE_SHARE *table_arg); @@ -368,6 +372,37 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd); */ extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); +#ifdef WITH_WSREP +#include +//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); + +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(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_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +#endif typedef struct trx_struct trx_t; /********************************************************************//** @file handler/ha_innodb.h @@ -408,3 +443,6 @@ innobase_index_name_is_reserved( ulint num_of_keys); /*!< in: Number of indexes to be created. */ +#ifdef WITH_WSREP +extern "C" int wsrep_trx_is_aborting(void *thd_ptr); +#endif diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 2fd05901393..ef802c0d373 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -37,6 +37,10 @@ extern "C" { #include "handler0alter.h" } +#ifdef WITH_WSREP +//#include "wsrep_api.h" +#include // PROCESS_ACL +#endif #include "ha_innodb.h" /*************************************************************//** diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 4701fcd87f9..7f7904f6a25 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -343,6 +343,9 @@ barracuda format, the length could be REC_VERSION_56_MAX_INDEX_COL_LEN /** Defines the maximum fixed length column size */ #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN +#ifdef WITH_WSREP +#define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500 +#endif /* WITH_WSREP */ /** Data structure for a field in an index */ struct dict_field_struct{ diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 2e200ba7f43..d5874a51cae 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -300,6 +300,19 @@ thd_flush_log_at_trx_commit( /*================================*/ void* thd); +#ifdef WITH_WSREP +UNIV_INTERN +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal); +int wsrep_thd_is_brute_force(void *thd_ptr); +int wsrep_trx_order_before(void *thd1, void *thd2); +void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length); +//UNIV_INTERN +int +wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); +#endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from mysqld.cc. We do a dirty read because for one there is no synchronization diff --git a/storage/xtradb/include/lock0lock.h b/storage/xtradb/include/lock0lock.h index ea636f985b4..f7c3d82e495 100644 --- a/storage/xtradb/include/lock0lock.h +++ b/storage/xtradb/include/lock0lock.h @@ -798,6 +798,7 @@ lock_rec_get_page_no( remains set when the waiting lock is granted, or if the lock is inherited to a neighboring record */ +#define WSREP_BF 4096 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION)&LOCK_MODE_MASK # error #endif diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h index 10b74d18c13..ab390f4fb3a 100644 --- a/storage/xtradb/include/rem0rec.h +++ b/storage/xtradb/include/rem0rec.h @@ -832,6 +832,13 @@ are given in one byte (resp. two byte) format. */ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) +#ifdef WITH_WSREP +int wsrep_rec_get_primary_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index); /* in: record descriptor */ +#endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" #endif diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index b660f7ea104..eeb5806de40 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -152,6 +152,10 @@ extern ulint srv_log_buffer_size; extern char srv_use_global_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +#ifdef WITH_INNODB_DISALLOW_WRITES +/* When this event is reset we do not allow any file writes to take place. */ +extern os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ /* If this flag is TRUE, then we will load the indexes' (and tables') metadata even if they are marked as "corrupted". Mostly it is for DBA to process corrupted index and table */ diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h index 495ce0e1184..0f12fc496b7 100644 --- a/storage/xtradb/include/trx0sys.h +++ b/storage/xtradb/include/trx0sys.h @@ -41,6 +41,9 @@ Created 3/26/1996 Heikki Tuuri #include "ut0bh.h" #include "read0types.h" #include "page0types.h" +#ifdef WITH_WSREP +#include "trx0xa.h" +#endif /* WITH_WSREP */ /** In a MySQL replication slave, in crash recovery we store the master log file name and position here. */ @@ -337,6 +340,17 @@ UNIV_INTERN void trx_sys_print_mysql_binlog_offset(void); /*===================================*/ +#ifdef WITH_WSREP +/** Update WSREP checkpoint XID in sys header. */ +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: WSREP XID */ + mtr_t* mtr); /*!< in: mtr */ +void +/** Read WSREP checkpoint XID from sys header. */ +trx_sys_read_wsrep_checkpoint( + XID* xid); /*!< out: WSREP XID */ +#endif /* WITH_WSREP */ /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ @@ -546,6 +560,22 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ +#ifdef WITH_WSREP +/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused + otherwise (see comments for MySQL bug #34058). */ +/** */ +#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO +#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 +#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 + +/* XID field: formatID, gtrid_len, bqual_len, xid_data */ +#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) +#define TRX_SYS_WSREP_XID_FORMAT 4 +#define TRX_SYS_WSREP_XID_GTRID_LEN 8 +#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 +#define TRX_SYS_WSREP_XID_DATA 16 +#endif /* WITH_WSREP*/ + /** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 5fce345d0fe..ff711195785 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -39,6 +39,9 @@ Created 5/7/1996 Heikki Tuuri #include "dict0mem.h" #include "trx0sys.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -921,6 +924,11 @@ lock_rec_has_to_wait( if (trx != lock2->trx && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, lock_get_mode(lock2))) { +#ifdef WITH_WSREP + if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { + return FALSE; + } +#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1450,6 +1458,11 @@ lock_rec_has_expl( return(NULL); } +#ifdef WITH_WSREP +static +void +lock_rec_discard(lock_t* in_lock); +#endif #ifdef UNIV_DEBUG /*********************************************************************//** Checks if some other transaction has a lock request in the queue. @@ -1499,6 +1512,27 @@ lock_rec_other_has_expl_req( } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP +static void +wsrep_kill_victim(trx_t *trx, lock_t *lock) { + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = + wsrep_thd_is_brute_force(lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd))) { + + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: BF victim waiting\n"); + /* cannot release lock, until our lock + is in the queue*/ + } else if (lock->trx != trx) { + wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE); + } + } +} +#endif /*********************************************************************//** Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. @@ -1528,6 +1562,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, TRUE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1538,6 +1575,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, FALSE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1669,6 +1709,9 @@ static lock_t* lock_rec_create( /*============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and replaced by LOCK_REC */ @@ -1714,6 +1757,11 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock->type_mode |= WSREP_BF; + } +#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1728,8 +1776,56 @@ lock_rec_create( /* Set the bit corresponding to rec */ lock_rec_set_nth_bit(lock, heap_no); +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock_t *hash = c_lock->hash; + lock_t *prev = NULL; + + while (hash && + wsrep_thd_is_brute_force(hash->trx->mysql_thd) && + wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){ + prev = hash; + hash = hash->hash; + } + lock->hash = hash; + if (prev) { + prev->hash = lock; + } else { + c_lock->hash = lock; + } + /* + * delayed conflict resolution '...kill_one_trx' was not called, + * if victim was waiting for some other lock + */ + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + trx->que_state = TRX_QUE_LOCK_WAIT; + lock_set_lock_and_trx_wait(lock, trx); + + lock_cancel_waiting_and_release(c_lock->trx->wait_lock); + + /* trx might not wait for c_lock, but some other lock */ + if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + } + if (c_lock->trx->wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) + fprintf(stderr, "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + /* have to bail out here to avoid lock_set_lock... */ + return(lock); + } + } else { + HASH_INSERT(lock_t, hash, lock_sys->rec_hash, + lock_rec_fold(space, page_no), lock); + } +#else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); +#endif lock_sys->rec_num++; if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -1750,6 +1846,9 @@ static enum db_err lock_rec_enqueue_waiting( /*=====================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode this transaction is requesting: LOCK_S or LOCK_X, possibly @@ -1802,8 +1901,16 @@ lock_rec_enqueue_waiting( } /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_rec_create(c_lock, type_mode | LOCK_WAIT, + block, heap_no, index, trx); +#else lock = lock_rec_create(type_mode | LOCK_WAIT, block, heap_no, index, trx); +#endif /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ @@ -1885,7 +1992,19 @@ lock_rec_add_to_queue( lock_t* other_lock = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT, block, heap_no, trx); +#ifdef WITH_WSREP + /* this can potentionally assert with wsrep */ + if (wsrep_on(trx->mysql_thd)) { + if (wsrep_debug && other_lock) { + fprintf(stderr, + "WSREP: InnoDB assert ignored\n"); + } + } else { + ut_a(!other_lock); + } +#else ut_a(!other_lock); +#endif /* WITH_WSREP */ } #endif /* UNIV_DEBUG */ @@ -1938,7 +2057,11 @@ lock_rec_add_to_queue( } somebody_waits: +#ifdef WITH_WSREP + return(lock_rec_create(NULL, type_mode, block, heap_no, index, trx)); +#else return(lock_rec_create(type_mode, block, heap_no, index, trx)); +#endif } /** Record locking request status */ @@ -1988,6 +2111,10 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); lock = lock_rec_get_first_on_page(block); @@ -1996,7 +2123,11 @@ lock_rec_lock_fast( if (lock == NULL) { if (!impl) { +#ifdef WITH_WSREP + lock_rec_create(NULL, mode, block, heap_no, index, trx); +#else lock_rec_create(mode, block, heap_no, index, trx); +#endif } return(LOCK_REC_SUCCESS_CREATED); @@ -2052,6 +2183,9 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S @@ -2062,6 +2196,10 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2070,14 +2208,24 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ +#ifdef WITH_WSREP + } else if ((c_lock = lock_rec_other_has_conflicting( + mode, block, heap_no, trx))) { +#else } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { +#endif /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the record, we have to wait. */ +#ifdef WITH_WSREP + return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no, + index, thr)); +#else return(lock_rec_enqueue_waiting(mode, block, heap_no, index, thr)); +#endif } else if (!impl) { /* Set the requested lock on the record */ @@ -2123,8 +2271,16 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) == WSREP_BF + || mode - (LOCK_MODE_MASK & mode) - LOCK_REC_NOT_GAP == WSREP_BF +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); - +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { + mode |= WSREP_BF; + } +#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3496,6 +3652,34 @@ lock_deadlock_recursive( stderr); } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP + if (wsrep_debug) + fputs("WSREP: Deadlock detected\n", ef); + if (wsrep_thd_is_brute_force(start->mysql_thd) && + wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd) && + (start != wait_lock->trx)) { + + if (wsrep_trx_order_before( + start->mysql_thd, + wait_lock->trx->mysql_thd)) { + + wait_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(wait_lock); + return(LOCK_VICTIM_IS_OTHER); + } else { + return(LOCK_VICTIM_IS_START); + } + } +#endif + if (too_far) { + + fputs("TOO DEEP OR LONG SEARCH" + " IN THE LOCK TABLE" + " WAITS-FOR GRAPH\n", ef); + + return(LOCK_VICTIM_IS_START); + } if (trx_weight_ge(wait_lock->trx, start)) { /* Our recursion starting point @@ -3503,8 +3687,21 @@ lock_deadlock_recursive( choose 'start' as the victim and roll back it */ +#ifdef WITH_WSREP + if (!wsrep_thd_is_brute_force( + start->mysql_thd)) { + return(LOCK_VICTIM_IS_START); + } +#else + return(LOCK_VICTIM_IS_START); +#endif + } +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd)) { return(LOCK_VICTIM_IS_START); } +#endif lock_deadlock_found = TRUE; @@ -3589,6 +3786,9 @@ UNIV_INLINE lock_t* lock_table_create( /*==============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif dict_table_t* table, /*!< in: database table in dictionary cache */ ulint type_mode,/*!< in: lock mode possibly ORed with LOCK_WAIT */ @@ -3624,7 +3824,25 @@ lock_table_create( lock->un_member.tab_lock.table = table; +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + UT_LIST_INSERT_AFTER( + un_member.tab_lock.locks, table->locks, c_lock, lock); + } else { + UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); + } + + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", + (ulonglong) lock->trx->id); + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(c_lock); + } + +#else UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); +#endif if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -3770,6 +3988,9 @@ static ulint lock_table_enqueue_waiting( /*=======================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint mode, /*!< in: lock mode this transaction is requesting */ dict_table_t* table, /*!< in: table */ @@ -3812,7 +4033,14 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx); +#else lock = lock_table_create(table, mode | LOCK_WAIT, trx); +#endif /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ @@ -3875,7 +4103,32 @@ lock_table_other_has_incompatible( && (!lock_mode_compatible(lock_get_mode(lock), mode)) && (wait || !(lock_get_wait(lock)))) { +#ifdef WITH_WSREP + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = wsrep_thd_is_brute_force( + lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && + wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd) + ) + ) { + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) fprintf(stderr, + "WSREP: BF victim waiting"); + return(lock); + } else { + if (bf_this && bf_other) + wsrep_innobase_kill_one_trx( + (trx_t *)trx, lock->trx, TRUE); + return(lock); + } + } else { + return(lock); + } +#else return(lock); +#endif } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); @@ -3898,6 +4151,9 @@ lock_table( enum lock_mode mode, /*!< in: lock mode */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + lock_t *c_lock; +#endif trx_t* trx; ulint err; @@ -3930,19 +4186,32 @@ lock_table( /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ +#ifdef WITH_WSREP + if ((c_lock = (lock_t *)lock_table_other_has_incompatible( + trx, LOCK_WAIT, table, mode))) { +#else if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) { +#endif /* Another trx has a request on the table in an incompatible mode: this trx may have to wait */ +#ifdef WITH_WSREP + err = lock_table_enqueue_waiting(c_lock, mode | flags, table, thr); +#else err = lock_table_enqueue_waiting(mode | flags, table, thr); +#endif lock_mutex_exit_kernel(); return(err); } +#ifdef WITH_WSREP + lock_table_create(c_lock, table, mode | flags, trx); +#else lock_table_create(table, mode | flags, trx); +#endif ut_a(!flags || mode == LOCK_S || mode == LOCK_X); @@ -4860,6 +5129,7 @@ lock_rec_queue_validate( if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { +#ifndef WITH_WSREP enum lock_mode mode; if (lock_get_mode(lock) == LOCK_S) { @@ -4869,6 +5139,7 @@ lock_rec_queue_validate( } ut_a(!lock_rec_other_has_expl_req( mode, 0, 0, block, heap_no, lock->trx)); +#endif /* WITH_WSREP */ } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { @@ -5109,6 +5380,9 @@ lock_rec_insert_check_and_lock( lock_t* lock; ulint err; ulint next_rec_heap_no; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(block->frame == page_align(rec)); @@ -5166,15 +5440,28 @@ lock_rec_insert_check_and_lock( had to wait for their insert. Both had waiting gap type lock requests on the successor, which produced an unnecessary deadlock. */ +#ifdef WITH_WSREP + if ((c_lock = lock_rec_other_has_conflicting( + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF, + block, next_rec_heap_no, trx))) { +#else if (lock_rec_other_has_conflicting( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, trx)) { +#endif /* Note that we may get DB_SUCCESS also here! */ +#ifdef WITH_WSREP + err = lock_rec_enqueue_waiting(c_lock, LOCK_X | LOCK_GAP + | LOCK_INSERT_INTENTION, + block, next_rec_heap_no, + index, thr); +#else err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, index, thr); +#endif } else { err = DB_SUCCESS; } diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index ea7abb2549e..b0bfdc6c2bb 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -96,6 +96,12 @@ UNIV_INTERN os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES]; /* In simulated aio, merge at most this many consecutive i/os */ #define OS_AIO_MERGE_N_CONSECUTIVE 64 +#ifdef WITH_INNODB_DISALLOW_WRITES +#define WAIT_ALLOW_WRITES() os_event_wait(srv_allow_writes_event) +#else +#define WAIT_ALLOW_WRITES() do { } while (0) +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /********************************************************************** InnoDB AIO Implementation: @@ -816,7 +822,9 @@ os_file_create_tmpfile(void) /*========================*/ { FILE* file = NULL; - int fd = innobase_mysql_tmpfile(); + int fd; + WAIT_ALLOW_WRITES(); + fd = innobase_mysql_tmpfile(); if (fd >= 0) { file = fdopen(fd, "w+b"); @@ -1135,6 +1143,7 @@ os_file_create_directory( return (TRUE); #else int rcode; + WAIT_ALLOW_WRITES(); rcode = mkdir(pathname, 0770); @@ -1236,6 +1245,8 @@ try_again: os_file_t file; int create_flag; ibool retry; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); try_again: ut_a(name); @@ -1368,6 +1379,8 @@ os_file_create_simple_no_error_handling_func( int create_flag; ut_a(name); + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); if (create_mode == OS_FILE_OPEN) { if (access_type == OS_FILE_READ_ONLY) { @@ -1614,6 +1627,8 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); try_again: ut_a(name); @@ -1775,6 +1790,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1838,6 +1854,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1878,6 +1895,7 @@ os_file_rename_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); ret = rename(oldpath, newpath); @@ -2141,6 +2159,7 @@ os_file_set_eof( HANDLE h = (HANDLE) _get_osfhandle(fileno(file)); return(SetEndOfFile(h)); #else /* __WIN__ */ + WAIT_ALLOW_WRITES(); return(!ftruncate(fileno(file), ftell(file))); #endif /* __WIN__ */ } @@ -2249,6 +2268,7 @@ os_file_flush_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); #if defined(HAVE_DARWIN_THREADS) # ifndef F_FULLFSYNC @@ -2924,6 +2944,7 @@ retry: return(FALSE); #else ssize_t ret; + WAIT_ALLOW_WRITES(); ret = os_file_pwrite(file, buf, n, offset, offset_high); diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index 30fc28561fa..9ba1c646d9d 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -31,6 +31,9 @@ Created 5/30/1994 Heikki Tuuri #include "mtr0mtr.h" #include "mtr0log.h" +#ifdef WITH_WSREP +#include +#endif /* WITH_WSREP */ /* PHYSICAL RECORD (OLD STYLE) =========================== @@ -1772,3 +1775,72 @@ rec_print( } } #endif /* !UNIV_HOTBACKUP */ +#ifdef WITH_WSREP +int +wsrep_rec_get_primary_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index) /* in: record descriptor */ +{ + const byte* data; + ulint len; + ulint key_len = 0; + ulint i; + uint key_parts; + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + + ut_ad(index); + key_parts = dict_index_get_n_unique_in_tree(index); + *offsets_ = (sizeof offsets_) / sizeof *offsets_; + + rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + ut_ad(rec_offs_validate(rec, NULL, offsets_)); + + ut_ad(rec); + + for (i = 0; i < key_parts; i++) { + dict_field_t* field = dict_index_get_nth_field(index, i); + const dict_col_t* col = dict_field_get_col(field); + + data = rec_get_nth_field(rec, offsets_, i, &len); + if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? + *buf_len : *buf_len - 1)) { + fprintf (stderr, + "WSREP: FK key len exceeded %lu %lu %lu\n", + key_len, len, *buf_len); + goto err_out; + } + + if (len == UNIV_SQL_NULL) { + ut_a(!(col->prtype & DATA_NOT_NULL)); + *buf++ = 1; + key_len++; + } else { + if (!(col->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col->prtype), + buf, len); + key_len += len; + buf += len; + } + } + + rec_validate(rec, offsets_); + *buf_len = key_len; + return DB_SUCCESS; + + err_out: + return DB_ERROR; +} +#endif // WITH_WSREP diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index adc75bd5760..bc722d56203 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -752,6 +752,13 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); mem_free(buf); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool shared); +#endif /* WITH_WSREP */ /*********************************************************************//** Perform referential actions or checks when a parent row is deleted or updated @@ -1068,6 +1075,16 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); +#ifdef WITH_WSREP + if (err == DB_SUCCESS) { + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE); + } +#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" @@ -1403,7 +1420,14 @@ run_again: if (check_ref) { err = DB_SUCCESS; - +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + TRUE); +#endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE @@ -1660,6 +1684,9 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + trx_t* trx = thr_get_trx(thr); +#endif ulint n_unique; ulint i; int cmp; @@ -1713,7 +1740,14 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + /* slave applier must not get duplicate error */ + if (allow_duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (allow_duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1831,7 +1865,13 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1875,7 +1915,13 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 3476743a692..c8eefb56fef 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -96,6 +96,10 @@ ulong innobase_thd_get_thread_id(const void* thd); /* prototypes for new functions added to ha_innodb.cc */ ibool innobase_get_slow_log(); +#ifdef WITH_WSREP +extern int wsrep_debug; +extern int wsrep_trx_is_aborting(void *thd_ptr); +#endif /* The following counter is incremented whenever there is some user activity in the server */ UNIV_INTERN ulint srv_activity_count = 0; @@ -219,6 +223,10 @@ srv_printf_innodb_monitor() will request mutex acquisition with mutex_enter(), which will wait until it gets the mutex. */ #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) +#ifdef WITH_INNODB_DISALLOW_WRITES +UNIV_INTERN os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /** The sort order table of the MySQL latin1_swedish_ci character set collation */ UNIV_INTERN const byte* srv_latin1_ordering; @@ -405,6 +413,9 @@ struct srv_conc_slot_struct{ free to proceed; but reserved may still be TRUE at that point */ +#ifdef WITH_WSREP + void *thd; /*!< to see priority */ +#endif UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /*!< queue node */ }; @@ -1141,8 +1152,20 @@ srv_init(void) conc_slot->reserved = FALSE; conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); +#ifdef WITH_WSREP + conc_slot->thd = NULL; +#endif /* WITH_WSREP */ } +#ifdef WITH_INNODB_DISALLOW_WRITES + /* Writes have to be enabled on init or else we hang. Thus, we + always set the event here regardless of innobase_disallow_writes. + That flag will always be 0 at this point because it isn't settable + via my.cnf or command line arg. */ + srv_allow_writes_event = os_event_create(NULL); + os_event_set(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); } @@ -1308,6 +1331,18 @@ srv_conc_enter_innodb( } #endif +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } +#endif os_fast_mutex_lock(&srv_conc_mutex); retry: if (trx->declared_to_be_inside_innodb) { @@ -1401,6 +1436,9 @@ retry: /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; +#ifdef WITH_WSREP + slot->thd = trx->mysql_thd; +#endif UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); @@ -1447,6 +1485,9 @@ retry: incremented the thread counter on behalf of this thread */ slot->reserved = FALSE; +#ifdef WITH_WSREP + slot->thd = NULL; +#endif UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); @@ -1532,6 +1573,9 @@ srv_conc_force_exit_innodb( trx->n_tickets_to_enter_innodb = 0; if (srv_conc_n_threads < (lint)srv_thread_concurrency) { +#ifdef WITH_WSREP + srv_conc_slot_t* wsrep_slot; +#endif /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ @@ -1541,6 +1585,19 @@ srv_conc_force_exit_innodb( slot = UT_LIST_GET_NEXT(srv_conc_queue, slot); } +#ifdef WITH_WSREP + /* look for aborting trx, they must be released asap */ + wsrep_slot= slot; + while (wsrep_slot && (wsrep_slot->wait_ended == TRUE || + !wsrep_trx_is_aborting(wsrep_slot->thd))) { + wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot); + } + if (wsrep_slot) { + slot = wsrep_slot; + if (wsrep_debug) + fprintf(stderr, "WSREP: releasing aborting thd\n"); + } +#endif if (slot != NULL) { slot->wait_ended = TRUE; @@ -1913,7 +1970,20 @@ srv_suspend_mysql_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + fprintf(stderr, + "WSREP: BF long lock wait ended after %.f sec\n", + wait_time); + srv_print_innodb_monitor = FALSE; + srv_print_innodb_lock_monitor = FALSE; + } else { +#endif trx->error_state = DB_LOCK_WAIT_TIMEOUT; +#ifdef WITH_WSREP + } +#endif } if (trx_is_interrupted(trx)) { @@ -2646,6 +2716,27 @@ exit_func: OS_THREAD_DUMMY_RETURN; } +#ifdef WITH_WSREP +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + srv_slot_t* slot) /* in: lock slot to check for lock priority */ +{ + if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && + wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_lock_timeout_thread_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ /*********************************************************************//** A thread which wakes up threads whose lock wait may have lasted too long. @return a dummy parameter */ @@ -2714,8 +2805,14 @@ loop: granted: in that case do nothing */ if (trx->wait_lock) { +#ifdef WITH_WSREP + if (!wsrep_is_BF_lock_timeout(slot)) { +#endif lock_cancel_waiting_and_release( trx->wait_lock); +#ifdef WITH_WSREP + } +#endif } } } @@ -2831,7 +2928,20 @@ loop: if (sync_array_print_long_waits(&waiter, &sema) && sema == old_sema && os_thread_eq(waiter, old_waiter)) { +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + if (srv_allow_writes_event->is_set) { +#endif /* WITH_WSREP */ fatal_cnt++; +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + } else { + fprintf(stderr, + "WSREP: avoiding InnoDB self crash due to long " + "semaphore wait of > %lu seconds\n" + "Server is processing SST donor operation, " + "fatal_cnt now: %lu", + (ulong) srv_fatal_semaphore_wait_threshold, fatal_cnt); + } +#endif /* WITH_WSREP */ if (fatal_cnt > 10) { fprintf(stderr, diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c index b55471959ce..3db63469cbe 100644 --- a/storage/xtradb/trx/trx0roll.c +++ b/storage/xtradb/trx/trx0roll.c @@ -42,6 +42,9 @@ Created 3/26/1996 Heikki Tuuri #include "row0mysql.h" #include "lock0lock.h" #include "pars0pars.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" +#endif /* WITH_WSREP */ /** This many pages must be undone before a truncate is tried within rollback */ @@ -147,6 +150,12 @@ trx_rollback_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -174,6 +183,12 @@ trx_rollback_last_sql_stat_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -1123,6 +1138,12 @@ trx_rollback( srv_que_task_enqueue_low(thr); /* srv_que_task_enqueue_low(thr2); */ } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /****************************************************************//** @@ -1281,6 +1302,12 @@ trx_finish_rollback_off_kernel( sig = next_sig; } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /*********************************************************************//** diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index e0663ca5f87..56d0723d777 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -44,6 +44,10 @@ Created 3/26/1996 Heikki Tuuri #include "os0file.h" #include "read0read.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" /* wsrep_is_wsrep_xid() */ +#endif /* */ + /** The file format tag structure with id and name. */ struct file_format_struct { ulint id; /*!< id of the file format */ @@ -960,6 +964,89 @@ trx_sys_print_mysql_binlog_offset(void) mtr_commit(&mtr); } +#ifdef WITH_WSREP + +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: transaction XID */ + mtr_t* mtr) /*!< in: mtr */ +{ + trx_sysf_t* sys_header; + + ut_ad(xid && mtr); + ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); + + sys_header = trx_sysf_get(mtr); + if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD) + != TRX_SYS_WSREP_XID_MAGIC_N) { + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD, + TRX_SYS_WSREP_XID_MAGIC_N, + MLOG_4BYTES, mtr); + } + + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_FORMAT, + (int)xid->formatID, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_GTRID_LEN, + (int)xid->gtrid_length, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_BQUAL_LEN, + (int)xid->bqual_length, + MLOG_4BYTES, mtr); + mlog_write_string(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_DATA, + (const unsigned char*) xid->data, + XIDDATASIZE, mtr); + +} + +void +trx_sys_read_wsrep_checkpoint(XID* xid) +/*===================================*/ +{ + trx_sysf_t* sys_header; + mtr_t mtr; + ulint magic; + + ut_ad(xid); + + mtr_start(&mtr); + + sys_header = trx_sysf_get(&mtr); + + if ((magic = mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + != TRX_SYS_WSREP_XID_MAGIC_N) { + memset(xid, 0, sizeof(*xid)); + xid->formatID = -1; + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return; + } + + xid->formatID = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_FORMAT); + xid->gtrid_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_GTRID_LEN); + xid->bqual_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_BQUAL_LEN); + ut_memcpy(xid->data, + sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA, + XIDDATASIZE); + + mtr_commit(&mtr); +} + +#endif /* WITH_WSREP */ + /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index 2bb38571bda..96e0716e5c0 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -755,6 +755,11 @@ trx_start_low( trx->id = trx_sys_get_new_trx_id(); +#ifdef WITH_WSREP + memset(&trx->xid, 0, sizeof(trx->xid)); + trx->xid.formatID = -1; +#endif /* WITH_WSREP */ + /* The initial value for trx->no: IB_ULONGLONG_MAX is used in read_view_open_now: */ @@ -909,6 +914,14 @@ trx_write_serialisation_history( mutex_exit(&rseg->mutex); +#ifdef WITH_WSREP + /* Update latest MySQL wsrep XID in trx sys header. */ + if (wsrep_is_wsrep_xid(&trx->xid)) + { + trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + } +#endif /* WITH_WSREP */ + /* Update the latest MySQL binlog name and offset info in trx sys header if MySQL binlogging is on or the database server is a MySQL replication slave */ @@ -1138,6 +1151,12 @@ trx_commit_off_kernel( ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0); ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0); +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); } diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index f8a65e75d4d..d0a7f89d150 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -40,7 +40,7 @@ ELSE() SET(inst_location ${INSTALL_SUPPORTFILESDIR}) ENDIF() -FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small) +FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small wsrep) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${inifile}.cnf.sh ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} @@ -84,4 +84,10 @@ IF(UNIX) DESTINATION ${inst_location} COMPONENT SupportFiles PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/wsrep_notify.sh + ${CMAKE_CURRENT_BINARY_DIR}/wsrep_notify @ONLY) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/wsrep_notify + DESTINATION ${inst_location} COMPONENT SupportFiles + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ + GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) ENDIF() diff --git a/support-files/build-tags b/support-files/build-tags index b5386dc79c3..f42fae218d2 100755 --- a/support-files/build-tags +++ b/support-files/build-tags @@ -1,12 +1,17 @@ #! /bin/sh rm -f TAGS -filter='\.cc$\|\.c$\|\.h$\|\.yy$' +filter='\.cc$\|\.c$\|\.h$\|\.yy\|\.ic\|.ih$' -list="find . -type f" +#list="find . -type f" bzr root >/dev/null 2>/dev/null && list="bzr ls --from-root -R --kind=file --versioned" $list |grep $filter |while read f; do etags -o TAGS --append $f done + +(cd storage/galera && svn ls -R) | grep $filter | while read f; +do + etags -o TAGS --append storage/galera/$f +done diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index a3d8554188e..1b6cc1cdb04 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -67,6 +67,17 @@ # $ rpmbuild --define="option " ... # +# ---------------------------------------------------------------------------- +# wsrep builds +# ---------------------------------------------------------------------------- +%if %{defined with_wsrep} +%define mysql_version @VERSION@_wsrep_@WSREP_API_VERSION@.@WSREP_PATCH_VERSION@ +%define wsrep_version @WSREP_VERSION@ +%define wsrep_comment , wsrep_%{wsrep_version} +%else +%define wsrep_comment %{nil} +%endif + # ---------------------------------------------------------------------------- # Commercial builds # ---------------------------------------------------------------------------- @@ -93,10 +104,10 @@ # Server comment strings # ---------------------------------------------------------------------------- %if %{undefined compilation_comment_debug} -%define compilation_comment_debug MySQL Community Server - Debug (GPL) +%define compilation_comment_debug MySQL Community Server - Debug (GPL)%{wsrep_comment} %endif %if %{undefined compilation_comment_release} -%define compilation_comment_release MySQL Community Server (GPL) +%define compilation_comment_release MySQL Community Server (GPL)%{wsrep_comment} %endif # ---------------------------------------------------------------------------- @@ -114,6 +125,13 @@ %define server_suffix %{nil} %endif +# ---------------------------------------------------------------------------- +# Packager +# ---------------------------------------------------------------------------- +%if %{undefined mysql_packager} +%define mysql_packager MySQL Build Team +%endif + # ---------------------------------------------------------------------------- # Distribution support # ---------------------------------------------------------------------------- @@ -280,6 +298,10 @@ documentation and the manual for more information. ############################################################################## %package -n MySQL-server%{product_suffix} +%if %{defined with_wsrep} +Version: %{mysql_version} +#Release: %{wsrep_version}.%{release} +%endif Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases Requires: %{distro_requires} @@ -309,6 +331,9 @@ and the manual for more information. This package includes the MySQL server binary as well as related utilities to run and administer a MySQL server. +%if %{defined with_wsrep} +Built with wsrep patch %{wsrep_version}. +%endif If you want to access and work with the database, you have to install package "MySQL-client%{product_suffix}" as well! @@ -374,6 +399,7 @@ This package contains the shared libraries (*.so*) which certain languages and applications need to dynamically load and use MySQL. # ---------------------------------------------------------------------------- +%if %{undefined with_wsrep} %package -n MySQL-embedded%{product_suffix} Summary: MySQL - Embedded library Group: Applications/Databases @@ -395,6 +421,7 @@ The API is identical for the embedded MySQL version and the client/server version. For a description of MySQL see the base MySQL RPM or http://www.mysql.com/ +%endif ############################################################################## %prep @@ -460,6 +487,9 @@ mkdir debug -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_debug}" \ +%if %{defined with_wsrep} + -DWITH_WSREP=1 \ +%endif -DMYSQL_SERVER_SUFFIX="%{server_suffix}" echo BEGIN_DEBUG_CONFIG ; egrep '^#define' include/config.h ; echo END_DEBUG_CONFIG make ${MAKE_JFLAG} VERBOSE=1 @@ -475,6 +505,9 @@ mkdir release -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_release}" \ +%if %{defined with_wsrep} + -DWITH_WSREP=1 \ +%endif -DMYSQL_SERVER_SUFFIX="%{server_suffix}" echo BEGIN_NORMAL_CONFIG ; egrep '^#define' include/config.h ; echo END_NORMAL_CONFIG make ${MAKE_JFLAG} VERBOSE=1 @@ -530,11 +563,20 @@ install -m 755 $MBD/release/support-files/mysql.server $RBR%{_sysconfdir}/init.d # Create a symlink "rcmysql", pointing to the init.script. SuSE users # will appreciate that, as all services usually offer this. -ln -s %{_sysconfdir}/init.d/mysql $RBR%{_sbindir}/rcmysql +ln -sf %{_sysconfdir}/init.d/mysql $RBR%{_sbindir}/rcmysql + +%if %{defined with_wsrep} +# Create a wsrep_sst_rsync_wan symlink. +install -d $RBR%{_bindir} +ln -sf wsrep_sst_rsync $RBR%{_bindir}/wsrep_sst_rsync_wan +%endif # Touch the place where the my.cnf config file might be located # Just to make sure it's in the file list and marked as a config file touch $RBR%{_sysconfdir}/my.cnf +%if %{defined with_wsrep} +touch $RBR%{_sysconfdir}/wsrep.cnf +%endif # Install SELinux files in datadir install -m 600 $MBD/%{src_dir}/support-files/RHEL4-SElinux/mysql.{fc,te} \ @@ -988,6 +1030,11 @@ echo "=====" >> $STATUS_HISTORY %doc %{src_dir}/Docs/INFO_SRC* %doc release/Docs/INFO_BIN* %doc release/support-files/my-*.cnf +%if %{defined with_wsrep} +%doc %{src_dir}/Docs/README-wsrep +%doc release/support-files/wsrep.cnf +%doc release/support-files/wsrep_notify +%endif %doc %attr(644, root, root) %{_infodir}/mysql.info* @@ -1021,6 +1068,9 @@ echo "=====" >> $STATUS_HISTORY %doc %attr(644, root, man) %{_mandir}/man1/resolveip.1* %ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf +%if %{defined with_wsrep} +%ghost %config(noreplace,missingok) %{_sysconfdir}/wsrep.cnf +%endif %attr(755, root, root) %{_bindir}/innochecksum %attr(755, root, root) %{_bindir}/my_print_defaults @@ -1047,6 +1097,11 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_bindir}/replace %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip +%if %{defined with_wsrep} +%attr(755, root, root) %{_bindir}/wsrep_sst_mysqldump +%attr(755, root, root) %{_bindir}/wsrep_sst_rsync +%attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan +%endif %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug @@ -1125,8 +1180,10 @@ echo "=====" >> $STATUS_HISTORY %defattr(-, root, root, 0755) %attr(-, root, root) %{_datadir}/mysql-test %attr(755, root, root) %{_bindir}/mysql_client_test +%if %{undefined with_wsrep} %attr(755, root, root) %{_bindir}/mysql_client_test_embedded %attr(755, root, root) %{_bindir}/mysqltest_embedded +%endif %doc %attr(644, root, man) %{_mandir}/man1/mysql_client_test.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql-stress-test.pl.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql-test-run.pl.1* @@ -1134,11 +1191,13 @@ echo "=====" >> $STATUS_HISTORY %doc %attr(644, root, man) %{_mandir}/man1/mysqltest_embedded.1* # ---------------------------------------------------------------------------- +%if %{undefined with_wsrep} %files -n MySQL-embedded%{product_suffix} %defattr(-, root, root, 0755) %attr(755, root, root) %{_bindir}/mysql_embedded %attr(644, root, root) %{_libdir}/mysql/libmysqld.a %attr(644, root, root) %{_libdir}/mysql/libmysqld-debug.a +%endif ############################################################################## # The spec file changelog only includes changes made to the spec file @@ -1146,6 +1205,10 @@ echo "=====" >> $STATUS_HISTORY # merging BK trees) ############################################################################## %changelog +* Wed Dec 07 2011 Alexey Yurchenko + +- wsrep-related cleanups. + * Wed Sep 28 2011 Joerg Bruehe - Fix duplicate mentioning of "mysql_plugin" and its manual page, @@ -1198,7 +1261,6 @@ echo "=====" >> $STATUS_HISTORY - Fix bug#12561297: Added the MySQL embedded binary * Thu Jul 07 2011 Joerg Bruehe - - Fix bug#45415: "rpm upgrade recreates test database" Let the creation of the "test" database happen only during a new installation, not in an RPM upgrade. From f96fd3f40f37c0080e71e45f85e53bd156aa27f5 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 26 Apr 2012 13:09:06 +0300 Subject: [PATCH 002/294] Added wsrep specific files --- BUILD/compile-amd64-debug-wsrep | 11 + BUILD/compile-amd64-wsrep | 9 + BUILD/compile-pentium-debug-wsrep | 12 + BUILD/compile-pentium-wsrep | 11 + BUILD/compile-pentium64-wsrep | 28 + Docs/README-wsrep | 466 +++++++++++++ cmake/wsrep.cmake | 59 ++ scripts/wsrep_sst_mysqldump.sh | 133 ++++ scripts/wsrep_sst_rsync.sh | 214 ++++++ sql/wsrep_check_opts.cc | 392 +++++++++++ sql/wsrep_hton.cc | 419 ++++++++++++ sql/wsrep_mysqld.cc | 1060 +++++++++++++++++++++++++++++ sql/wsrep_mysqld.h | 297 ++++++++ sql/wsrep_notify.cc | 107 +++ sql/wsrep_priv.h | 231 +++++++ sql/wsrep_sst.cc | 932 +++++++++++++++++++++++++ sql/wsrep_utils.cc | 447 ++++++++++++ sql/wsrep_var.cc | 505 ++++++++++++++ support-files/wsrep.cnf.sh | 125 ++++ support-files/wsrep_notify.sh | 102 +++ wsrep/CMakeLists.txt | 24 + wsrep/Makefile.am | 2 + wsrep/wsrep_api.h | 875 ++++++++++++++++++++++++ wsrep/wsrep_dummy.c | 368 ++++++++++ wsrep/wsrep_loader.c | 199 ++++++ wsrep/wsrep_uuid.c | 78 +++ 26 files changed, 7106 insertions(+) create mode 100755 BUILD/compile-amd64-debug-wsrep create mode 100755 BUILD/compile-amd64-wsrep create mode 100755 BUILD/compile-pentium-debug-wsrep create mode 100755 BUILD/compile-pentium-wsrep create mode 100755 BUILD/compile-pentium64-wsrep create mode 100644 Docs/README-wsrep create mode 100644 cmake/wsrep.cmake create mode 100644 scripts/wsrep_sst_mysqldump.sh create mode 100644 scripts/wsrep_sst_rsync.sh create mode 100644 sql/wsrep_check_opts.cc create mode 100644 sql/wsrep_hton.cc create mode 100644 sql/wsrep_mysqld.cc create mode 100644 sql/wsrep_mysqld.h create mode 100644 sql/wsrep_notify.cc create mode 100644 sql/wsrep_priv.h create mode 100644 sql/wsrep_sst.cc create mode 100644 sql/wsrep_utils.cc create mode 100644 sql/wsrep_var.cc create mode 100644 support-files/wsrep.cnf.sh create mode 100644 support-files/wsrep_notify.sh create mode 100644 wsrep/CMakeLists.txt create mode 100644 wsrep/Makefile.am create mode 100644 wsrep/wsrep_api.h create mode 100644 wsrep/wsrep_dummy.c create mode 100644 wsrep/wsrep_loader.c create mode 100644 wsrep/wsrep_uuid.c diff --git a/BUILD/compile-amd64-debug-wsrep b/BUILD/compile-amd64-debug-wsrep new file mode 100755 index 00000000000..995a8afcca9 --- /dev/null +++ b/BUILD/compile-amd64-debug-wsrep @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$amd64_cflags $debug_cflags -g -O0 $wsrep_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$amd64_configs $debug_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-amd64-wsrep b/BUILD/compile-amd64-wsrep new file mode 100755 index 00000000000..57dfbdd6da2 --- /dev/null +++ b/BUILD/compile-amd64-wsrep @@ -0,0 +1,9 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$amd64_cflags $fast_cflags -g $wsrep_cflags" +extra_configs="$amd64_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-debug-wsrep b/BUILD/compile-pentium-debug-wsrep new file mode 100755 index 00000000000..ee68e3fd0c1 --- /dev/null +++ b/BUILD/compile-pentium-debug-wsrep @@ -0,0 +1,12 @@ +#! /bin/sh -x + +path=`dirname $0` +set -- "$@" --with-debug=full +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $debug_cflags -g -O0 $wsrep_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-wsrep b/BUILD/compile-pentium-wsrep new file mode 100755 index 00000000000..eeb14310e4e --- /dev/null +++ b/BUILD/compile-pentium-wsrep @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $fast_cflags $wsrep_cflags" +extra_configs="$pentium_configs $wsrep_configs --with-wsrep" + +#strip=yes + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-wsrep b/BUILD/compile-pentium64-wsrep new file mode 100755 index 00000000000..0bccb34e753 --- /dev/null +++ b/BUILD/compile-pentium64-wsrep @@ -0,0 +1,28 @@ +#! /bin/sh + +# Copyright (C) 2006, 2007 MySQL AB +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium64_cflags $fast_cflags -g $wsrep_cflags" +extra_configs="$pentium_configs $static_link $wsrep_configs --with-wsrep" +CC="$CC --pipe" +strip=yes + +. "$path/FINISH.sh" diff --git a/Docs/README-wsrep b/Docs/README-wsrep new file mode 100644 index 00000000000..ea6a62621ed --- /dev/null +++ b/Docs/README-wsrep @@ -0,0 +1,466 @@ +Codership Oy +http://www.codership.com + + +DISCLAIMER + +THIS SOFTWARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +IN NO EVENT SHALL CODERSHIP OY BE HELD LIABLE TO ANY PARTY FOR ANY DAMAGES +RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE. + +Trademark Information. + +MySQL is a trademark or registered trademark of Oracle and/or its affiliates. +Other trademarks are the property of their respective owners. + +Licensing Information. + +Please see file COPYING that came with this distribution + +Source code can be found at +wsrep API: https://launchpad.net/wsrep +MySQL patch: https://launchpad.net/codership-mysql + + +ABOUT THIS DOCUMENT + +This document covers installation and configuration issues specific to this +wsrep-patched MySQL distribution by Codership. It does not cover the use or +administration of MySQL server per se. The reader is assumed to know how to +install, configure, administer and use standard MySQL server version 5.1.xx. + + + MYSQL-5.5.x/wsrep-23.x + +CONTENTS: +========= +1. WHAT IS WSREP PATCH FOR MYSQL +2. INSTALLATION +3. FIRST TIME SETUP + 3.1 CONFIGURATION FILES + 3.2 DATABASE PRIVILEGES + 3.3 CHECK AND CORRECT FIREWALL SETTINGS + 3.4 SELINUX + 3.5 APPARMOR + 3.6 CONNECT TO CLUSTER +4. UPGRADING FROM MySQL 5.1.x +5. CONFIGURATION OPTIONS + 5.1 MANDATORY MYSQL OPTIONS + 5.2 WSREP OPTIONS +6. ONLINE SCHEMA UPGRADE + 6.1 TOTAL ORDER ISOLATION (TOI) + 6.2 ROLLING SCHEMA UPGRADE (RSU) +7. LIMITATIONS + + +1. WHAT IS WSREP PATCH FOR MYSQL/INNODB + +Wsrep API developed by Codership Oy is a modern generic (database-agnostic) +replication API for transactional databases with a goal to make database +replication/logging subsystem completely modular and pluggable. It is developed +with flexibility and completeness in mind to satisfy broad range of modern +replication scenarios. It is equally suitable for synchronous and asynchronous, +master-slave and multi-master replication. + +wsrep stands for Write Set REPlication. + +Wsrep patch for MySQL/InnoDB allows MySQL server to load and use various wsrep +API implementations ("wsrep providers") with different qualities of service. +Without wsrep provider MySQL-wsrep server will function like a regular +standalone server. + + +2. INSTALLATION + +In the examples below mysql authentication options are omitted for brevity. + +2.1 Download and install mysql-wsrep package. + +Download binary package for your Linux distribution from +https://launchpad.net/codership-mysql/ + +2.1.1 On Debian and Debian-derived distributions. + +Upgrade from mysql-server-5.0 to mysql-wsrep is not supported yet, please +upgrade to mysql-server-5.1 first. + +If you're installing over an existing mysql installation, mysql-server-wsrep +will conflict with mysql-server-5.1 package, so remove it first: + +$ sudo apt-get remove mysql-server-5.1 mysql-server-core-5.1 + +mysql-server-wsrep requires psmisc and mysql-client-5.1.47 (or later). +MySQL 5.1 packages can be found from backports repositories. +For further information about configuring and using Debian or Ubuntu +backports, see: + +* http://backports.debian.org + +* https://help.ubuntu.com/community/UbuntuBackports + +For example, installation of required packages on Debian Lenny: + +$ sudo apt-get install psmisc +$ sudo apt-get -t lenny-backports install mysql-client-5.1 + +Now you should be able to install mysql-wsrep package: + +$ sudo dpkg -i + +2.1.2 On CentOS and similar RPM-based distributions. + +If you're migrating from existing MySQL installation, there are two variants: + + a) If you're already using official MySQL-server-community 5.1.x RPM from + Oracle: + + # rpm -e mysql-server + + b) If you're upgrading from the stock mysql-5.0.77 on CentOS: + + 1) Make sure that the following packages are not installed: + # rpm --nodeps --allmatches -e mysql-server mysql-test mysql-bench + + 2) Install *official* MySQL-shared-compat-5.1.x from + http://dev.mysql.com/downloads/mysql/5.1.html + +Actual installation: + + # rpm -Uvh + + If this fails due to unsatisfied dependencies, install missing packages + (e.g. yum install perl-DBI) and retry. + +Additional packages to consider (if not yet installed): + * galera (multi-master replication provider, https://launchpad.net/galera) + * MySQL-client-community (for connecting to server and mysqldump-based SST) + * rsync (for rsync-based SST) + +2.2 Upgrade system tables. + +If you're upgrading a previous MySQL installation, it might be advisable to +upgrade system tables. To do that start mysqld and run mysql_upgrade command. +Consult MySQL documentation in case of errors. Normally they are not critical +and can be ignored unless specific functionality is needed. + + +3. FIRST TIME SETUP + +Unless you're upgrading an already installed mysql-wsrep package, you will need +to set up a few things to prepare server for operation. + +3.1 CONFIGURATION FILES + +* Make sure system-wide my.cnf does not bind mysqld to 127.0.0.1. That is, if + you have the following line in [mysqld] section, comment it out: + + #bind-address = 127.0.0.1 + +* Make sure system-wide my.cnf contains "!includedir /etc/mysql/conf.d/" line. + +* Edit /etc/mysql/conf.d/wsrep.cnf and set wsrep_provider option by specifying + a path to provider library. If you don't have a provider, leave it as it is. + +* When a new node joins the cluster it'll have to receive a state snapshot from + one of the peers. This requires a privileged MySQL account with access from + the rest of the cluster. Edit /etc/mysql/conf.d/wsrep.cnf and set mysql + login/password pair for SST, for example: + + wsrep_sst_auth=wsrep_sst:wspass + +* See CONFIGURATION section below about other configuration parameters that you + might want to change at this point. + +3.2 DATABASE PRIVILEGES + +Restart MySQL server and connect to it as root to grant privileges to SST +account (empty users confuse MySQL authentication matching rules, we need to +delete them too): + +$ mysql -e "SET wsrep_on=OFF; DELETE FROM mysql.user WHERE user='';" +$ mysql -e "SET wsrep_on=OFF; GRANT ALL ON *.* TO wsrep_sst@'%' IDENTIFIED BY 'wspass'"; + +3.3 CHECK AND CORRECT FIREWALL SETTINGS. + +MySQL-wsrep server needs to be accessible from other cluster members through +its client listening socket and through wsrep provider socket. See your +distribution and wsrep provider documentation for details. For example on +CentOS you might need to do something along these lines: + +# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 3306 -j ACCEPT +# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 4567 -j ACCEPT + +If there is a NAT firewall between the nodes, it must be configured to allow +direct connections between the nodes (e.g. via port forwarding). + +3.4 SELINUX + +If you have SELinux enabled, it may block mysqld from doing required operations. +You'll need to either disable it or configure to allow mysqld to run external +programs and open listen sockets at unprivileged ports (i.e. things that +an unprivileged user can do). See SELinux documentation about it. + +To quickly disable SELinux: +1) run 'setenforce 0' as root. +2) set 'SELINUX=permissive' in /etc/selinux/config + +3.5 APPARMOR + +AppArmor automatically comes with Ubuntu and may also prevent mysqld to from +opening additional ports or run scripts. See AppArmor documentation about its +configuration. To disable AppArmor for mysqld: + +$ cd /etc/apparmor.d/disable/ +$ sudo ln -s /etc/apparmor.d/usr.sbin.mysqld +$ sudo service apparmor restart + + +3.6 CONNECT TO CLUSTER + +Now you're ready to connect to cluster by setting wsrep_cluster_address variable +and monitor status of wsrep provider: + +mysql> SET GLOBAL wsrep_cluster_address=''; +mysql> SHOW STATUS LIKE 'wsrep%'; + + +4 UPGRADING FROM MySQL 5.1.x + +!!! THESE INSTRUCTIONS ARE PRELIMINARY AND INCOMPLETE !!! + +1) BEFORE UPGRADE (while running 5.1.x): + - comment out 'wsrep_provider' setting from configuration files + (my.cnf and/or wsrep.cnf) + - If performing a rolling upgrade on a running cluster, set + wsrep_sst_method=mysqldump. + You might also need to configure wsrep_sst_receive_address and + wsrep_sst_auth appropriately. Mysqldump is the only way to transfer data + from 5.1.x to 5.5.x reliably. + - remove innodb_plugin settings from configuration files. + +2) Perform upgrade as usual: + http://dev.mysql.com/doc/refman/5.5/en/upgrading-from-previous-series.html + Don't forget to run 'mysql_upgrade' command. + +3) AFTER UPGRADING individual node: + - uncomment 'wsrep_provider' line in configuration file. + - restart the server and join the cluster. + +4) AFTER UPGRADING the whole cluster: + - revert to usual wsrep SST settings if not 'mysqldump'. + + +5. CONFIGURATION OPTIONS + +5.1 MANDATORY MYSQL OPTIONS + +binlog_format=ROW + This option is required to use row-level replication as opposed to + statement-level. For performance and consistency considerations don't change + that. As a side effect, binlog, if turned on, can be ROW only. In future this + option won't have special meaning. + +innodb_autoinc_lock_mode=2 + This is a required parameter. Without it INSERTs into tables with + AUTO_INCREMENT column may fail. + autoinc lock modes 0 and 1 can cause unresolved deadlock, and make + system unresponsive. + +innodb_locks_unsafe_for_binlog=1 + This option is required for parallel applying. + +5.2 WSREP OPTIONS + +All options are optional except for wsrep_provider, wsrep_cluster_address, and +wsrep_sst_auth. + +wsrep_provider=none + A full path to the library that implements WSREP interface. If none is + specified, the server behaves like a regular mysqld. + +wsrep_provider_options= + Provider-specific option string. Check wsrep provider documentation or + http://www.codership.com/wiki + +wsrep_cluster_address= + Provider-specific cluster address string. This is used to connect a node to + the desired cluster. This option can be given either on mysqld startup or set + during runtime. See wsrep provider documentation for possible values. + +wsrep_cluster_name="my_wsrep_cluster" + Logical cluster name, must be the same for all nodes of the cluster. + +wsrep_node_name= + Human readable node name (for easier log reading only). Defaults to hostname. + +wsrep_slave_threads=1 + Number of threads dedicated to processing of writesets from other nodes. + For best performance should be few per CPU core. + +wsrep_dbug_option + Options for the built-in DBUG library (independent from what MySQL uses). + Empty by default. Not currently in use. + +wsrep_debug=0 + Enable debug-level logging. + +wsrep_convert_LOCK_to_trx=0 + Implicitly convert locking sessions into transactions inside mysqld. By + itself it does not mean support for locking sessions, but it prevents the + database from going into logically inconsistent state. Note however, that + loading large database dump with LOCK statements might result in abnormally + large transactions and cause an out-of-memory condition + +wsrep_retry_autocommit=1 + Retry autocommit queries and single statement transactions should they fail + certification test. This is analogous to rescheduling an autocommit query + should it go into deadlock with other transactions in the database lock + manager. + +wsrep_auto_increment_control=1 + Automatically adjust auto_increment_increment and auto_increment_offset + variables based on the number of nodes in the cluster. Significantly reduces + certification conflict rate for INSERTS. + +wsrep_drupal_282555_workaround=1 + MySQL seems to have an obscure bug when INSERT into table with + AUTO_INCREMENT column with NULL value for that column can fail with a + duplicate key error. When this option is on, it retries such INSERTs. + Required for stable Drupal operation. Documented at: + http://bugs.mysql.com/bug.php?id=41984 + http://drupal.org/node/282555 + +wsrep_causal_reads=0 + Enforce strict READ COMMITTED semantics on reads and transactions. May + result in additional latencies. It is a session variable. + +wsrep_OSU_method=TOI + Online Schema Upgrade (OSU) can be performed with two alternative methods: + Total Order Isolation (TOI) runs DDL statement in all cluster nodes in + same total order sequence locking the affected table for the duration of the + operation. This may result in the whole cluster being blocked for the + duration of the operation. + Rolling Schema Upgrade (RSU) executes the DDL statement only locally, thus + blocking only one cluster node. During the DDL processing, the node + is not replicating and may be unable to process replication events (due to + table lock). Once DDL operation is complete, the node will catch up and sync + with the cluster to become fully operational again. The DDL statement or + its effects are not replicated, so it is user's responsibility to manually + perform this operation on each of the nodes. + +wsrep_forced_binlog_format=none + Force every transaction to use given binlog format. When this variable is + set to something else than NONE, all transactions will use the given forced + format, regardless of what the client session has specified in binlog_format. + Valid choices for wsrep_forced_binlog_format are: ROW, STATEMENT, MIXED and + special value NONE, meaning that there is no forced binlog format in effect. + This variable was intruduced to support STATEMENT format replication during + rolling schema upgrade processing. However, in most cases ROW replication + is valid for asymmetrict schema replication. + +State snapshot transfer options. + +When a new node joins the cluster it has to synchronize its initial state with +the other cluster members by transferring state snapshot from one of them. +The options below govern how this happens and should be set up before attempting +to join or start a cluster. + +wsrep_sst_method=mysqldump + What method to use to copy database state to a newly joined node. Supported + methods: + - mysqldump: slow (except for small datasets) but most tested. + - rsync: much faster on large datasets. + - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. + +wsrep_sst_receive_address= + Address (hostname:port) at which this node wants to receive state snapshot. + Defaults to mysqld bind address, and if that is not specified (0.0.0.0) - + to the first IP of eth0 + mysqld bind port. + NOTE: check that your firewall allows connections to this address from other + cluster nodes. + +wsrep_sst_auth= + Authentication information needed for state transfer. Depends on the state + transfer method. For mysqldump-based SST it is + : + and should be the same on all nodes - it is used to authenticate with both + state snapshot receiver and state snapshot donor. + +wsrep_sst_donor= + A name of the node which should serve as state snapshot donor. This allows + to control which node will serve state snapshot request. By default the + most suitable node is chosen by wsrep provider. This is the same as given in + wsrep_node_name. + + +6. ONLINE SCHEMA UPGRADE + + Schema upgrades mean any data definition statements (DDL statemnents) run + for the database. They change the database structure and are non- + transactional. + + Release 22.3 brings a new method for performing schema upgrades. User can + now choose whether to use the traditional total order isolation or new + rolling schema upgrade method. The OSU method choice is done by global + parameter: 'wsrep_OSU_method'. + +6.1 Total Order Isolation (TOI) + + With earlier releases, DDL processing happened always by Total Order + Isolation (TOI) method. With TOI, the DDL was scheduled to be processed in + same transaction seqeuncing 'slot' in each cluster node. + The processing is secured by locking the affected table from any other use. + With TOI method, the whole cluster has part of the database locked for the + duration of the DDL processing. + +6.2 Rolling Schema Upgrade (RSU) + + Rolling schema upgrade is new DDL processing method, where DDL will be + processed locally for the node. The node is disconnected of the replication + for the duration of the DDL processing, so that there is only DDL statement + processing in the node and it does not block the rest of the cluster. When + the DDL processing is complete, the node applies delayed replication events + and synchronizes back with the cluster. + The DDL can then be executed cluster-wide by running the same DDL statement + for each node in turn. When this rolling schema upgrade proceeds, part of + the cluster will have old schema structure and part of the cluster will have + new schema structure. + + +7. LIMITATIONS + +1) Currently replication works only with InnoDB storage engine. Any writes to + tables of other types, including system (mysql.*) tables are not replicated. + However, DDL statements are replicated in statement level, and changes + to mysql.* tables will get replicated that way. + So, you can safely issue: CREATE USER..., + but issuing: INSERT INTO mysql.user..., will not be replicated. + +2) DELETE operation is unsupported on tables without primary key. Also rows in + tables without primary key may appear in different order on different nodes. + As a result SELECT...LIMIT... may return slightly different sets. + +3) Unsupported queries: + * LOCK/UNLOCK TABLES cannot be supported in multi-master setups. + * lock functions (GET_LOCK(), RELEASE_LOCK()... ) + +4) Query log cannot be directed to table. If you enable query logging, + you must forward the log to a file: + log_output = FILE + Use general_log and general_log_file to choose query logging and the + log file name + +5) Maximum allowed transaction size is defined by wsrep_max_ws_rows and + wsrep_max_ws_size. Anything bigger (e.g. huge LOAD DATA) will be rejected. + +6) Due to cluster level optimistic concurrency control, transaction issuing + COMMIT may still be aborted at that stage. There can be two transactions. + writing to same rows and committing in separate cluster nodes, and only one + of the them can successfully commit. The failing one will be aborted. + For cluster level aborts, MySQL/galera cluster gives back deadlock error. + code (Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK)). + +7) XA transactions can not be supported due to possible rollback on commit. + diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake new file mode 100644 index 00000000000..1fd747cddd6 --- /dev/null +++ b/cmake/wsrep.cmake @@ -0,0 +1,59 @@ +# Copyright (c) 2011, Codership Oy . +# +# 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 + +# We need to generate a proper spec file even without --with-wsrep flag, +# so WSREP_VERSION is produced regardless + +# Set the patch version +SET(WSREP_PATCH_VERSION "5") + +# Obtain patch revision number +SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) +IF(NOT WSREP_PATCH_REVNO) + EXECUTE_PROCESS( + COMMAND bzr revno + OUTPUT_VARIABLE WSREP_PATCH_REVNO + RESULT_VARIABLE RESULT + ) +STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_PATCH_REVNO "${WSREP_PATCH_REVNO}") +#FILE(WRITE "wsrep_config" "Debug: WSREP_PATCH_REVNO result: ${RESULT}\n") +ENDIF() +IF(NOT WSREP_PATCH_REVNO) + SET(WSREP_PATCH_REVNO "XXXX") +ENDIF() + +# Obtain wsrep API version +EXECUTE_PROCESS( + COMMAND sh -c "grep WSREP_INTERFACE_VERSION ${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h | cut -d '\"' -f 2" + OUTPUT_VARIABLE WSREP_API_VERSION + RESULT_VARIABLE RESULT +) +#FILE(WRITE "wsrep_config" "Debug: WSREP_API_VERSION result: ${RESULT}\n") +STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_API_VERSION "${WSREP_API_VERSION}") + +SET(WSREP_VERSION + "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" +) + +OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" OFF) +IF (WITH_WSREP) + SET(WSREP_C_FLAGS "-DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WSREP_C_FLAGS}") + SET(COMPILATION_COMMENT "${COMPILATION_COMMENT}, wsrep_${WSREP_VERSION}") + SET(WITH_EMBEDDED_SERVER OFF) +ENDIF() + +# diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh new file mode 100644 index 00000000000..8106850e918 --- /dev/null +++ b/scripts/wsrep_sst_mysqldump.sh @@ -0,0 +1,133 @@ +#!/bin/sh -e +# Copyright (C) 2009 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for mysqldump-based state snapshot tansfer + +USER=$1 +PSWD=$2 +HOST=$3 +PORT=$4 +LOCAL_HOST="127.0.0.1" +LOCAL_PORT=$5 +UUID=$6 +SEQNO=$7 +BYPASS=$8 + +EINVAL=22 + +err() +{ + echo "SST error: $*" >&2 +} + +local_ip() +{ + PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin + + [ "$1" = "127.0.0.1" ] && return 0 + [ "$1" = "localhost" ] && return 0 + [ "$1" = "$(hostname -s)" ] && return 0 + [ "$1" = "$(hostname -f)" ] && return 0 + [ "$1" = "$(hostname -d)" ] && return 0 + + # Now if ip program is not found in the path, we can't return 0 since + # it would block any address. Thankfully grep should fail in this case + ip route get "$1" | grep local >/dev/null && return 0 + + return 1 +} + +if test -z "$USER"; then err "USER cannot be nil"; exit $EINVAL; fi +if test -z "$HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi +if test -z "$PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi +if test -z "$LOCAL_PORT"; then err "LOCAL_PORT cannot be nil"; exit $EINVAL; fi +if test -z "$UUID"; then err "UUID cannot be nil"; exit $EINVAL; fi +if test -z "$SEQNO"; then err "SEQNO cannot be nil"; exit $EINVAL; fi + +if local_ip $HOST && [ "$PORT" = "$LOCAL_PORT" ] +then + err "destination address '$HOST:$PORT' matches source address." + exit $EINVAL +fi + +# Check client version +if ! mysql --version | grep 'Distrib 5.5' >/dev/null +then + mysql --version >&2 + err "this procedure requires MySQL client version 5.5.x" + exit $EINVAL +fi + +AUTH="-u$USER" +if test -n "$PSWD"; then AUTH="$AUTH -p$PSWD"; fi + +STOP_WSREP="SET wsrep_on=OFF;" + +# NOTE: we don't use --routines here because we're dumping mysql.proc table +#MYSQLDUMP="@bindir@/mysqldump $AUTH -h$LOCAL_HOST -P$LOCAL_PORT \ +MYSQLDUMP="mysqldump $AUTH -h$LOCAL_HOST -P$LOCAL_PORT \ +--add-drop-database --add-drop-table --skip-add-locks --create-options \ +--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ +--skip-comments --flush-privileges --all-databases" + +# mysqldump cannot restore CSV tables, fix this issue +CSV_TABLES_FIX=" +set sql_mode=''; + +USE mysql; + +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, thread_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, command_type VARCHAR(64) NOT NULL,argument MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"General log\"', 'SET @dummy = 0'); + +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"Slow log\"', 'SET @dummy = 0'); + +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt;" + +SET_START_POSITION="SET GLOBAL wsrep_start_position='$UUID:$SEQNO';" + +#MYSQL="@bindir@/mysql -u'$USER' -p'$PSWD' -h'$HOST' -P'$PORT'" +MYSQL="mysql $AUTH -h$HOST -P$PORT --disable-reconnect --connect_timeout=10" + +# need to disable logging when loading the dump +# reason is that dump contains ALTER TABLE for log tables, and +# this causes an error if logging is enabled +GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@GENERAL_LOG"` +SLOW_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@SLOW_QUERY_LOG"` +$MYSQL -e"$STOP_WSREP SET GLOBAL GENERAL_LOG=OFF" +$MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF" + +# commands to restore log settings +RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" +RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" + +if [ $BYPASS -eq 0 ] +then + (echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX \ + && echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG \ + && echo $SET_START_POSITION \ + || echo "SST failed to complete;") | $MYSQL +else + echo "Bypassing state dump." >&2 + echo $SET_START_POSITION | $MYSQL +fi + +# diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh new file mode 100644 index 00000000000..c0b54159eda --- /dev/null +++ b/scripts/wsrep_sst_rsync.sh @@ -0,0 +1,214 @@ +#!/bin/bash -ue + +# Copyright (C) 2010 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for rsync-based state snapshot tansfer + +RSYNC_PID= +RSYNC_CONF= + +cleanup_joiner() +{ + echo "Joiner cleanup:" >&2 +set -x + local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) + [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID || : +set +x + rm -rf "$RSYNC_CONF" + rm -rf "$MAGIC_FILE" + rm -rf "$RSYNC_PID" +} + +check_pid() +{ + local pid_file=$1 + [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 +} + +check_pid_and_port() +{ + local pid_file=$1 + local rsync_pid=$(cat $pid_file) + local rsync_port=$2 + + check_pid $pid_file && \ + netstat -anpt 2>/dev/null | \ + grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null +} + +ROLE=$1 +ADDR=$2 +AUTH=$3 +DATA=$4 +CONF=$5 + +MAGIC_FILE="$DATA/rsync_sst_complete" +rm -rf "$MAGIC_FILE" + +if [ "$ROLE" = "donor" ] +then + UUID=$6 + SEQNO=$7 + BYPASS=$8 + + if [ $BYPASS -eq 0 ] + then + + FLUSHED="$DATA/tables_flushed" + rm -rf "$FLUSHED" + + # Use deltaxfer only for WAN + inv=$(basename $0) + [ "$inv" = "wsrep_sst_rsync_wan" ] && WHOLE_FILE_OPT="" \ + || WHOLE_FILE_OPT="--whole-file" + + echo "flush tables" + + # wait for tables flushed and state ID written to the file + while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1 + do + sleep 0.2 + done + + STATE="$(cat $FLUSHED)" + rm -rf "$FLUSHED" + + sync + + # Old filter - include everything except selected + # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ + # --exclude '*.conf' --exclude core --exclude 'galera.*' \ + # --exclude grastate.txt --exclude '*.pem' \ + # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') + + # New filter - exclude everything except dirs (schemas) and innodb files + FILTER=(-f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') + + RC=0 + rsync --archive --no-times --ignore-times --inplace --delete --quiet \ + $WHOLE_FILE_OPT "${FILTER[@]}" "$DATA" rsync://$ADDR || RC=$? + + [ $RC -ne 0 ] && echo "rsync returned code $RC:" >> /dev/stderr + + case $RC in + 0) RC=0 # Success + ;; + 12) RC=71 # EPROTO + echo "rsync server on the other end has incompatible protocol. " \ + "Make sure you have the same version of rsync on all nodes."\ + >> /dev/stderr + ;; + 22) RC=12 # ENOMEM + ;; + *) RC=255 # unknown error + ;; + esac + + [ $RC -ne 0 ] && exit $RC + + else # BYPASS + STATE="$UUID:$SEQNO" + fi + + echo "continue" # now server can resume updating data + + echo "$STATE" > "$MAGIC_FILE" + rsync -aqc "$MAGIC_FILE" rsync://$ADDR + + echo "done $STATE" + +elif [ "$ROLE" = "joiner" ] +then + MYSQLD_PID=$6 + + MODULE="rsync_sst" + + RSYNC_PID="$DATA/$MODULE.pid" + + if check_pid $RSYNC_PID + then + echo "rsync daemon already running." + exit 114 # EALREADY + fi + rm -rf "$RSYNC_PID" + + RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }') + if [ -z "$RSYNC_PORT" ] + then + RSYNC_PORT=4444 + ADDR="$(echo $ADDR | awk -F ':' '{ print $1 }'):$RSYNC_PORT" + fi + + trap "exit 32" HUP PIPE + trap "exit 3" INT TERM + trap cleanup_joiner EXIT + + MYUID=$(id -u) + MYGID=$(id -g) + RSYNC_CONF="$DATA/$MODULE.conf" + +cat << EOF > "$RSYNC_CONF" +pid file = $RSYNC_PID +use chroot = no +[$MODULE] + path = $DATA + read only = no + timeout = 300 + uid = $MYUID + gid = $MYGID +EOF + +# rm -rf "$DATA"/ib_logfile* # we don't want old logs around + + # listen at all interfaces (for firewalled setups) + rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF" + + until check_pid_and_port $RSYNC_PID $RSYNC_PORT + do + sleep 0.2 + done + + echo "ready $ADDR/$MODULE" + + # wait for SST to complete by monitoring magic file + while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \ + ps -p $MYSQLD_PID >/dev/null + do + sleep 1 + done + + if ! ps -p $MYSQLD_PID >/dev/null + then + echo "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." >&2 + exit 32 + fi + + if [ -r "$MAGIC_FILE" ] + then + cat "$MAGIC_FILE" # output UUID:seqno + else + # this message should cause joiner to abort + echo "rsync process ended without creating '$MAGIC_FILE'" + fi + +# cleanup_joiner +else + echo "Unrecognized role: $ROLE" + exit 22 # EINVAL +fi + +exit 0 diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc new file mode 100644 index 00000000000..5764be39093 --- /dev/null +++ b/sql/wsrep_check_opts.cc @@ -0,0 +1,392 @@ +/* Copyright 2011 Codership Oy + + 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 +#include +//#include +//#include + +#include "wsrep_mysqld.h" + +#include +#include +#include +#include + +/* This file is about checking for correctness of mysql configuration options */ + +struct opt +{ + const char* const name; + const char* value; +}; + +/* A list of options to check. + * At first we assume default values and then see if they are changed on CLI or + * in my.cnf */ +static struct opt opts[] = +{ + { "wsrep_slave_threads", "1" }, // mysqld.cc + { "bind_address", "0.0.0.0" }, // mysqld.cc + { "wsrep_sst_method","mysqldump" }, // mysqld.cc + { "wsrep_sst_receive_address","AUTO"}, // mysqld.cc + { "binlog_format", "ROW" }, // mysqld.cc + { "wsrep_provider", "none" }, // mysqld.cc + { "query_cache_type", "0" }, // mysqld.cc + { "query_cache_size", "0" }, // mysqld.cc + { "locked_in_memory", "0" }, // mysqld.cc + { "wsrep_cluster_address", "0" }, // mysqld.cc + { "locks_unsafe_for_binlog", "0" }, // ha_innodb.cc + { "autoinc_lock_mode", "1" }, // ha_innodb.cc + { 0, 0 } +}; + +enum +{ + WSREP_SLAVE_THREADS, + BIND_ADDRESS, + WSREP_SST_METHOD, + WSREP_SST_RECEIVE_ADDRESS, + BINLOG_FORMAT, + WSREP_PROVIDER, + QUERY_CACHE_TYPE, + QUERY_CACHE_SIZE, + LOCKED_IN_MEMORY, + WSREP_CLUSTER_ADDRESS, + LOCKS_UNSAFE_FOR_BINLOG, + AUTOINC_LOCK_MODE +}; + + +/* A class to make a copy of argv[] vector */ +struct argv_copy +{ + int const argc_; + char** argv_; + + argv_copy (int const argc, const char* const argv[]) : + argc_ (argc), + argv_ (reinterpret_cast(calloc(argc_, sizeof(char*)))) + { + if (argv_) + { + for (int i = 0; i < argc_; ++i) + { + argv_[i] = strdup(argv[i]); + + if (!argv_[i]) + { + argv_free (); // free whatever bee allocated + return; + } + } + } + } + + ~argv_copy () { argv_free (); } + +private: + argv_copy (const argv_copy&); + argv_copy& operator= (const argv_copy&); + + void argv_free() + { + if (argv_) + { + for (int i = 0; (i < argc_) && argv_[i] ; ++i) free (argv_[i]); + free (argv_); + argv_ = 0; + } + } +}; + +/* a short corresponding to '--' byte sequence */ +static short const long_opt_prefix ('-' + ('-' << 8)); + +/* Normalizes long options to have '_' instead of '-' */ +static int +normalize_opts (argv_copy& a) +{ + if (a.argv_) + { + for (int i = 0; i < a.argc_; ++i) + { + char* ptr = a.argv_[i]; + if (long_opt_prefix == *(short*)ptr) // long option + { + ptr += 2; + const char* end = strchr(ptr, '='); + + if (!end) end = ptr + strlen(ptr); + + for (; ptr != end; ++ptr) if ('-' == *ptr) *ptr = '_'; + } + } + + return 0; + } + + return EINVAL; +} + +/* Find required options in the argument list and change their values */ +static int +find_opts (argv_copy& a, struct opt* const opts) +{ + for (int i = 0; i < a.argc_; ++i) + { + char* ptr = a.argv_[i] + 2; // we're interested only in long options + + struct opt* opt = opts; + for (; 0 != opt->name; ++opt) + { + if (!strstr(ptr, opt->name)) continue; // try next option + + /* 1. try to find value after the '=' */ + opt->value = strchr(ptr, '=') + 1; + + /* 2. if no '=', try next element in the argument vector */ + if (reinterpret_cast(1) == opt->value) + { + /* also check that the next element is not an option itself */ + if (i + 1 < a.argc_ && *(a.argv_[i + 1]) != '-') + { + ++i; + opt->value = a.argv_[i]; + } + else opt->value = ""; // no value supplied (like boolean opt) + } + + break; // option found, break inner loop + } + } + + return 0; +} + +/* Parses string for an integer. Returns 0 on success. */ +int get_long_long (const struct opt& opt, long long* const val, int const base) +{ + const char* const str = opt.value; + + if ('\0' != *str) + { + char* endptr; + + *val = strtoll (str, &endptr, base); + + if ('k' == *endptr || 'K' == *endptr) + { + *val *= 1024L; + endptr++; + } + else if ('m' == *endptr || 'M' == *endptr) + { + *val *= 1024L * 1024L; + endptr++; + } + else if ('g' == *endptr || 'G' == *endptr) + { + *val *= 1024L * 1024L * 1024L; + endptr++; + } + + if ('\0' == *endptr) return 0; // the whole string was a valid integer + } + + WSREP_ERROR ("Bad value for *%s: '%s'. Should be integer.", + opt.name, opt.value); + + return EINVAL; +} + +/* This is flimzy coz hell knows how mysql interprets boolean strings... + * and, no, I'm not going to become versed in how mysql handles options - + * I'd rather sing. + + Aha, http://dev.mysql.com/doc/refman/5.1/en/dynamic-system-variables.html: + Variables that have a type of “boolean†can be set to 0, 1, ON or OFF. (If you + set them on the command line or in an option file, use the numeric values.) + + So it is '0' for FALSE, '1' or empty string for TRUE + + */ +int get_bool (const struct opt& opt, bool* const val) +{ + const char* str = opt.value; + + while (isspace(*str)) ++str; // skip initial whitespaces + + ssize_t str_len = strlen(str); + switch (str_len) + { + case 0: + *val = true; + return 0; + case 1: + if ('0' == *str || '1' == *str) + { + *val = ('1' == *str); + return 0; + } + } + + WSREP_ERROR ("Bad value for *%s: '%s'. Should be '0', '1' or empty string.", + opt.name, opt.value); + + return EINVAL; +} + +static int +check_opts (int const argc, const char* const argv[], struct opt opts[]) +{ + /* First, make a copy of argv to be able to manipulate it */ + argv_copy a(argc, argv); + + if (!a.argv_) + { + WSREP_ERROR ("Could not copy argv vector: not enough memory."); + return ENOMEM; + } + + int err = normalize_opts (a); + if (err) + { + WSREP_ERROR ("Failed to normalize options."); + return err; + } + + err = find_opts (a, opts); + if (err) + { + WSREP_ERROR ("Failed to parse options."); + return err; + } + + /* At this point we have updated default values in our option list to + what has been specified on the command line / my.cnf */ + + long long slave_threads; + err = get_long_long (opts[WSREP_SLAVE_THREADS], &slave_threads, 10); + if (err) return err; + + int rcode = 0; + + if (slave_threads > 1) + /* Need to check AUTOINC_LOCK_MODE and LOCKS_UNSAFE_FOR_BINLOG */ + { + long long autoinc_lock_mode; + err = get_long_long (opts[AUTOINC_LOCK_MODE], &autoinc_lock_mode, 10); + if (err) return err; + + bool locks_unsafe_for_binlog; + err = get_bool (opts[LOCKS_UNSAFE_FOR_BINLOG],&locks_unsafe_for_binlog); + if (err) return err; + + if (autoinc_lock_mode != 2) + { + WSREP_ERROR ("Parallel applying (wsrep_slave_threads > 1) requires" + " innodb_autoinc_lock_mode = 2."); + rcode = EINVAL; + } + } + + long long query_cache_size, query_cache_type; + if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10))) + return err; + if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10))) + return err; + + if (0 != query_cache_size && 0 != query_cache_type) + { + WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)", + query_cache_size, query_cache_type); + rcode = EINVAL; + } + + bool locked_in_memory; + err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory); + if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; } + if (locked_in_memory) + { + WSREP_ERROR ("Memory locking is not supported (locked_in_memory=%s)", + locked_in_memory ? "ON" : "OFF"); + rcode = EINVAL; + } + + if (!strcasecmp(opts[WSREP_SST_METHOD].value,"mysqldump")) + { + if (!strcasecmp(opts[BIND_ADDRESS].value, "127.0.0.1") || + !strcasecmp(opts[BIND_ADDRESS].value, "localhost")) + { + WSREP_ERROR ("wsrep_sst_method is set to 'mysqldump' yet " + "mysqld bind_address is set to '%s', which makes it " + "impossible to receive state transfer from another " + "node, since mysqld won't accept such connections. " + "If you wish to use mysqldump state transfer method, " + "set bind_address to allow mysql client connections " + "from other cluster members (e.g. 0.0.0.0).", + opts[BIND_ADDRESS].value); + rcode = EINVAL; + } + } + else + { + // non-mysqldump SST requires wsrep_cluster_address on startup + if (strlen(opts[WSREP_CLUSTER_ADDRESS].value) == 0) + { + WSREP_ERROR ("%s SST method requires wsrep_cluster_address to be " + "configured on startup.",opts[WSREP_SST_METHOD].value); + rcode = EINVAL; + } + } + + if (strcasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, "AUTO")) + { + if (!strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, + "127.0.0.1", strlen("127.0.0.1")) || + !strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, + "localhost", strlen("localhost"))) + { + WSREP_WARN ("wsrep_sst_receive_address is set to '%s' which " + "makes it impossible for another host to reach this " + "one. Please set it to the address which this node " + "can be connected at by other cluster members.", + opts[WSREP_SST_RECEIVE_ADDRESS].value); +// rcode = EINVAL; + } + } + + if (strcasecmp(opts[WSREP_PROVIDER].value, "none")) + { + if (strcasecmp(opts[BINLOG_FORMAT].value, "ROW")) + { + WSREP_ERROR ("Only binlog_format = 'ROW' is currently supported. " + "Configured value: '%s'. Please adjust your " + "configuration.", opts[BINLOG_FORMAT].value); + + rcode = EINVAL; + } + } + + return rcode; +} + +int +wsrep_check_opts (int const argc, char* const* const argv) +{ + return check_opts (argc, argv, opts); +} + diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc new file mode 100644 index 00000000000..9986d7c79cd --- /dev/null +++ b/sql/wsrep_hton.cc @@ -0,0 +1,419 @@ +/* Copyright 2008 Codership Oy + + 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 +#include "sql_base.h" +#include +#include "wsrep_mysqld.h" +#include "wsrep_priv.h" +#include +#include + +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 + +enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); + +/* + a post-commit cleanup on behalf of wsrep. Can't be a part of hton struct. + Is called by THD::transactions.cleanup() +*/ +void wsrep_cleanup_transaction(THD *thd) +{ + if (thd->thread_id == 0) return; + if (thd->wsrep_exec_mode == LOCAL_COMMIT) + { + if (thd->variables.wsrep_on && + thd->wsrep_conflict_state != MUST_REPLAY) + { + if (thd->wsrep_seqno_changed) + { + if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("set committed fail")); + WSREP_WARN("set committed fail: %llu %d", + (long long)thd->real_id, thd->stmt_da->status()); + } + } + //else + //WSREP_DEBUG("no trx handle for %s", thd->query()); + thd_binlog_trx_reset(thd); + thd->wsrep_seqno_changed = false; + } + thd->wsrep_exec_mode= LOCAL_STATE; + } +} + +/* + wsrep hton +*/ +handlerton *wsrep_hton; + +void wsrep_register_hton(THD* thd, bool all) +{ + THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) + { + if (i->ht()->db_type == DB_TYPE_INNODB) + { + trans_register_ha(thd, all, wsrep_hton); + thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + 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_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_ROLLBACK, 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) +{ +#ifndef DBUG_OFF + //wsrep_seqno_t old = thd->wsrep_trx_seqno; +#endif + DBUG_ENTER("wsrep_prepare"); + if ((all || + !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) + { + switch (wsrep_run_wsrep_commit(thd, hton, all)) + { + case WSREP_TRX_OK: + // DBUG_ASSERT(thd->wsrep_trx_seqno > old || + // thd->wsrep_exec_mode == REPL_RECV || + // thd->wsrep_exec_mode == TOTAL_ORDER); + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + +static int wsrep_savepoint_set(handlerton *hton, THD *thd, void *sv) +{ + if (!wsrep_emulate_bin_log) return 0; + int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); + return rcode; +} +static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) +{ + if (!wsrep_emulate_bin_log) return 0; + int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); + return rcode; +} + +static int wsrep_rollback(handlerton *hton, THD *thd, bool all) +{ + DBUG_ENTER("wsrep_rollback"); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) + { + if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("setting rollback fail")); + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + (long long)thd->real_id, thd->query()); + } + } + + int rcode = 0; + if (!wsrep_emulate_bin_log) + { + if (all) thd_binlog_trx_reset(thd); + } + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(rcode); +} + +int wsrep_commit(handlerton *hton, THD *thd, bool all) +{ + DBUG_ENTER("wsrep_commit"); + + DBUG_RETURN(0); +} + +extern my_bool opt_log_slave_updates; +enum wsrep_trx_status +wsrep_run_wsrep_commit( + THD *thd, handlerton *hton, bool all) +{ + int rcode = -1; + uint data_len = 0; + uchar *rbr_data = NULL; + IO_CACHE *cache; + int replay_round= 0; + + if (thd->stmt_da->is_error()) { + WSREP_ERROR("commit issue, error: %d %s", + thd->stmt_da->sql_errno(), thd->stmt_da->message()); + } + + DBUG_ENTER("wsrep_run_wsrep_commit"); + 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_wsrep_thd); + 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_wsrep_thd); + // + // 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_wsrep_thd); + } + if (thd->wsrep_exec_mode != LOCAL_STATE) { + DBUG_RETURN(WSREP_TRX_OK); + } + if (thd->wsrep_consistency_check) { + WSREP_DEBUG("commit for consistency check: %s", thd->query()); + DBUG_RETURN(WSREP_TRX_OK); + } + + DBUG_PRINT("wsrep", ("replicating commit")); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + DBUG_PRINT("wsrep", ("replicate commit fail")); + thd->wsrep_conflict_state = ABORTED; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (wsrep_debug) { + WSREP_INFO("innobase_commit, abort %s", + (thd->query()) ? thd->query() : "void"); + } + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } + + mysql_mutex_lock(&LOCK_wsrep_replaying); + + while (wsrep_replaying > 0 && + thd->wsrep_conflict_state == NO_CONFLICT && + thd->killed == NOT_KILLED && + !shutdown_in_progress) { + + mysql_mutex_unlock(&LOCK_wsrep_replaying); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_mutex_lock(&thd->mysys_var->mutex); + thd_proc_info(thd, "wsrep waiting on replaying"); + thd->mysys_var->current_mutex= &LOCK_wsrep_replaying; + thd->mysys_var->current_cond= &COND_wsrep_replaying; + mysql_mutex_unlock(&thd->mysys_var->mutex); + + mysql_mutex_lock(&LOCK_wsrep_replaying); + // Using timedwait is a hack to avoid deadlock in case if BF victim + // misses the signal. + struct timespec wtime = {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: (%lu) conflict: %d (round: %d)", + wsrep_replaying, 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_wsrep_thd); + 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_wsrep_thd); + WSREP_DEBUG("innobase_commit abort after replaying wait %s", + (thd->query()) ? thd->query() : "void"); + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } thd->wsrep_query_state = QUERY_COMMITTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + cache = get_trans_log(thd); + rcode = 0; + if (cache) { + thd->binlog_flush_pending_rows_event(true); + rcode = wsrep_write_cache(cache, &rbr_data, &data_len); + if (rcode) { + WSREP_ERROR("rbr write fail, data_len: %d, %d", data_len, rcode); + if (data_len) my_free(rbr_data); + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } + } + if (data_len == 0) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_exec_mode = LOCAL_COMMIT; + WSREP_DEBUG("empty rbr buffer, query: %s", thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(WSREP_TRX_OK); + } + if (!rcode) { + rcode = wsrep->pre_commit( + wsrep, + (wsrep_conn_id_t)thd->thread_id, + &thd->wsrep_trx_handle, + rbr_data, + data_len, + (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, + &thd->wsrep_trx_seqno); + if (rcode == WSREP_TRX_MISSING) { + rcode = WSREP_OK; + } else if (rcode == WSREP_BF_ABORT) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state = MUST_REPLAY; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying++; + WSREP_DEBUG("replaying increased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + thd->wsrep_seqno_changed = true; + } else { + WSREP_ERROR("I/O error reading from thd's binlog iocache: " + "errno=%d, io cache code=%d", my_errno, cache->error); + if (data_len) my_free(rbr_data); + DBUG_ASSERT(0); // failure like this can not normally happen + DBUG_RETURN(WSREP_TRX_ERROR); + } + + if (data_len) { + my_free(rbr_data); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + switch(rcode) { + case 0: + thd->wsrep_exec_mode = LOCAL_COMMIT; + /* 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, + wsrep_cluster_uuid(), + thd->wsrep_trx_seqno); + } + DBUG_PRINT("wsrep", ("replicating commit success")); + + break; + case WSREP_TRX_FAIL: + case WSREP_BF_ABORT: + 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; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(WSREP_TRX_ROLLBACK); + + case WSREP_CONN_FAIL: + WSREP_ERROR("connection failure"); + DBUG_RETURN(WSREP_TRX_ERROR); + default: + WSREP_ERROR("unknown connection failure"); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + thd->wsrep_query_state= QUERY_EXEC; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + 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=DB_TYPE_WSREP; + 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 + wsrep_hton->slot= 0; + return 0; +} + + +struct st_mysql_storage_engine wsrep_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + + +mysql_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 */ + NULL, /* config options */ + 0, /* flags */ +} +mysql_declare_plugin_end; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc new file mode 100644 index 00000000000..5a5250652b8 --- /dev/null +++ b/sql/wsrep_mysqld.cc @@ -0,0 +1,1060 @@ +/* Copyright 2008 Codership Oy + + 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 +#include +#include +#include "wsrep_priv.h" +#include +#include +#include "log_event.h" + +wsrep_t *wsrep = NULL; +my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface + +/* + * Begin configuration options and their default values + */ + +const char* wsrep_data_home_dir = NULL; + +#define WSREP_NODE_INCOMING_AUTO "AUTO" +const char* wsrep_node_incoming_address = WSREP_NODE_INCOMING_AUTO; +const char* wsrep_dbug_option = ""; + +long wsrep_slave_threads = 1; // # of slave action appliers wanted +my_bool wsrep_debug = 0; // enable debug level logging +my_bool wsrep_convert_LOCK_to_trx = 1; // convert locking sessions to trx +ulong wsrep_retry_autocommit = 5; // retry aborted autocommit trx +my_bool wsrep_auto_increment_control = 1; // control auto increment variables +my_bool wsrep_drupal_282555_workaround = 1; // retry autoinc insert after dupkey +my_bool wsrep_incremental_data_collection = 0; // incremental data collection +long long wsrep_max_ws_size = 1073741824LL; //max ws (RBR buffer) size +long wsrep_max_ws_rows = 65536; // max number of rows in ws +int wsrep_to_isolation = 0; // # of active TO isolation threads +my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key +long wsrep_max_protocol_version = 1; // maximum protocol version to use +ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; +my_bool wsrep_recovery = 0; // recovery + +/* + * End configuration options + */ + +static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; +const wsrep_uuid_t* wsrep_cluster_uuid() +{ + return &cluster_uuid; +} +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 + */ +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; +const char* wsrep_provider_name = provider_name; +const char* wsrep_provider_version = provider_version; +const char* wsrep_provider_vendor = provider_vendor; +/* End wsrep status variables */ + + +wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; +wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; +wsp::node_status local_status; +long wsrep_protocol_version = 1; + +// action execute callback +extern wsrep_status_t wsrep_apply_cb(void *ctx, + const void* buf, size_t buf_len, + wsrep_seqno_t global_seqno); + +extern wsrep_status_t wsrep_commit_cb (void *ctx, + wsrep_seqno_t global_seqno, + bool commit); + +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: + sql_print_error("WSREP: %s", msg); + break; + case WSREP_LOG_DEBUG: + if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); + default: + break; + } +} + +static void wsrep_log_states (wsrep_log_level_t level, + wsrep_uuid_t* group_uuid, + wsrep_seqno_t group_seqno, + wsrep_uuid_t* node_uuid, + wsrep_seqno_t 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); +} + +static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= reinterpret_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + if (hton->db_type == DB_TYPE_INNODB) + { + const wsrep_uuid_t* uuid(wsrep_xid_uuid(xid)); + char uuid_str[40] = {0, }; + wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(xid)); + hton->wsrep_set_checkpoint(hton, xid); + } + return FALSE; +} + +void wsrep_set_SE_checkpoint(XID* xid) +{ + plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); +} + +static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= reinterpret_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + if (hton->db_type == DB_TYPE_INNODB) + { + hton->wsrep_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_DEBUG("Read WSREPXid from InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(xid)); + + } + return FALSE; +} + +void wsrep_get_SE_checkpoint(XID* xid) +{ + plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); +} + +static void 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, + ssize_t* sst_req_len) +{ + wsrep_member_status_t new_status= local_status.get(); + + if (memcmp(&cluster_uuid, &view->uuid, sizeof(wsrep_uuid_t))) + { + cluster_uuid= view->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->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) { + wsrep_ready= FALSE; + new_status= WSREP_MEMBER_UNDEFINED; + /* Always record local_uuid and local_seqno in non-prim since this + * may lead to re-initializing provider and start position is + * determined according to these variables */ + // 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; + } + + switch (view->proto_ver) + { + case 0: + case 1: + // version change + if (view->proto_ver != wsrep_protocol_version) + { + my_bool wsrep_ready_saved= wsrep_ready; + wsrep_ready= 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= 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= FALSE; + + /* Close client connections to ensure that they don't interfere + * with SST */ + WSREP_DEBUG("[debug]: closing client connections for PRIM"); + wsrep_close_client_connections(TRUE); + + *sst_req_len= wsrep_sst_prepare (sst_req); + + if (*sst_req_len < 0) + { + int err = *sst_req_len; + WSREP_ERROR("SST preparation failed: %d (%s)", -err, strerror(-err)); + new_status= WSREP_MEMBER_UNDEFINED; + } + else + { + new_status= WSREP_MEMBER_JOINER; + } + } + else + { + /* + * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized + * before. + */ + if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t))) + { + if (wsrep_init_first()) + { + wsrep_SE_init_grab(); + // Signal init thread to continue + wsrep_sst_complete (&cluster_uuid, view->seqno, false); + // and wait for SE initialization + wsrep_SE_init_wait(); + } + else + { + local_uuid= cluster_uuid; + local_seqno= view->seqno; + } + /* Init storage engine XIDs from first view */ + XID xid; + wsrep_xid_init(&xid, &local_uuid, local_seqno); + wsrep_set_SE_checkpoint(&xid); + new_status= WSREP_MEMBER_JOINED; + } + else // 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->seqno, + &local_uuid, -1); + abort(); + } + } + } + + if (wsrep_auto_increment_control) + { + global_system_variables.auto_increment_offset= view->my_idx + 1; + global_system_variables.auto_increment_increment= view->memb_num; + } + +out: + + local_status.set(new_status, view); +} + +// Wait until wsrep has reached ready state +void wsrep_ready_wait () +{ + 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); +} + +static void wsrep_synced_cb(void* app_ctx) +{ + WSREP_INFO("Synchronized with group, ready for connections"); + if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); + if (!wsrep_ready) + { + wsrep_ready= TRUE; + mysql_cond_signal (&COND_wsrep_ready); + } + local_status.set(WSREP_MEMBER_SYNCED); + mysql_mutex_unlock (&LOCK_wsrep_ready); +} + +static void wsrep_init_position() +{ + /* read XIDs from storage engines */ + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + wsrep_get_SE_checkpoint(&xid); + + if (xid.formatID == -1) + { + WSREP_INFO("Read nil XID from storage engines, skipping position init"); + return; + } + else if (!wsrep_is_wsrep_xid(&xid)) + { + WSREP_WARN("Read non-wsrep XID from storage engines, skipping position init"); + return; + } + + const wsrep_uuid_t* uuid= wsrep_xid_uuid(&xid); + const wsrep_seqno_t seqno= wsrep_xid_seqno(&xid); + + 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"); + } +} + + +int wsrep_init() +{ + int rcode= -1; + + wsrep_ready= 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 + (void) wsrep_init(); + return rcode; + } + 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); + } + } + + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) + { + // enable normal operation in case no provider is specified + wsrep_ready= TRUE; + global_system_variables.wsrep_on = 0; + } + 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); + } + + struct wsrep_init_args wsrep_args; + + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + wsrep_data_home_dir = mysql_real_data_home; + + if (strcmp (wsrep_provider, WSREP_NONE) && + (!wsrep_node_incoming_address || + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + static char inc_addr[256]; + size_t inc_addr_max = sizeof (inc_addr); + size_t ret = default_address (inc_addr, inc_addr_max); + if (ret > 0 && ret < inc_addr_max) { + wsrep_node_incoming_address = inc_addr; + } + else { + wsrep_node_incoming_address = NULL; + } + } + + wsrep_args.data_dir = wsrep_data_home_dir; + wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; + wsrep_args.node_address = (wsrep_node_address) ? wsrep_node_address : ""; + wsrep_args.node_incoming = wsrep_node_incoming_address; + wsrep_args.options = (wsrep_provider_options) ? + wsrep_provider_options : ""; + wsrep_args.proto_ver = wsrep_max_protocol_version; + + wsrep_args.state_uuid = &local_uuid; + wsrep_args.state_seqno = local_seqno; + + 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.sst_donate_cb = wsrep_sst_donate_cb; + wsrep_args.synced_cb = wsrep_synced_cb; + + rcode = wsrep->init(wsrep, &wsrep_args); + + if (rcode) + { + DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); + WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); + free(wsrep); + wsrep = NULL; + } + + return rcode; +} + +extern "C" int wsrep_on(void *); + +void wsrep_init_startup (bool first) +{ + if (wsrep_init()) unireg_abort(1); + + wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd, + wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); + + /* Skip replication start if no cluster address */ + if (!wsrep_cluster_address || strlen(wsrep_cluster_address) == 0) return; + + if (first) wsrep_sst_grab(); // do it so we can wait for SST below + + 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 +} + + +void wsrep_deinit() +{ + wsrep_unload(wsrep); + wsrep= 0; + provider_name[0]= '\0'; + provider_version[0]= '\0'; + provider_vendor[0]= '\0'; +} + +void wsrep_recover() +{ + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + wsrep_get_SE_checkpoint(&xid); + char uuid_str[40]; + wsrep_uuid_print(wsrep_xid_uuid(&xid), uuid_str, sizeof(uuid_str)); + WSREP_INFO("Recovered position: %s:%lld", uuid_str, + (long long)wsrep_xid_seqno(&xid)); +} + + +void wsrep_stop_replication(THD *thd) +{ + WSREP_INFO("Stop replication"); + if (!wsrep) + { + WSREP_INFO("Provider was not loaded, in stop replication"); + return; + } + + /* disconnect from group first to get wsrep_ready == FALSE */ + WSREP_DEBUG("Provider disconnect"); + wsrep->disconnect(wsrep); + + wsrep_connected= FALSE; + + wsrep_close_client_connections(TRUE); + + /* wait until appliers have stopped */ + wsrep_wait_appliers_close(thd); + + return; +} + + +bool wsrep_start_replication() +{ + wsrep_status_t rcode; + + /* + if provider is trivial, don't even try to connect, + but resume local node operation + */ + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) + { + // enable normal operation in case no provider is specified + wsrep_ready = TRUE; + return true; + } + + if (!wsrep_cluster_address || strlen(wsrep_cluster_address)== 0) + { + // if provider is non-trivial, but no address is specified, wait for address + wsrep_ready = FALSE; + return true; + } + + WSREP_INFO("Start replication"); + + if ((rcode = wsrep->connect(wsrep, + wsrep_cluster_name, + wsrep_cluster_address, + wsrep_sst_donor))) + { + if (-ESOCKTNOSUPPORT == rcode) + { + DBUG_PRINT("wsrep",("unrecognized cluster address: '%s', rcode: %d", + wsrep_cluster_address, rcode)); + WSREP_ERROR("unrecognized cluster address: '%s', rcode: %d", + wsrep_cluster_address, rcode); + } + else + { + DBUG_PRINT("wsrep",("wsrep->connect() failed: %d", rcode)); + WSREP_ERROR("wsrep::connect() failed: %d", rcode); + } + + return false; + } + else + { + wsrep_connected= TRUE; + + uint64_t caps = wsrep->capabilities (wsrep); + + wsrep_incremental_data_collection = + (caps & WSREP_CAP_WRITE_SET_INCREMENTS); + + char* opts= wsrep->options_get(wsrep); + if (opts) + { + wsrep_provider_options_init(opts); + free(opts); + } + else + { + WSREP_WARN("Failed to get wsrep options"); + } + } + + return true; +} + +bool +wsrep_causal_wait (THD* thd) +{ + if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on && + !thd->in_active_multi_stmt_transaction()) + { + // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 + // TODO: modify to check if thd has locked any rows. + wsrep_seqno_t seqno; + wsrep_status_t ret= wsrep->causal_read (wsrep, &seqno); + + if (unlikely(WSREP_OK != ret)) + { + 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 + + switch (ret) + { + case WSREP_NOT_IMPLEMENTED: + msg= "consistent reads by wsrep backend. " + "Please unset wsrep_causal_reads variable."; + err= ER_NOT_SUPPORTED_YET; + break; + default: + msg= "Causal wait failed."; + err= ER_ERROR_ON_READ; + } + + my_error(err, MYF(0), msg); + + return true; + } + } + + return false; +} + +bool wsrep_prepare_key_for_isolation(const char* db, + const char* table, + wsrep_key_part_t* key, + size_t* key_len) +{ + if (*key_len < 2) return false; + + switch (wsrep_protocol_version) + { + case 0: + *key_len= 0; + break; + case 1: + { + *key_len= 0; + if (db) + { + // sql_print_information("%s.%s", db, table); + if (db) + { + key[*key_len].buf= db; + key[*key_len].buf_len= strlen(db); + ++(*key_len); + if (table) + { + key[*key_len].buf= table; + key[*key_len].buf_len= strlen(table); + ++(*key_len); + } + } + } + break; + } + default: + return false; + } + + return true; +} + +bool wsrep_prepare_key_for_innodb(const uchar* cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len) +{ + if (*key_len < 3) return false; + + *key_len= 0; + switch (wsrep_protocol_version) + { + case 0: + { + key[*key_len].buf = cache_key; + key[*key_len].buf_len = cache_key_len; + ++(*key_len); + break; + } + case 1: + { + key[*key_len].buf = cache_key; + key[*key_len].buf_len = strlen( (char*)cache_key ); + ++(*key_len); + key[*key_len].buf = cache_key + strlen( (char*)cache_key ) + 1; + key[*key_len].buf_len = strlen( (char*)(key[*key_len].buf) ); + ++(*key_len); + break; + } + default: + return false; + } + + key[*key_len].buf = row_id; + key[*key_len].buf_len = row_id_len; + ++(*key_len); + + return true; +} + +/* + * Construct Query_log_Event from thd query and serialize it + * into buffer. + * + * Return 0 in case of success, 1 in case of error. + */ +int wsrep_to_buf_helper( + THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len) +{ + IO_CACHE tmp_io_cache; + if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, + 65536, MYF(MY_WME))) + return 1; + Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); + int ret(0); + if (ev.write(&tmp_io_cache)) ret= 1; + if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; + close_cached_file(&tmp_io_cache); + return ret; +} + +#include "sql_show.h" +static int +create_view_query(THD *thd, uchar** buf, uint* buf_len) +{ + LEX *lex= thd->lex; + SELECT_LEX *select_lex= &lex->select_lex; + TABLE_LIST *first_table= select_lex->table_list.first; + TABLE_LIST *views = first_table; + + String buff; + const LEX_STRING command[3]= + {{ C_STRING_WITH_LEN("CREATE ") }, + { C_STRING_WITH_LEN("ALTER ") }, + { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; + + buff.append(command[thd->lex->create_view_mode].str, + command[thd->lex->create_view_mode].length); + + if (!lex->definer) + { + /* + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. + */ + + if (!(lex->definer= create_default_definer(thd))) + { + WSREP_WARN("view default definer issue"); + } + } + + views->algorithm = lex->create_view_algorithm; + views->definer.user = lex->definer->user; + views->definer.host = lex->definer->host; + 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 ")); + /* Test if user supplied a db (ie: we did not use thd->db) */ + if (views->db && views->db[0] && + (thd->db == NULL || strcmp(views->db, thd->db))) + { + append_identifier(thd, &buff, views->db, + views->db_length); + buff.append('.'); + } + append_identifier(thd, &buff, views->table_name, + views->table_name_length); + if (lex->view_list.elements) + { + List_iterator_fast names(lex->view_list); + LEX_STRING *name; + int i; + + for (i= 0; (name= names++); i++) + { + buff.append(i ? ", " : "("); + append_identifier(thd, &buff, name->str, name->length); + } + 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); +} + +static int wsrep_TOI_begin(THD *thd, char *db_, char *table_) +{ + wsrep_status_t ret(WSREP_WARNING); + uchar* buf(0); + uint buf_len(0); + int buf_err; + + wsrep_key_part_t wkey_part[2]; + wsrep_key_t wkey = {wkey_part, 2}; + WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + switch (thd->lex->sql_command) + { + case SQLCOM_CREATE_VIEW: + buf_err= create_view_query(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_PROCEDURE: + case SQLCOM_CREATE_SPFUNCTION: + buf_err= wsrep_create_sp(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_TRIGGER: + buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_EVENT: + buf_err= wsrep_create_event_query(thd, &buf, &buf_len); + break; + default: + buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, + &buf_len); + break; + } + + if (!buf_err && + wsrep_prepare_key_for_isolation(db_, table_, wkey_part, + &wkey.key_parts_len) && + WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, + &wkey, 1, + buf, buf_len, + &thd->wsrep_trx_seqno))) + { + thd->wsrep_exec_mode= TOTAL_ORDER; + wsrep_to_isolation++; + if (buf) my_free(buf); + WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode); + } + else { + /* jump to error handler in mysql_execute_command() */ + WSREP_WARN("TO isolation failed for: %d, sql: %s. Check wsrep " + "connection state and retry the query.", + ret, (thd->query()) ? thd->query() : "void"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " + "your wsrep connection state and retry the query."); + if (buf) my_free(buf); + return -1; + } + return 0; +} + +static void wsrep_TOI_end(THD *thd) { + wsrep_status_t ret; + wsrep_to_isolation--; + WSREP_DEBUG("TO END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void") + if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { + WSREP_DEBUG("TO END: %lld", (long long)thd->wsrep_trx_seqno); + } + else { + WSREP_WARN("TO isolation end failed for: %d, sql: %s", + ret, (thd->query()) ? thd->query() : "void"); + } +} + +static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) +{ + wsrep_status_t ret(WSREP_WARNING); + WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + + ret = wsrep->desync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("desync failed %d for %s", ret, thd->query()); + return(ret); + } + wsrep_seqno_t seqno = wsrep->pause(wsrep); + if (seqno == WSREP_SEQNO_UNDEFINED) + { + WSREP_WARN("pause failed %lld for %s", (long long)seqno, thd->query()); + return(1); + } + 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)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + + ret = wsrep->resume(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resume failed %d for %s", ret, thd->query()); + } + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for %s", ret, thd->query()); + return; + } + thd->variables.wsrep_on = 1; + return; +} + +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_) +{ + int ret= 0; + if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) + { + switch (wsrep_OSU_method_options) { + case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_); break; + case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; + } + if (!ret) + { + thd->wsrep_exec_mode= TOTAL_ORDER; + } + } + return ret; +} + +void wsrep_to_isolation_end(THD *thd) { + if (thd->wsrep_exec_mode==TOTAL_ORDER) + { + switch(wsrep_OSU_method_options) + { + case WSREP_OSU_TOI: return wsrep_TOI_end(thd); + case WSREP_OSU_RSU: return wsrep_RSU_end(thd); + } + } +} + +#define WSREP_MDL_LOG(severity, msg, req, gra) \ + WSREP_##severity( \ + "%s\n" \ + "request: (%lu \tseqno %lld \tmode %d \tQstate \t%d cmd %d %d \t%s)\n" \ + "granted: (%lu \tseqno %lld \tmode %d \tQstate \t%d cmd %d %d \t%s)", \ + msg, \ + req->thread_id, (long long)req->wsrep_trx_seqno, \ + req->wsrep_exec_mode, req->wsrep_query_state, \ + req->command, req->lex->sql_command, req->query(), \ + gra->thread_id, (long long)gra->wsrep_trx_seqno, \ + gra->wsrep_exec_mode, gra->wsrep_query_state, \ + gra->command, gra->lex->sql_command, gra->query()); + +bool +wsrep_grant_mdl_exception(MDL_context *requestor_ctx, + MDL_ticket *ticket +) { + if (!WSREP_ON) return FALSE; + + THD *request_thd = requestor_ctx->get_thd(); + THD *granted_thd = ticket->get_ctx()->get_thd(); + + mysql_mutex_lock(&request_thd->LOCK_wsrep_thd); + if (request_thd->wsrep_exec_mode == TOTAL_ORDER || + request_thd->wsrep_exec_mode == REPL_RECV) + { + mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); + WSREP_MDL_LOG(DEBUG, "MDL conflict", request_thd, granted_thd); + + mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); + if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || + granted_thd->wsrep_exec_mode == REPL_RECV) + { + WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + return TRUE; + } + else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) + { + WSREP_DEBUG("mdl granted over FLUSH BF"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + return TRUE; + } + else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) + { + WSREP_DEBUG("DROP caused BF abort"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + return FALSE; + } + else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) + { + WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + return FALSE; + } + else + { + WSREP_MDL_LOG(INFO, "MDL conflict -> BF abort", request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + return FALSE; + } + } + else + { + mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); + } + return FALSE; +} diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h new file mode 100644 index 00000000000..90498c266ee --- /dev/null +++ b/sql/wsrep_mysqld.h @@ -0,0 +1,297 @@ +/* Copyright 2008 Codership Oy + + 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_MYSQLD_H +#define WSREP_MYSQLD_H + +#include "mysqld.h" +typedef struct st_mysql_show_var SHOW_VAR; +//#include +#include +#include "../wsrep/wsrep_api.h" +//#include + +class set_var; +class THD; + +// Global wsrep parameters +extern wsrep_t* wsrep; + +// MySQL wsrep options +extern const char* wsrep_provider; +extern const char* wsrep_provider_options; +extern const char* wsrep_cluster_name; +extern const char* wsrep_cluster_address; +extern const char* wsrep_node_name; +extern const char* wsrep_node_address; +extern const char* wsrep_node_incoming_address; +extern const char* wsrep_data_home_dir; +extern const char* wsrep_dbug_option; +extern long wsrep_slave_threads; +extern 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_sst_method; +extern const char* wsrep_sst_receive_address; +extern char* wsrep_sst_auth; +extern const char* wsrep_sst_donor; +extern const char* wsrep_start_position; +extern long long wsrep_max_ws_size; +extern long wsrep_max_ws_rows; +extern const char* wsrep_notify_cmd; +extern my_bool wsrep_certify_nonPK; +extern long wsrep_max_protocol_version; +extern long wsrep_protocol_version; +extern ulong wsrep_forced_binlog_format; +extern ulong wsrep_OSU_method_options; +extern my_bool wsrep_recovery; + +enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; + +// MySQL status variables +extern my_bool wsrep_connected; +extern my_bool wsrep_ready; +extern const char* wsrep_cluster_state_uuid; +extern long long wsrep_cluster_conf_id; +extern const char* wsrep_cluster_status; +extern long wsrep_cluster_size; +extern long wsrep_local_index; +extern const char* wsrep_provider_name; +extern const char* wsrep_provider_version; +extern const char* wsrep_provider_vendor; +extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); + +#define WSREP_SST_ADDRESS_AUTO "AUTO" +// MySQL variables funcs + +#define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) +#define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) +#define DEFAULT_ARGS (THD* thd, enum_var_type var_type) +#define INIT_ARGS (const char* opt) + +extern int wsrep_init_vars(); + +extern bool wsrep_on_update UPDATE_ARGS; +extern void wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_start_position_check CHECK_ARGS; +extern bool wsrep_start_position_update UPDATE_ARGS; +extern void wsrep_start_position_init INIT_ARGS; + +extern bool wsrep_provider_check CHECK_ARGS; +extern bool wsrep_provider_update UPDATE_ARGS; +extern void wsrep_provider_init INIT_ARGS; + +extern bool wsrep_provider_options_check CHECK_ARGS; +extern bool wsrep_provider_options_update UPDATE_ARGS; +extern void wsrep_provider_options_init INIT_ARGS; + +extern bool wsrep_cluster_address_check CHECK_ARGS; +extern bool wsrep_cluster_address_update UPDATE_ARGS; +extern void wsrep_cluster_address_init INIT_ARGS; + +extern bool wsrep_cluster_name_check CHECK_ARGS; +extern bool wsrep_cluster_name_update UPDATE_ARGS; + +extern bool wsrep_node_name_check CHECK_ARGS; +extern bool wsrep_node_name_update UPDATE_ARGS; + +extern bool wsrep_node_address_check CHECK_ARGS; +extern bool wsrep_node_address_update UPDATE_ARGS; +extern void wsrep_node_address_init INIT_ARGS; + +extern bool wsrep_sst_method_check CHECK_ARGS; +extern bool wsrep_sst_method_update UPDATE_ARGS; +extern void wsrep_sst_method_init INIT_ARGS; + +extern bool wsrep_sst_receive_address_check CHECK_ARGS; +extern bool wsrep_sst_receive_address_update UPDATE_ARGS; + +extern bool wsrep_sst_auth_check CHECK_ARGS; +extern bool wsrep_sst_auth_update UPDATE_ARGS; +extern void wsrep_sst_auth_init INIT_ARGS; + +extern bool wsrep_sst_donor_check CHECK_ARGS; +extern bool wsrep_sst_donor_update UPDATE_ARGS; + + +extern bool wsrep_init_first(); // initialize wsrep before storage + // engines or after +extern int wsrep_init(); +extern void wsrep_deinit(); +extern void wsrep_recover(); + +/* wsrep initialization sequence at startup + * @param first wsrep_init_first() value */ +extern void wsrep_init_startup(bool first); + +extern void wsrep_close_client_connections(my_bool wait_to_end); +extern void wsrep_close_applier(THD *thd); +extern void wsrep_wait_appliers_close(THD *thd); +extern void wsrep_create_appliers(long threads = wsrep_slave_threads); +extern void wsrep_create_rollbacker(); +extern void wsrep_kill_mysql(THD *thd); + +/* new defines */ +extern void wsrep_stop_replication(THD *thd); +extern bool wsrep_start_replication(); +extern bool wsrep_causal_wait(THD* thd); +extern int wsrep_check_opts (int argc, char* const* argv); +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(thd) \ + (WSREP_ON && (thd && thd->variables.wsrep_on)) + +#define WSREP_EMULATE_BINLOG(thd) \ + (WSREP(thd) && wsrep_emulate_bin_log) + +// MySQL logging functions don't seem to understand long long length modifer. +// This is a workaround. It also prefixes all messages with "WSREP" +#define WSREP_LOG(fun, ...) \ + { \ + char msg[256] = {'\0'}; \ + snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ + fun("WSREP: %s", msg); \ + } + +#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__) + +/*! Synchronizes applier thread start with init thread */ +extern void wsrep_sst_grab(); +/*! Init thread waits for SST completion */ +extern bool wsrep_sst_wait(); +/*! Signals wsrep that initialization is complete, writesets can be applied */ +extern void wsrep_sst_continue(); + +extern void wsrep_SE_init_grab(); /*! grab init critical section */ +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 */ + +extern void wsrep_ready_wait(); + +enum wsrep_trx_status { + WSREP_TRX_OK, + WSREP_TRX_ROLLBACK, + WSREP_TRX_ERROR, + }; + +extern enum wsrep_trx_status +wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); +class Ha_trx_info; +struct THD_TRANS; +void wsrep_register_hton(THD* thd, bool all); + +/*! + * @param db Database string + * @param table Table string + * @param key Array of wsrep_key_t + * @param key_len In: number of elements in key array, Out: number of + * elements populated + * + * @return true if preparation was successful, otherwise false. + */ +bool wsrep_prepare_key_for_isolation(const char* db, + const char* table, + wsrep_key_part_t* key, + size_t *key_len); + +void wsrep_replication_process(THD *thd); +void wsrep_rollback_process(THD *thd); +void wsrep_brute_force_killer(THD *thd); +int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id); +extern "C" bool wsrep_consistency_check(void *thd_ptr); +extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); +extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, + my_bool signal); +extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); +void *wsrep_prepare_bf_thd(THD *thd); +void wsrep_return_from_bf_mode(void *shadow, THD *thd); + +/* this is visible for client build so that innodb plugin gets this */ +typedef struct wsrep_aborting_thd { + struct wsrep_aborting_thd *next; + THD *aborting_thd; +} *wsrep_aborting_thd_t; + +extern mysql_mutex_t LOCK_wsrep_ready; +extern mysql_cond_t COND_wsrep_ready; +extern mysql_mutex_t LOCK_wsrep_sst; +extern mysql_cond_t COND_wsrep_sst; +extern mysql_mutex_t LOCK_wsrep_sst_init; +extern mysql_cond_t COND_wsrep_sst_init; +extern mysql_mutex_t LOCK_wsrep_rollback; +extern mysql_cond_t COND_wsrep_rollback; +extern int wsrep_replaying; +extern mysql_mutex_t LOCK_wsrep_replaying; +extern mysql_cond_t COND_wsrep_replaying; +extern wsrep_aborting_thd_t wsrep_aborting_thd; +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_emulate_bin_log; +extern my_bool wsrep_auto_increment_control; +extern my_bool wsrep_drupal_282555_workaround; +extern long long wsrep_max_ws_size; +extern long wsrep_max_ws_rows; +extern int wsrep_to_isolation; +extern my_bool wsrep_certify_nonPK; + +extern PSI_mutex_key key_LOCK_wsrep_ready; +extern PSI_mutex_key key_COND_wsrep_ready; +extern PSI_mutex_key key_LOCK_wsrep_sst; +extern PSI_cond_key key_COND_wsrep_sst; +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; + +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_); +void wsrep_to_isolation_end(THD *thd); + +void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); +void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow*); +int wsrep_to_buf_helper( + THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len); +int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len); +int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len); +int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len); + +const wsrep_uuid_t* wsrep_cluster_uuid(); +struct xid_t; +void wsrep_set_SE_checkpoint(xid_t*); + +void wsrep_xid_init(xid_t*, const wsrep_uuid_t*, wsrep_seqno_t); +const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*); +wsrep_seqno_t wsrep_xid_seqno(const xid_t*); +extern "C" int wsrep_is_wsrep_xid(const void* xid); + +#endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc new file mode 100644 index 00000000000..ff997d01183 --- /dev/null +++ b/sql/wsrep_notify.cc @@ -0,0 +1,107 @@ +/* Copyright 2010 Codership Oy + + 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 +#include "wsrep_priv.h" + +const char* wsrep_notify_cmd=""; + +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) +{ + if (!wsrep_notify_cmd || 0 == strlen(wsrep_notify_cmd)) + { + WSREP_INFO("wsrep_notify_cmd is not defined, skipping notification."); + return; + } + + 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; + + 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); + } + + if (0 != view) + { + char uuid_str[40]; + + wsrep_uuid_print (&view->uuid, uuid_str, sizeof(uuid_str)); + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --uuid %s", uuid_str); + + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --primary %s", view->view >= 0 ? "yes" : "no"); + + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --index %d", view->my_idx); + + 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); + } + } + + if (cmd_off == cmd_len) + { + WSREP_ERROR("Notification buffer too short (%ld). Aborting notification.", + cmd_len); + return; + } + + wsp::process p(cmd_ptr, "r"); + + p.wait(); + int err = p.error(); + + if (err) + { + WSREP_ERROR("Notification command failed: %d (%s): \"%s\"", + err, strerror(err), cmd_ptr); + } +} + diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h new file mode 100644 index 00000000000..4db8abf68de --- /dev/null +++ b/sql/wsrep_priv.h @@ -0,0 +1,231 @@ +/* Copyright 2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//! @file declares symbols private to wsrep integration layer + +#ifndef WSREP_PRIV_H +#define WSREP_PRIV_H + +#include "wsrep_mysqld.h" +#include "../wsrep/wsrep_api.h" + +#include +#include +#include + +extern ssize_t wsrep_sst_prepare (void** msg); +extern int wsrep_sst_donate_cb (void* app_ctx, + void* recv_ctx, + const void* msg, size_t msg_len, + const wsrep_uuid_t* current_uuid, + wsrep_seqno_t current_seqno, + const char* state, size_t state_len, + bool bypass); + +extern size_t default_ip (char* buf, size_t buf_len); +extern size_t default_address(char* buf, size_t buf_len); + +extern wsrep_uuid_t local_uuid; +extern wsrep_seqno_t local_seqno; + +/*! SST thread signals init thread about sst completion */ +extern void wsrep_sst_complete(wsrep_uuid_t* uuid, wsrep_seqno_t seqno, bool); + +extern void wsrep_notify_status (wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0); + +namespace wsp { +class node_status +{ +public: + node_status() : status(WSREP_MEMBER_UNDEFINED) {} + void set(wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0) + { + if (status != new_status || 0 != view) + { + wsrep_notify_status(new_status, view); + status = new_status; + } + } + wsrep_member_status_t get() const { return status; } +private: + wsrep_member_status_t status; +}; +} /* namespace wsp */ + +extern wsp::node_status local_status; + +namespace wsp { +/* A small class to run external programs. */ +class process +{ +private: + const char* const str_; + FILE* io_; + int err_; + pid_t pid_; + +public: +/*! @arg type is a pointer to a null-terminated string which must contain + either the letter 'r' for reading or the letter 'w' for writing. + */ + process (const char* cmd, const char* type); + ~process (); + + FILE* pipe () { return io_; } + int error() { return err_; } + int wait (); + const char* cmd() { return str_; } +}; +#ifdef REMOVED +class lock +{ + pthread_mutex_t* const mtx_; + +public: + + lock (pthread_mutex_t* mtx) : mtx_(mtx) + { + int err = pthread_mutex_lock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex lock failed: %s", strerror(err)); + abort(); + } + } + + virtual ~lock () + { + int err = pthread_mutex_unlock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); + abort(); + } + } + + inline void wait (pthread_cond_t* cond) + { + pthread_cond_wait (cond, mtx_); + } + +private: + + lock (const lock&); + lock& operator=(const lock&); + +}; + +class monitor +{ + int mutable refcnt; + pthread_mutex_t mutable mtx; + pthread_cond_t mutable cond; + +public: + + monitor() : refcnt(0) + { + pthread_mutex_init (&mtx, NULL); + pthread_cond_init (&cond, NULL); + } + + ~monitor() + { + pthread_mutex_destroy (&mtx); + pthread_cond_destroy (&cond); + } + + void enter() const + { + lock l(&mtx); + + while (refcnt) + { + l.wait(&cond); + } + refcnt++; + } + + void leave() const + { + lock l(&mtx); + + refcnt--; + if (refcnt == 0) + { + pthread_cond_signal (&cond); + } + } + +private: + + monitor (const monitor&); + monitor& operator= (const monitor&); +}; + +class critical +{ + const monitor& mon; + +public: + + critical(const monitor& m) : mon(m) { mon.enter(); } + + ~critical() { mon.leave(); } + +private: + + critical (const critical&); + critical& operator= (const critical&); +}; +#endif + +class thd +{ + class thd_init + { + public: + thd_init() { my_thread_init(); } + ~thd_init() { my_thread_end(); } + } + init; + + thd (const thd&); + thd& operator= (const thd&); + +public: + + thd(); + ~thd(); + THD* const ptr; +}; + +class string +{ +public: + string() : string_(0) {} + void set(char* str) { if (string_) free (string_); string_ = str; } + ~string() { set (0); } +private: + char* string_; +}; + +} // namespace wsrep +#endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc new file mode 100644 index 00000000000..4ce7fe84b0f --- /dev/null +++ b/sql/wsrep_sst.cc @@ -0,0 +1,932 @@ +/* Copyright 2008-2011 Codership Oy + + 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 +#include +#include +#include +#include +#include +#include "wsrep_priv.h" +#include +#include + +extern const char wsrep_defaults_file[]; + +#define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP +#define WSREP_SST_ADDRESS_AUTO "AUTO" +#define WSREP_SST_AUTH_MASK "********" + +const char* wsrep_sst_method = WSREP_SST_DEFAULT; +const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; +const char* wsrep_sst_donor = ""; + char* wsrep_sst_auth = NULL; + +// container for real auth string +static const char* sst_auth_real = NULL; + +static const char *sst_methods[] = { + "mysqldump", + "rsync", + "rsync_wan", + "xtrabackup", + NULL +}; + +bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* c_str = NULL; + + if ((res = var->value->val_str(&str))) { + c_str = res->c_ptr(); + int i = 0; + + while (sst_methods[i] && strcasecmp(sst_methods[i], c_str)) i++; + if (!sst_methods[i]) { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); + return 1; + } + } + return 0; +} + +bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +static bool sst_receive_address_check (const char* str) +{ + if (!strncasecmp(str, "127.0.0.1", strlen("127.0.0.1")) || + !strncasecmp(str, "localhost", strlen("localhost"))) + { + return 1; + } + + return 0; +} + +bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) +{ + const char* c_str = var->value->str_value.c_ptr(); + + if (sst_receive_address_check (c_str)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_receive_address", c_str ? c_str : "NULL"); + return 1; + } + + return 0; +} + +bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, + enum_var_type type) +{ + return 0; +} + +bool wsrep_sst_auth_check (sys_var *self, THD* thd, set_var* var) +{ + return 0; +} +static bool sst_auth_real_set (const char* value) +{ + const char* v = strdup (value); + + if (v) + { + if (sst_auth_real) free (const_cast(sst_auth_real)); + sst_auth_real = v; + + if (strlen(sst_auth_real)) + { + if (wsrep_sst_auth) + { + my_free ((void*)wsrep_sst_auth); + wsrep_sst_auth = my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); + //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, + // sizeof(wsrep_sst_auth) - 1); + } + else + wsrep_sst_auth = my_strdup (WSREP_SST_AUTH_MASK, MYF(0)); + } + return 0; + } + + return 1; +} + +bool wsrep_sst_auth_update (sys_var *self, THD* thd, enum_var_type type) +{ + return sst_auth_real_set (wsrep_sst_auth); +} + +void wsrep_sst_auth_init (const char* value) +{ + if (wsrep_sst_auth == value) wsrep_sst_auth = NULL; + if (value) sst_auth_real_set (value); +} + +bool wsrep_sst_donor_check (sys_var *self, THD* thd, set_var* var) +{ + return 0; +} + +bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; + +bool wsrep_init_first() +{ + return (wsrep_provider != NULL + && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); +} + +static bool sst_complete = false; +static bool sst_needed = false; + +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 () +{ + if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); + while (!sst_complete) + { + WSREP_INFO("Waiting for SST to complete."); + mysql_cond_wait (&COND_wsrep_sst, &LOCK_wsrep_sst); + } + + 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 (wsrep_uuid_t* sst_uuid, + wsrep_seqno_t sst_seqno, + bool needed) +{ + 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 + { + WSREP_WARN("Nobody is waiting for SST."); + } + mysql_mutex_unlock (&LOCK_wsrep_sst); +} + +// Let applier threads to continue +void wsrep_sst_continue () +{ + if (sst_needed) + { + WSREP_INFO("Signalling provider to continue."); + wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + } +} + +struct sst_thread_arg +{ + const char* cmd; + int err; + char* ret_str; + mysql_mutex_t lock; + mysql_cond_t cond; + + sst_thread_arg (const char* c) : cmd(c), err(-1), ret_str(0) + { + mysql_mutex_init(key_LOCK_wsrep_sst_thread, + &lock, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL); + } + + ~sst_thread_arg() + { + mysql_cond_destroy (&cond); + mysql_mutex_unlock (&lock); + mysql_mutex_destroy (&lock); + } +}; + +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); + if (offt > 0 && strlen(str) > (unsigned int)offt && ':' == str[offt]) + { + *seqno = strtoll (str + offt + 1, NULL, 10); + if (*seqno != LLONG_MAX || errno != ERANGE) + { + return 0; + } + } + + WSREP_ERROR("Failed to parse uuid:seqno pair: '%s'", str); + return EINVAL; +} + +// get rid of trailing \n +static char* my_fgets (char* buf, size_t buf_len, FILE* stream) +{ + char* ret= fgets (buf, buf_len, stream); + + if (ret) + { + size_t len = strlen(ret); + if (len > 0 && ret[len - 1] == '\n') ret[len - 1] = '\0'; + } + + return ret; +} + +static void* sst_joiner_thread (void* a) +{ + sst_thread_arg* arg= (sst_thread_arg*) a; + int err= 1; + + { + 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); + + wsp::process proc (arg->cmd, "r"); + + if (proc.pipe() && !proc.error()) + { + const char* tmp= my_fgets (out, out_len, proc.pipe()); + + if (!tmp || strlen(tmp) < (magic_len + 2) || + strncasecmp (tmp, magic, magic_len)) + { + WSREP_ERROR("Failed to read '%s ' from: %s\n\tRead: '%s'", + magic, arg->cmd, tmp); + proc.wait(); + if (proc.error()) err = proc.error(); + } + else + { + err = 0; + } + } + else + { + 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 + mysql_mutex_lock (&arg->lock); + if (!err) + { + arg->ret_str = strdup (out + magic_len + 1); + if (!arg->ret_str) err = ENOMEM; + } + arg->err = -err; + mysql_cond_signal (&arg->cond); + mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. + + if (err) return NULL; /* lp:808417 - return immediately, don't signal + * initializer thread to ensure single thread of + * shutdown. */ + + 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()); + + proc.wait(); + err= EINVAL; + + if (!tmp) + { + WSREP_ERROR("Failed to read uuid:seqno from joiner script."); + if (proc.error()) err = proc.error(); + } + else + { + err= sst_scan_uuid_seqno (out, &ret_uuid, &ret_seqno); + } + + if (err) + { + ret_uuid= WSREP_UUID_UNDEFINED; + ret_seqno= -err; + } + + // Tell initializer thread that SST is complete + wsrep_sst_complete (&ret_uuid, ret_seqno, true); + } + + return NULL; +} + +static ssize_t sst_prepare_other (const char* method, + const char* addr_in, + const char** addr_out) +{ + ssize_t cmd_len= 1024; + char cmd_str[cmd_len]; + const char* sst_dir= mysql_real_data_home; + + int ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s 'joiner' '%s' '%s' '%s' '%s' '%d' 2>sst.err", + method, addr_in, (sst_auth_real) ? sst_auth_real : "", + sst_dir, wsrep_defaults_file, (int)getpid()); + + if (ret < 0 || ret >= cmd_len) + { + WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); + return (ret < 0 ? ret : -EMSGSIZE); + } + + pthread_t tmp; + sst_thread_arg arg(cmd_str); + mysql_mutex_lock (&arg.lock); + pthread_create (&tmp, NULL, sst_joiner_thread, &arg); + mysql_cond_wait (&arg.cond, &arg.lock); + + *addr_out= arg.ret_str; + + if (!arg.err) + ret = strlen(*addr_out); + else + { + assert (arg.err < 0); + ret = arg.err; + } + + pthread_detach (tmp); + + return ret; +} + +//extern ulong my_bind_addr; +extern uint mysqld_port; + +/*! Just tells donor where ti sent mysqldump */ +static ssize_t sst_prepare_mysqldump (const char* addr_in, + const char** addr_out) +{ + ssize_t ret = strlen (addr_in); + + if (!strrchr(addr_in, ':')) + { + ssize_t s = ret + 7; + char* tmp = (char*) malloc (s); + + if (tmp) + { + ret= snprintf (tmp, s, "%s:%u", addr_in, mysqld_port); + + if (ret > 0 && ret < s) + { + *addr_out= tmp; + return ret; + } + if (ret > 0) /* buffer too short */ ret = -EMSGSIZE; + free (tmp); + } + else { + ret= -ENOMEM; + } + + sql_print_error ("WSREP: Could not prepare state transfer request: " + "adding default port failed: %zd.", ret); + } + else { + *addr_out= addr_in; + } + + return ret; +} + +static bool SE_initialized = false; + +ssize_t wsrep_sst_prepare (void** msg) +{ + const ssize_t ip_max= 256; + char ip_buf[ip_max]; + const char* addr_in= NULL; + const char* addr_out= NULL; + + // Figure out SST address. Common for all SST methods + if (wsrep_sst_receive_address && + strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) + { + addr_in= wsrep_sst_receive_address; + } + else if (wsrep_node_address && strlen(wsrep_node_address)) + { + const char* const colon= strchr (wsrep_node_address, ':'); + if (colon) + { + ptrdiff_t const len= colon - wsrep_node_address; + strncpy (ip_buf, wsrep_node_address, len); + ip_buf[len]= '\0'; + addr_in= ip_buf; + } + else + { + addr_in= wsrep_node_address; + } + } + else + { + ssize_t ret= default_ip (ip_buf, ip_max); + + if (ret && ret < ip_max) + { + addr_in= ip_buf; + } + else + { + WSREP_ERROR("Could not prepare state transfer request: " + "failed to guess address to accept state transfer at. " + "wsrep_sst_receive_address must be set manually."); + unireg_abort(1); + } + } + + ssize_t addr_len= -ENOSYS; + if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP)) + { + addr_len= sst_prepare_mysqldump (addr_in, &addr_out); + if (addr_len < 0) unireg_abort(1); + } + else + { + /*! A heuristic workaround until we learn how to stop and start engines */ + if (SE_initialized) + { + // we already did SST at initializaiton, now engines are running + // sql_print_information() is here because the message is too long + // for WSREP_INFO. + sql_print_information ("WSREP: " + "You have configured '%s' state snapshot transfer method " + "which cannot be performed on a running server. " + "Wsrep provider won't be able to fall back to it " + "if other means of state transfer are unavailable. " + "In that case you will need to restart the server.", + wsrep_sst_method); + *msg = 0; + return 0; + } + + addr_len = sst_prepare_other (wsrep_sst_method, addr_in, &addr_out); + if (addr_len < 0) + { + WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", + wsrep_sst_method); + unireg_abort(1); + } + } + + size_t const method_len(strlen(wsrep_sst_method)); + size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); + + *msg = malloc (msg_len); + if (NULL != *msg) { + char* const method_ptr(reinterpret_cast(*msg)); + strcpy (method_ptr, wsrep_sst_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); + } + + if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); + + return msg_len; +} + +// helper method for donors +static int sst_run_shell (const char* cmd_str, int max_tries) +{ + int ret = 0; + + for (int tries=1; tries <= max_tries; tries++) + { + wsp::process proc (cmd_str, "r"); + + if (NULL != proc.pipe()) + { + proc.wait(); + } + + if ((ret = proc.error())) + { + WSREP_ERROR("Try %d/%d: '%s' failed: %d (%s)", + tries, max_tries, proc.cmd(), ret, strerror(ret)); + sleep (1); + } + else + { + WSREP_DEBUG("SST script successfully completed."); + break; + } + } + + return -ret; +} + +static int sst_mysqldump_check_addr (const char* user, const char* pswd, + const char* host, const char* port) +{ + return 0; +} + +static int sst_donate_mysqldump (const char* addr, + const wsrep_uuid_t* uuid, + const char* uuid_str, + wsrep_seqno_t seqno, + bool bypass) +{ + size_t host_len; + const char* port = strchr (addr, ':'); + + if (port) + { + port += 1; + host_len = port - addr; + } + else + { + port = ""; + host_len = strlen (addr) + 1; + } + + char host[host_len]; + + strncpy (host, addr, host_len - 1); + host[host_len - 1] = '\0'; + + const char* auth = sst_auth_real; + const char* pswd = (auth) ? strchr (auth, ':') : NULL; + size_t user_len; + + if (pswd) + { + pswd += 1; + user_len = pswd - auth; + } + else + { + pswd = ""; + user_len = (auth) ? strlen (auth) + 1 : 1; + } + + char user[user_len]; + + strncpy (user, (auth) ? auth : "", user_len - 1); + user[user_len - 1] = '\0'; + + int ret = sst_mysqldump_check_addr (user, pswd, host, port); + if (!ret) + { + size_t cmd_len= 1024; + char cmd_str[cmd_len]; + + snprintf (cmd_str, cmd_len, + "wsrep_sst_mysqldump '%s' '%s' '%s' '%s' '%u' '%s' '%lld' '%d'", + user, pswd, host, port, mysqld_port, uuid_str, (long long)seqno, + bypass); + + WSREP_DEBUG("Running: '%s'", cmd_str); + + ret= sst_run_shell (cmd_str, 3); + } + + wsrep->sst_sent (wsrep, uuid, ret ? ret : seqno); + + return ret; +} + +wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + +static int run_sql_command(THD *thd, const char *query) +{ + thd->set_query((char *)query, strlen(query)); + + Parser_state ps; + if (ps.init(thd, thd->query(), thd->query_length())) + { + WSREP_ERROR("SST query: %s failed", query); + return -1; + } + + mysql_parse(thd, thd->query(), thd->query_length(), &ps); + if (thd->is_error()) + { + int const err= thd->stmt_da->sql_errno(); + WSREP_WARN ("error executing '%s': %d (%s)%s", + query, err, thd->stmt_da->message(), + err == ER_UNKNOWN_SYSTEM_VARIABLE ? + ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); + thd->clear_error(); + return -1; + } + return 0; +} + +static int sst_flush_tables(THD* thd) +{ + WSREP_INFO("Flushing tables for SST..."); + + int err; + int not_used; + if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) + { + WSREP_ERROR("Failed to flush and lock tables"); + err = -1; + } + else + { + /* make sure logs are flushed after global read lock acquired */ + err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG, + (TABLE_LIST*) 0, ¬_used); + } + + if (err) + { + WSREP_ERROR("Failed to flush tables: %d (%s)", err, strerror(err)); + } + else + { + WSREP_INFO("Tables flushed."); + const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; + char real_name[full_len]; + sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); + char tmp_name[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 + { + fprintf(file, "%s:%lld\n", + wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno); + 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)); + } + } + } + + return err; +} + +static void sst_disallow_writes (THD* thd, bool yes) +{ + char query_str[64] = { 0, }; + ssize_t const query_max = sizeof(query_str) - 1; + snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", + yes ? 1 : 0); + + if (run_sql_command(thd, query_str)) + { + WSREP_ERROR("Failed to disallow InnoDB writes"); + } +} + +static void* sst_donor_thread (void* a) +{ + sst_thread_arg* arg= (sst_thread_arg*)a; + + WSREP_INFO("Running: '%s'", arg->cmd); + + int err= 1; + bool locked= false; + + const char* out= NULL; + const size_t out_len= 128; + char out_buf[out_len]; + + wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST + + wsp::thd thd; + wsp::process proc(arg->cmd, "r"); + + err= proc.error(); + +/* Inform server about SST script startup and release TO isolation */ + mysql_mutex_lock (&arg->lock); + arg->err = -err; + mysql_cond_signal (&arg->cond); + mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. + + if (proc.pipe() && !err) + { +wait_signal: + out= my_fgets (out_buf, out_len, proc.pipe()); + + if (out) + { + const char magic_flush[]= "flush tables"; + const char magic_cont[]= "continue"; + const char magic_done[]= "done"; + + if (!strcasecmp (out, magic_flush)) + { + err= sst_flush_tables (thd.ptr); + if (!err) + { + sst_disallow_writes (thd.ptr, true); + locked= true; + goto wait_signal; + } + } + else if (!strcasecmp (out, magic_cont)) + { + if (locked) + { + sst_disallow_writes (thd.ptr, false); + thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + locked= false; + } + err= 0; + goto wait_signal; + } + else if (!strncasecmp (out, magic_done, strlen(magic_done))) + { + err= sst_scan_uuid_seqno (out + strlen(magic_done) + 1, + &ret_uuid, &ret_seqno); + } + else + { + WSREP_WARN("Received unknown signal: '%s'", out); + } + } + else + { + WSREP_ERROR("Failed to read from: %s", proc.cmd()); + } + if (err && proc.error()) err= proc.error(); + } + else + { + WSREP_ERROR("Failed to execute: %s : %d (%s)", + proc.cmd(), err, strerror(err)); + } + + if (locked) // don't forget to unlock server before return + { + sst_disallow_writes (thd.ptr, false); + thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + } + + // signal to donor that SST is over + wsrep->sst_sent (wsrep, &ret_uuid, err ? -err : ret_seqno); + proc.wait(); + + return NULL; +} + +static int sst_donate_other (const char* method, + const char* addr, + const char* uuid, + wsrep_seqno_t seqno, + bool bypass) +{ + ssize_t cmd_len = 4096; + char cmd_str[cmd_len]; + + int ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s 'donor' '%s' '%s' '%s' '%s' '%s' '%lld' '%d'" + , + method, addr, sst_auth_real, mysql_real_data_home, + wsrep_defaults_file, uuid, (long long) seqno, bypass); + + if (ret < 0 || ret >= cmd_len) + { + WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); + return (ret < 0 ? ret : -EMSGSIZE); + } + + pthread_t tmp; + sst_thread_arg arg(cmd_str); + mysql_mutex_lock (&arg.lock); + pthread_create (&tmp, NULL, sst_donor_thread, &arg); + mysql_cond_wait (&arg.cond, &arg.lock); + + WSREP_INFO("sst_donor_thread signaled with %d", arg.err); + return arg.err; +} + +int wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, + const void* msg, size_t msg_len, + const wsrep_uuid_t* current_uuid, + wsrep_seqno_t current_seqno, + const char* state, size_t state_len, + bool bypass) +{ + /* This will be reset when sync callback is called. + * Should we set wsrep_ready to FALSE here too? */ +// wsrep_notify_status(WSREP_MEMBER_DONOR); + local_status.set(WSREP_MEMBER_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 (current_uuid, uuid_str, sizeof(uuid_str)); + + int ret; + if (!strcmp (WSREP_SST_MYSQLDUMP, method)) + { + ret = sst_donate_mysqldump (data, current_uuid, uuid_str, current_seqno, + bypass); + } + else + { + ret = sst_donate_other (method, data, uuid_str, current_seqno, bypass); + } + + return (ret > 0 ? 0 : ret); +} + +void wsrep_SE_init_grab() +{ + if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); +} + +void wsrep_SE_init_wait() +{ + mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); + 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; +} diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc new file mode 100644 index 00000000000..f39353eda44 --- /dev/null +++ b/sql/wsrep_utils.cc @@ -0,0 +1,447 @@ +/* Copyright 2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//! @file declares symbols private to wsrep integration layer + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // POSIX_SPAWN_USEVFORK flag +#endif + +#include // posix_spawn() +#include // pipe() +#include // errno +#include // strerror() +#include // waitpid() + +#include +#include "wsrep_priv.h" + +extern char** environ; // environment variables + +static wsp::string wsrep_PATH; + +void +wsrep_prepend_PATH (const char* path) +{ + int count = 0; + + while (environ[count]) + { + if (strncmp (environ[count], "PATH=", 5)) + { + count++; + continue; + } + + char* const old_path (environ[count]); + + if (strstr (old_path, path)) return; // path already there + + size_t const new_path_len(strlen(old_path) + strlen(":") + + strlen(path) + 1); + + char* const new_path (reinterpret_cast(malloc(new_path_len))); + + if (new_path) + { + snprintf (new_path, new_path_len, "PATH=%s:%s", path, + old_path + strlen("PATH=")); + + wsrep_PATH.set (new_path); + environ[count] = new_path; + } + else + { + WSREP_ERROR ("Failed to allocate 'PATH' environment variable " + "buffer of size %zu.", new_path_len); + } + + return; + } + + WSREP_ERROR ("Failed to find 'PATH' environment variable. " + "State snapshot transfer may not be working."); +} + +namespace wsp +{ + +#define PIPE_READ 0 +#define PIPE_WRITE 1 +#define STDIN_FD 0 +#define STDOUT_FD 1 + +#ifndef POSIX_SPAWN_USEVFORK +# define POSIX_SPAWN_USEVFORK 0 +#endif + +process::process (const char* cmd, const char* type) + : str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0) +{ + if (0 == str_) + { + WSREP_ERROR ("Can't allocate command line of size: %zu", strlen(cmd)); + err_ = ENOMEM; + return; + } + + if (0 == strlen(str_)) + { + WSREP_ERROR ("Can't start a process: null or empty command line."); + return; + } + + if (NULL == type || (strcmp (type, "w") && strcmp(type, "r"))) + { + WSREP_ERROR ("type argument should be either \"r\" or \"w\"."); + return; + } + + int pipe_fds[2] = { -1, }; + if (::pipe(pipe_fds)) + { + err_ = errno; + WSREP_ERROR ("pipe() failed: %d (%s)", err_, strerror(err_)); + return; + } + + // which end of pipe will be returned to parent + int const parent_end (strcmp(type,"w") ? PIPE_READ : PIPE_WRITE); + 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 }; + if (!(pargv[0] && pargv[1] && pargv[2])) + { + err_ = ENOMEM; + WSREP_ERROR ("Failed to allocate pargv[] array."); + goto cleanup_pipe; + } + + posix_spawnattr_t attr; + err_ = posix_spawnattr_init (&attr); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_init() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_pipe; + } + + err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_USEVFORK); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setflags() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + posix_spawn_file_actions_t fact; + err_ = posix_spawn_file_actions_init (&fact); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_init() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + // close child's stdout|stdin depending on what we returning + err_ = posix_spawn_file_actions_addclose (&fact, close_fd); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_addclose() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_fact; + } + + // substitute our pipe descriptor in place of the closed one + err_ = posix_spawn_file_actions_adddup2 (&fact, + pipe_fds[child_end], close_fd); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_addup2() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_fact; + } + + err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, environ); + 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 + goto cleanup_fact; + } + + io_ = fdopen (pipe_fds[parent_end], type); + + if (io_) + { + pipe_fds[parent_end] = -1; // skip close on cleanup + } + else + { + 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); + if (err) + { + WSREP_ERROR ("posix_spawn_file_actions_destroy() failed: %d (%s)\n", + err, strerror(err)); + } + +cleanup_attr: + err = posix_spawnattr_destroy (&attr); + if (err) + { + WSREP_ERROR ("posix_spawnattr_destroy() failed: %d (%s)", + err, strerror(err)); + } + +cleanup_pipe: + if (pipe_fds[0] >= 0) close (pipe_fds[0]); + if (pipe_fds[1] >= 0) close (pipe_fds[1]); + + free (pargv[0]); + free (pargv[1]); + free (pargv[2]); +} + +process::~process () +{ + if (io_) + { + assert (pid_); + assert (str_); + + WSREP_WARN("Closing pipe to child process: %s, PID(%ld) " + "which might still be running.", str_, (long)pid_); + + if (fclose (io_) == -1) + { + err_ = errno; + WSREP_ERROR("fclose() failed: %d (%s)", err_, strerror(err_)); + } + } + + if (str_) free (const_cast(str_)); +} + +int +process::wait () +{ + if (pid_) + { + int status; + if (-1 == waitpid(pid_, &status, 0)) + { + 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); + } + else { // command didn't complete with exit() + WSREP_ERROR("Process was aborted."); + 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 */ + } + WSREP_ERROR("Process completed with error: %s: %d (%s)", + str_, err_, strerror(err_)); + } + + pid_ = 0; + if (io_) fclose (io_); + io_ = NULL; + } + } + else { + assert (NULL == io_); + WSREP_ERROR("Command did not run: %s", str_); + } + + return err_; +} + +thd::thd () : init(), ptr(new THD) +{ + if (ptr) + { + ptr->thread_stack= (char*) &ptr; + ptr->store_globals(); + ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog + ptr->security_ctx->master_access= ~(ulong)0; + lex_start(ptr); + } +} + +thd::~thd () +{ + if (ptr) + { + delete ptr; + my_pthread_setspecific_ptr (THR_THD, 0); + } +} + +} // namespace wsp + +extern ulong my_bind_addr; +extern uint mysqld_port; + +size_t default_ip (char* buf, size_t buf_len) +{ + size_t ip_len = 0; + + if (htonl(INADDR_NONE) == my_bind_addr) { + WSREP_ERROR("Networking not configured, cannot receive state transfer."); + return 0; + } + + if (htonl(INADDR_ANY) == my_bind_addr) { + // binds to all interfaces, try to find the address of the first one +#if (TARGET_OS_LINUX == 1) + const char cmd[] = "/sbin/ifconfig | " + "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +#elif defined(__sun__) + const char cmd[] = "/sbin/ifconfig -a | " + "grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; +#else + char *cmd; +#error "OS not supported" +#endif + wsp::process proc (cmd, "r"); + + if (NULL != proc.pipe()) { + char* ret; + + ret = fgets (buf, buf_len, proc.pipe()); + + if (proc.wait()) return 0; + + if (NULL == ret) { + WSREP_ERROR("Failed to read output of: '%s'", cmd); + return 0; + } + } + else { + WSREP_ERROR("Failed to execute: '%s'", cmd); + return 0; + } + + // clear possible \n at the end of ip string left by fgets() + ip_len = strlen (buf); + if (ip_len > 0 && '\n' == buf[ip_len - 1]) { + ip_len--; + buf[ip_len] = '\0'; + } + + if (INADDR_NONE == inet_addr(buf)) { + if (strlen(buf) != 0) { + WSREP_WARN("Shell command returned invalid address: '%s'", buf); + } + return 0; + } + } + else { + uint8_t* b = (uint8_t*)&my_bind_addr; + ip_len = snprintf (buf, buf_len, + "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); + } + + return ip_len; +} + +size_t default_address(char* buf, size_t buf_len) +{ + size_t addr_len = default_ip (buf, buf_len); + + if (addr_len && addr_len < buf_len) { + addr_len += snprintf (buf + addr_len, buf_len - addr_len, + ":%u", mysqld_port); + } + + return addr_len; +} + +/* + * WSREPXid + */ + +#define WSREP_XID_PREFIX "WSREPXid" +#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN +#define WSREP_XID_UUID_OFFSET 8 +#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) +{ + 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); + memcpy(xid->data + WSREP_XID_UUID_OFFSET, uuid, sizeof(wsrep_uuid_t)); + memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t)); +} + +const wsrep_uuid_t* wsrep_xid_uuid(const XID* xid) +{ + if (wsrep_is_wsrep_xid(xid)) + return reinterpret_cast(xid->data + + WSREP_XID_UUID_OFFSET); + else + return &WSREP_UUID_UNDEFINED; +} + +wsrep_seqno_t wsrep_xid_seqno(const XID* xid) +{ + + if (wsrep_is_wsrep_xid(xid)) + { + wsrep_seqno_t seqno; + memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); + return seqno; + } + else + { + return WSREP_SEQNO_UNDEFINED; + } +} + +extern "C" +int wsrep_is_wsrep_xid(const void* xid_ptr) +{ + const XID* xid= reinterpret_cast(xid_ptr); + return (xid->formatID == 1 && + xid->gtrid_length == WSREP_XID_GTRID_LEN && + xid->bqual_length == 0 && + !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)); +} diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc new file mode 100644 index 00000000000..66f0f05c006 --- /dev/null +++ b/sql/wsrep_var.cc @@ -0,0 +1,505 @@ +/* Copyright 2008 Codership Oy + + 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 +#include +#include +#include +#include +#include "wsrep_priv.h" +#include +#include +#include + +#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" + +// trx history position to start with +const char* wsrep_start_position = WSREP_START_POSITION_ZERO; +const char* wsrep_provider = WSREP_NONE; +const char* wsrep_provider_options = (const char*)my_memdup("", 1, MYF(MY_WME)); +const char* wsrep_cluster_address = NULL; +const char* wsrep_cluster_name = "my_wsrep_cluster"; +const char* wsrep_node_name = glob_hostname; +static char node_address[256] = { 0, }; +const char* wsrep_node_address = node_address; +ulong wsrep_OSU_method_options; + +int wsrep_init_vars() +{ + global_system_variables.binlog_format=BINLOG_FORMAT_ROW; + return 0; +} + +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; + } + else { + } + +#ifdef REMOVED + if (thd->variables.wsrep_on) + thd->variables.option_bits |= (OPTION_BIN_LOG); + else + thd->variables.option_bits &= ~(OPTION_BIN_LOG); +#endif + return false; +} + +void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) +{ + if (var_type == OPT_GLOBAL) { + thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; + } + else { + } +} + +static int wsrep_start_position_verify (const char* start_str) +{ + size_t start_len; + wsrep_uuid_t uuid; + ssize_t uuid_len; + + start_len = strlen (start_str); + if (start_len < 34) + return 1; + + uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid); + if (uuid_len < 0 || (start_len - uuid_len) < 2) + return 1; + + if (start_str[uuid_len] != ':') // separator should follow UUID + return 1; + + char* endptr; + wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings + (strtoll(&start_str[uuid_len + 1], &endptr, 10)); + + if (*endptr == '\0') return 0; // remaining string was seqno + + return 1; +} + +bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* start_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + start_str = res->c_ptr(); + + if (!start_str) goto err; + + if (!wsrep_start_position_verify(start_str)) return 0; + +err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + start_str ? start_str : "NULL"); + return 1; +} + +void wsrep_set_local_position (const char* value) +{ + size_t value_len = strlen (value); + size_t uuid_len = wsrep_uuid_scan (value, value_len, &local_uuid); + + local_seqno = strtoll (value + uuid_len + 1, NULL, 10); + + XID xid; + wsrep_xid_init(&xid, &local_uuid, local_seqno); + wsrep_set_SE_checkpoint(&xid); + WSREP_INFO ("wsrep_start_position var submitted: '%s'", wsrep_start_position); +} + +bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) +{ + // since this value passed wsrep_start_position_check, don't check anything + // here + wsrep_set_local_position (wsrep_start_position); + + if (wsrep) { + wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + } + + return 0; +} + +void wsrep_start_position_init (const char* val) +{ + if (NULL == val || wsrep_start_position_verify (val)) + { + WSREP_ERROR("Bad initial value for wsrep_start_position: %s", + (val ? val : "")); + return; + } + + wsrep_start_position = my_strdup(val, MYF(0)); + + wsrep_set_local_position (val); +} + +static bool refresh_provider_options() +{ + char* opts= wsrep->options_get(wsrep); + if (opts) + { + if (wsrep_provider_options) my_free((void *)wsrep_provider_options); + wsrep_provider_options = (char*)my_memdup(opts, strlen(opts) + 1, + MYF(MY_WME)); + } + else + { + WSREP_ERROR("Failed to get provider options"); + return true; + } + return false; +} + +static int wsrep_provider_verify (const char* provider_str) +{ + MY_STAT f_stat; + char path[FN_REFLEN]; + + if (!provider_str || strlen(provider_str)== 0) + return 1; + + if (!strcmp(provider_str, WSREP_NONE)) + return 0; + + if (!unpack_filename(path, provider_str)) + return 1; + + /* check that provider file exists */ + bzero(&f_stat, sizeof(MY_STAT)); + if (!my_stat(path, &f_stat, MYF(0))) + { + return 1; + } + return 0; +} + +bool wsrep_provider_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* provider_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + provider_str = res->c_ptr(); + + if (!provider_str) goto err; + + if (!wsrep_provider_verify(provider_str)) return 0; + +err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + provider_str ? provider_str : "NULL"); + return 1; +} + +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_stop_replication(thd); + wsrep_deinit(); + + char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider + //when fails + if (wsrep_init()) + { + my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp); + 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); + + thd->variables.wsrep_on= wsrep_on_saved; + + refresh_provider_options(); + + return rcode; +} + +void wsrep_provider_init (const char* value) +{ + if (NULL == value || wsrep_provider_verify (value)) + { + WSREP_ERROR("Bad initial value for wsrep_provider: %s", + (value ? value : "")); + return; + } + wsrep_provider = my_strdup(value, MYF(0)); +} + +bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) +{ + return 0; +} + +bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) +{ + wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options); + if (ret != WSREP_OK) + { + WSREP_ERROR("Set options returned %d", ret); + return true; + } + return refresh_provider_options(); +} + +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; +} + +static int wsrep_cluster_address_verify (const char* cluster_address_str) +{ + /* There is no predefined address format, it depends on provider. */ + return 0; +} + +bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* cluster_address_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + cluster_address_str = res->c_ptr(); + + if (!wsrep_cluster_address_verify(cluster_address_str)) return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + cluster_address_str ? cluster_address_str : "NULL"); + return 1 ; +} + +bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) +{ + bool wsrep_on_saved= thd->variables.wsrep_on; + thd->variables.wsrep_on= false; + + wsrep_stop_replication(thd); + + if (wsrep_start_replication()) + { + wsrep_create_rollbacker(); + wsrep_create_appliers(wsrep_slave_threads); + } + + thd->variables.wsrep_on= wsrep_on_saved; + + return false; +} + +void wsrep_cluster_address_init (const char* value) +{ + if (wsrep_cluster_address && wsrep_cluster_address != value) + my_free ((void*)wsrep_cluster_address); + + wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; +} + +bool wsrep_cluster_name_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* cluster_name_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + cluster_name_str = res->c_ptr(); + + if (!cluster_name_str || strlen(cluster_name_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + cluster_name_str ? cluster_name_str : "NULL"); + return 1; +} + +bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +bool wsrep_node_name_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* node_name_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + node_name_str = res->c_ptr(); + + if (!node_name_str || strlen(node_name_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + node_name_str ? node_name_str : "NULL"); + return 1; +} + +bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +// TODO: do something more elaborate, like checking connectivity +bool wsrep_node_address_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* node_address_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + node_address_str = res->c_ptr(); + + if (!node_address_str || strlen(node_address_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + node_address_str ? node_address_str : "NULL"); + return 1; +} + +bool wsrep_node_address_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +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; +} + +/* + * Status variables stuff below + */ +static inline void +wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep) +{ + mysql->name = wsrep->name; + switch (wsrep->type) { + case WSREP_VAR_INT64: + mysql->value = (char*) &wsrep->value._int64; + mysql->type = SHOW_LONGLONG; + break; + case WSREP_VAR_STRING: + mysql->value = (char*) &wsrep->value._string; + mysql->type = SHOW_CHAR_PTR; + break; + case WSREP_VAR_DOUBLE: + mysql->value = (char*) &wsrep->value._double; + mysql->type = SHOW_DOUBLE; + break; + } +} + +static wsrep_stats_var* wsrep_status_vars = NULL; + +#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[100 + 1]; +static const int mysql_status_len = 100; +#endif + +static void export_wsrep_status_to_mysql() +{ + int wsrep_status_len, i; + + if (wsrep_status_vars) wsrep->stats_free (wsrep, wsrep_status_vars); + + wsrep_status_vars = wsrep->stats_get (wsrep); + + if (!wsrep_status_vars) { + return; + } + + for (wsrep_status_len = 0; + wsrep_status_vars[wsrep_status_len].name != NULL; + wsrep_status_len++); + +#if DYNAMIC + if (wsrep_status_len != mysql_status_len) { + void* tmp = realloc (mysql_status_vars, + (wsrep_status_len + 1) * sizeof(SHOW_VAR)); + if (!tmp) { + + sql_print_error ("Out of memory for wsrep status variables." + "Number of variables: %d", wsrep_status_len); + return; + } + + mysql_status_len = wsrep_status_len; + mysql_status_vars = (SHOW_VAR*)tmp; + } + /* @TODO: fix this: */ +#else + if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len; +#endif + + for (i = 0; i < wsrep_status_len; i++) + wsrep_assign_to_mysql (mysql_status_vars + i, wsrep_status_vars + i); + + mysql_status_vars[wsrep_status_len].name = NullS; + mysql_status_vars[wsrep_status_len].value = NullS; + mysql_status_vars[wsrep_status_len].type = SHOW_LONG; +} + +int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) +{ + export_wsrep_status_to_mysql(); + var->type= SHOW_ARRAY; + var->value= (char *) &mysql_status_vars; + return 0; +} diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh new file mode 100644 index 00000000000..e8483910c0b --- /dev/null +++ b/support-files/wsrep.cnf.sh @@ -0,0 +1,125 @@ +# This file contains wsrep-related mysqld options. It should be included +# in the main MySQL configuration file. +# +# Options that need to be customized: +# - wsrep_provider +# - wsrep_cluster_address +# - wsrep_sst_auth +# The rest of defaults should work out of the box. + +## +## mysqld options _MANDATORY_ for correct opration of the cluster +## +[mysqld] + +# (This must be substituted by wsrep_format) +binlog_format=ROW + +# Currently only InnoDB storage engine is supported +default-storage-engine=innodb + +# to avoid issues with 'bulk mode inserts' using autoinc +innodb_autoinc_lock_mode=2 + +# This is a must for paralell applying +innodb_locks_unsafe_for_binlog=1 + +# Query Cache is not supported with wsrep +query_cache_size=0 +query_cache_type=0 + +# Override bind-address +# In some systems bind-address defaults to 127.0.0.1, and with mysqldump SST +# it will have (most likely) disastrous consequences on donor node +bind-address=0.0.0.0 + +## +## WSREP options +## + +# Full path to wsrep provider library or 'none' +wsrep_provider=none + +# Provider specific configuration options +#wsrep_provider_options= + +# Logical cluster name. Should be the same for all nodes. +wsrep_cluster_name="my_wsrep_cluster" + +# Group communication system handle +#wsrep_cluster_address="dummy://" + +# Human-readable node name (non-unique). Hostname by default. +#wsrep_node_name= + +# Base replication [:port] of the node. +# The values supplied will be used as defaults for state transfer receiving, +# listening ports and so on. Default: address of the first network interface. +#wsrep_node_address= + +# Address for incoming client connections. Autodetect by default. +#wsrep_node_incoming_address= + +# How many threads will process writesets from other nodes +wsrep_slave_threads=1 + +# DBUG options for wsrep provider +#wsrep_dbug_option + +# Generate fake primary keys for non-PK tables (required for multi-master +# and parallel applying operation) +wsrep_certify_nonPK=1 + +# Maximum number of rows in write set +wsrep_max_ws_rows=131072 + +# Maximum size of write set +wsrep_max_ws_size=1073741824 + +# to enable debug level logging, set this to 1 +wsrep_debug=0 + +# convert locking sessions into transactions +wsrep_convert_LOCK_to_trx=0 + +# how many times to retry deadlocked autocommits +wsrep_retry_autocommit=1 + +# change auto_increment_increment and auto_increment_offset automatically +wsrep_auto_increment_control=1 + +# retry autoinc insert, which failed for duplicate key error +wsrep_drupal_282555_workaround=0 + +# enable "strictly synchronous" semantics for read operations +wsrep_causal_reads=0 + +# Command to call when node status or cluster membership changes. +# Will be passed all or some of the following options: +# --status - new status of this node +# --uuid - UUID of the cluster +# --primary - whether the component is primary or not ("yes"/"no") +# --members - comma-separated list of members +# --index - index of this node in the list +wsrep_notify_cmd= + +## +## WSREP State Transfer options +## + +# State Snapshot Transfer method +wsrep_sst_method=mysqldump + +# Address on THIS node to receive SST at. DON'T SET IT TO DONOR ADDRESS!!! +# (SST method dependent. Defaults to the first IP of the first interface) +#wsrep_sst_receive_address= + +# SST authentication string. This will be used to send SST to joining nodes. +# Depends on SST method. For mysqldump method it is root: +wsrep_sst_auth=root: + +# Desired SST donor name. +#wsrep_sst_donor= + +# Protocol version to use +# wsrep_protocol_version= diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh new file mode 100644 index 00000000000..bdbe3d12a39 --- /dev/null +++ b/support-files/wsrep_notify.sh @@ -0,0 +1,102 @@ +#!/bin/sh -eu + +# This is a simple example of wsrep notification script (wsrep_notify_cmd). +# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' +# and fill them on every membership or node status change. +# +# Edit parameters below to specify the address and login to server. + +USER=root +PSWD=rootpass +HOST=127.0.0.1 +PORT=3306 + +SCHEMA="wsrep" +MEMB_TABLE="$SCHEMA.membership" +STATUS_TABLE="$SCHEMA.status" + +BEGIN=" +SET wsrep_on=0; +DROP SCHEMA IF EXISTS $SCHEMA; CREATE SCHEMA $SCHEMA; +CREATE TABLE $MEMB_TABLE ( + idx INT UNIQUE PRIMARY KEY, + uuid CHAR(40) UNIQUE, /* node UUID */ + name VARCHAR(32), /* node name */ + addr VARCHAR(256) /* node address */ +) ENGINE=MEMORY; +CREATE TABLE $STATUS_TABLE ( + size INT, /* component size */ + idx INT, /* this node index */ + status CHAR(16), /* this node status */ + uuid CHAR(40), /* cluster UUID */ + prim BOOLEAN /* if component is primary */ +) ENGINE=MEMORY; +BEGIN; +DELETE FROM $MEMB_TABLE; +DELETE FROM $STATUS_TABLE; +" +END="COMMIT;" + +configuration_change() +{ + echo "$BEGIN;" + + local idx=0 + + for NODE in $(echo $MEMBERS | sed s/,/\ /g) + do + echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " + # Don't forget to properly quote string values + echo "'$NODE'" | sed s/\\//\',\'/g + echo ");" + idx=$(( $idx + 1 )) + done + + echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" + + echo "$END" +} + +status_update() +{ + echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;" +} + +COM=status_update # not a configuration change by default + +while [ $# -gt 0 ] +do + case $1 in + --status) + STATUS=$2 + shift + ;; + --uuid) + CLUSTER_UUID=$2 + shift + ;; + --primary) + [ "$2" = "yes" ] && PRIMARY="1" || PRIMARY="0" + COM=configuration_change + shift + ;; + --index) + INDEX=$2 + shift + ;; + --members) + MEMBERS=$2 + shift + ;; + esac + shift +done + +# Undefined means node is shutting down +if [ "$STATUS" != "Undefined" ] +then + $COM | mysql -B -u$USER -p$PSWD -h$HOST -P$PORT +fi + +exit 0 +# diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt new file mode 100644 index 00000000000..11d0e34d1b0 --- /dev/null +++ b/wsrep/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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 + +INCLUDE_DIRECTORIES( "." ) + +SET(WSREP_SOURCES wsrep_uuid.c wsrep_loader.c wsrep_dummy.c) + +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/Makefile.am b/wsrep/Makefile.am new file mode 100644 index 00000000000..40e4b501e86 --- /dev/null +++ b/wsrep/Makefile.am @@ -0,0 +1,2 @@ +noinst_LIBRARIES = libwsrep.a +libwsrep_a_SOURCES = wsrep_api.h wsrep_loader.c wsrep_dummy.c wsrep_uuid.c diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h new file mode 100644 index 00000000000..2cd10afc7ff --- /dev/null +++ b/wsrep/wsrep_api.h @@ -0,0 +1,875 @@ +/* Copyright (C) 2009-2011 Codership Oy + + 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_H +#define WSREP_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * wsrep replication API + */ + +#define WSREP_INTERFACE_VERSION "23" + +/*! + * Certain provider capabilities application may need to know + */ +#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_WRITE_SET_INCREMENTS ( 1ULL << 8 ) +#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) +#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) +#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) + +/*! + * Write set replication flags + */ +#define WSREP_FLAG_PA_SAFE ( 1ULL << 0 ) + +/* Empty backend spec */ +#define WSREP_NONE "none" + +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. + +/*! undefined seqno */ +#define WSREP_SEQNO_UNDEFINED (-1) + +/*! wsrep 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_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; + +/*! + * @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 library 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 *); + +/*! + * UUID type - for all unique IDs + */ +typedef struct wsrep_uuid { + uint8_t uuid[16]; +} wsrep_uuid_t; + +/*! Undefined UUID */ +static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; + +/*! + * Scan UUID from string + * @return length of UUID string representation or negative error code + */ +extern ssize_t +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 ssize_t +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 + +/*! + * 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_uuid_t uuid; //!< global state UUID + wsrep_seqno_t seqno; //!< global state seqno + wsrep_seqno_t view; //!< global view number + wsrep_view_status_t status; //!< view status + bool 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 in 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 void (*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, + ssize_t* sst_req_len); + +/*! + * @brief apply callback + * + * This handler is called from wsrep library to apply replicated write set + * 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 write set + * @param size data buffer size + * @param seqno global seqno part of the write set to be applied + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_NOT_IMPLEMENTED appl. does not support the write set format + * @retval WSREP_ERROR failed to apply the write set + */ +typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, + const void* data, + size_t size, + wsrep_seqno_t seqno); + +/*! + * @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 seqno global seqno part of the write set to be committed + * @param commit true - commit writeset, false - rollback writeset + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_ERROR call failed + */ +typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, + wsrep_seqno_t seqno, + bool commit); + +/*! + * @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 uuid current state uuid on this node + * @param seqno current state seqno 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 + * @return 0 for success or negative error code + */ +typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, + void* recv_ctx, + const void* msg, + size_t msg_len, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno, + const char* state, + size_t state_len, + bool 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, used as arguments for wsrep_init() + */ +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_uuid_t* state_uuid; //!< Application state sequence UUID + wsrep_seqno_t state_seqno; //!< Applicaiton state sequence number + const char* state; //!< Initial state for wsrep implementation + 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 + + /* 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 _int64; + double _double; + const char* _string; + } value; //!< variable value +}; + + +/*! Key part structure */ +typedef struct wsrep_key_part_ +{ + const void* buf; /*!< Buffer containing key part data */ + size_t buf_len; /*!< Length of buffer */ +} wsrep_key_part_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_key_part_t* key_parts; /*!< Array of key parts */ + size_t key_parts_len; /*!< Length of key parts array */ +} wsrep_key_t; + +/*! Transaction handle struct passed for wsrep transaction handling calls */ +typedef struct wsrep_trx_handle_ +{ + wsrep_trx_id_t trx_id; //!< transaction ID + void* opaque; //!< opaque provider transaction context data +} wsrep_trx_handle_t; + +/*! + * @brief Helper method to reset trx handle state when trx id changes + * + * Instead of passing wsrep_trx_handle_t directly for wsrep calls, + * wrapping handle with this call offloads bookkeeping from + * application. + */ +static inline wsrep_trx_handle_t* wsrep_trx_handle_for_id( + wsrep_trx_handle_t* trx_handle, + wsrep_trx_id_t trx_id) +{ + if (trx_handle->trx_id != trx_id) + { + trx_handle->trx_id = trx_id; + trx_handle->opaque = NULL; + } + return trx_handle; +} + + +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 this wsrep 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 this wsrep handle + */ + uint64_t (*capabilities) (wsrep_t* wsrep); + + /*! + * @brief Passes provider-specific configuration string to provider. + * + * @param wsrep this wsrep 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 this wsrep 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 this wsrep 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. + */ + wsrep_status_t (*connect) (wsrep_t* wsrep, + const char* cluster_name, + const char* cluster_url, + const char* state_donor); + + /*! + * @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 this wsrep 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 this wsrep handle + * @param trx_handle transaction which is committing + * @param conn_id connection ID + * @param app_data application specific applying data + * @param data_len the size of the applying data + * @param flags fine tuning the replication WSREP_FLAG_* + * @param seqno seqno part of the global transaction ID + * + * @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_trx_handle_t* trx_handle, + const void* app_data, + size_t data_len, + uint64_t flags, + wsrep_seqno_t* seqno); + + /*! + * @brief Releases resources after transaction commit. + * + * Ends commit critical section. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @retval WSREP_OK post_commit succeeded + */ + wsrep_status_t (*post_commit) (wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle); + + /*! + * @brief Releases resources after transaction rollback. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @retval WSREP_OK post_rollback succeeded + */ + wsrep_status_t (*post_rollback)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle); + + /*! + * @brief Replay trx as a slave write set + * + * 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 write sets and certification + * test based on write set content can be different to DBMS lock conflicts. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @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_trx_handle_t* trx_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 this wsrep 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 query in transaction's write set + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param query SQL statement string + * @param timeval time to use for time functions + * @param randseed seed for rand + */ + wsrep_status_t (*append_query)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const char* query, + time_t timeval, + uint32_t randseed); + + /*! + * @brief Appends a row reference in transaction's write set + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param key array of keys + * @param key_len length of the array of keys + * @param shared boolean denoting if key corresponds to shared resource + */ + wsrep_status_t (*append_key)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const wsrep_key_t* key, + size_t key_len, + bool shared); + /*! + * @brief Appends data in transaction's write set + * + * This method can be called any time before commit and it + * appends data block into transaction's write set. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param data data buffer + * @param data_len data buffer length + */ + wsrep_status_t (*append_data)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const void* data, + size_t data_len); + + + /*! + * @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 + * seqno 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 this wsrep handle + * @param seqno location to store global transaction ID + */ + wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_seqno_t* seqno); + + /*! + * @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 this wsrep 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 query and returns success code, which + * caller must check. Total order isolation continues + * until to_execute_end() is called. + * + * @param wsrep this wsrep handle + * @param conn_id connection ID + * @param key array of keys + * @param key_len lenght of the array of keys + * @param query query to be executed + * @param query_len length of the query string + * @param seqno seqno part of the action 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_start)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_key_t* key, + size_t key_len, + const void* query, + size_t query_len, + wsrep_seqno_t* seqno); + + /*! + * @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 this wsrep 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 Signals to wsrep provider that state snapshot has been sent to + * joiner. + * + * @param wsrep this wsrep handle + * @param uuid sequence UUID (group UUID) + * @param seqno sequence number or negative error code of the operation + */ + wsrep_status_t (*sst_sent)(wsrep_t* wsrep, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno); + + /*! + * @brief Signals to wsrep provider that new state snapshot has been received. + * May deadlock if called from sst_prepare_cb. + * + * @param wsrep this wsrep handle + * @param uuid sequence UUID (group UUID) + * @param seqno sequence number or negative error code of the operation + * @param state initial state provided by SST donor + * @param state_len length of state buffer + */ + wsrep_status_t (*sst_received)(wsrep_t* wsrep, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno, + const char* state, + size_t state_len); + + + /*! + * @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 this wsrep 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 this wsrep 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 this wsrep handle. + */ + void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); + + /*! + * @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 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, int64_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, int64_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 + */ + bool (*is_locked) (wsrep_t* wsrep, const char* name, int64_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 this wsrep handle + */ + void (*free)(wsrep_t* wsrep); + + void *dlh; //!< reserved for future use + void *ctx; //!< reserved for implemetation private context +}; + +typedef int (*wsrep_loader_fun)(wsrep_t*); + +/*! + * + * @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 new file mode 100644 index 00000000000..6d01ce14b4e --- /dev/null +++ b/wsrep/wsrep_dummy.c @@ -0,0 +1,368 @@ +/* Copyright (C) 2009-2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Dummy wsrep API implementation. */ + +#include + +#include "wsrep_api.h" + +/*! Dummy backend context. */ +typedef struct wsrep_dummy +{ + wsrep_log_cb_t log_fn; +} 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); + 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); + 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 __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static char* dummy_options_get (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return NULL; +} + +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_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_trx_handle_t* trx_handle __attribute__((unused)), + const void* query __attribute__((unused)), + const size_t query_len __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_seqno_t* seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_commit( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_rollback( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_replay_trx( + wsrep_t* w, + wsrep_trx_handle_t* trx_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_query( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const char* query __attribute__((unused)), + const time_t timeval __attribute__((unused)), + const uint32_t randseed __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_row_key( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const size_t key_len __attribute__((unused)), + const bool shared __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_data( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const void* data __attribute__((unused)), + size_t data_len __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_causal_read( + wsrep_t* w, + wsrep_seqno_t* seqno __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_len __attribute__((unused)), + const void* query __attribute__((unused)), + const size_t query_len __attribute__((unused)), + wsrep_seqno_t* seqno __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_sst_sent( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + wsrep_seqno_t seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_sst_received( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + const wsrep_seqno_t seqno __attribute__((unused)), + const char* state __attribute__((unused)), + const size_t state_len __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 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)), + int64_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)), + int64_t o __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static bool dummy_is_locked (wsrep_t* w, + const char* s __attribute__((unused)), + int64_t* o __attribute__((unused)), + wsrep_uuid_t* t __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return false; +} + +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_query, + &dummy_append_row_key, + &dummy_append_data, + &dummy_causal_read, + &dummy_free_connection, + &dummy_to_execute_start, + &dummy_to_execute_end, + &dummy_sst_sent, + &dummy_sst_received, + &dummy_snapshot, + &dummy_stats_get, + &dummy_stats_free, + &dummy_pause, + &dummy_resume, + &dummy_desync, + &dummy_resync, + &dummy_lock, + &dummy_unlock, + &dummy_is_locked, + WSREP_NONE, + WSREP_INTERFACE_VERSION, + "Codership Oy ", + &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; + + return 0; +} + diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c new file mode 100644 index 00000000000..b4460658f80 --- /dev/null +++ b/wsrep/wsrep_loader.c @@ -0,0 +1,199 @@ +/* Copyright (C) 2009-2011 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file wsrep implementation loader */ + +#include +#include +#include +#include + +#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 verify(const wsrep_t *wh, const char *iface_ver) +{ + const size_t msg_len = 128; + char msg[msg_len]; + +#define VERIFY(_p) if (!(_p)) { \ + snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ + logger (WSREP_LOG_ERROR, msg); \ + return EINVAL; \ + } + + VERIFY(wh); + VERIFY(wh->version); + + if (strcmp(wh->version, iface_ver)) { + snprintf (msg, msg_len, + "provider interface version mismatch: need '%s', found '%s'", + iface_ver, wh->version); + logger (WSREP_LOG_ERROR, msg); + 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_query); + VERIFY(wh->append_key); + VERIFY(wh->free_connection); + VERIFY(wh->to_execute_start); + VERIFY(wh->to_execute_end); + VERIFY(wh->sst_sent); + VERIFY(wh->sst_received); + VERIFY(wh->stats_get); + VERIFY(wh->stats_free); + 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; +} + + +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; +} + +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; + const size_t msg_len = 1024; + char msg[msg_len + 1]; + msg[msg_len] = 0; + + if (NULL != log_cb) + logger = log_cb; + + if (!(spec && hptr)) + return EINVAL; + + snprintf (msg, msg_len, + "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, msg_len, "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 ((ret = (*dlfun)(*hptr)) != 0) { + snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", + strerror(ret)); + logger (WSREP_LOG_ERROR, msg); + goto out; + } + + if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { + snprintf (msg, msg_len, + "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, msg_len, + "wsrep_load(): %s %s by %s loaded succesfully.", + (*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 new file mode 100644 index 00000000000..c99240cc071 --- /dev/null +++ b/wsrep/wsrep_uuid.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2009 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Helper functions to deal with history UUID string representations */ + +#include +#include +#include + +#include "wsrep_api.h" + +/*! + * Read UUID from string + * @return length of UUID string representation or -EINVAL in case of error + */ +ssize_t +wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) +{ + size_t uuid_len = 0; + size_t uuid_offt = 0; + + while (uuid_len + 1 < str_len) { + if ((4 == uuid_offt || 6 == uuid_offt || 8 == uuid_offt || + 10 == uuid_offt) && 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 + sscanf (str + uuid_len, "%2hhx", uuid->uuid + uuid_offt); + uuid_len += 2; + uuid_offt += 1; + if (sizeof (uuid->uuid) == 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 + */ +ssize_t +wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) +{ + if (str_len > 36) { + const unsigned char* u = uuid->uuid; + 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; + } +} + From 609388fcfd912c9c2cb03a92251469a25a781893 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 26 Apr 2012 20:18:30 +0300 Subject: [PATCH 003/294] Merged changes from lp:codership-mysql up to rev 3743 -r3725..3737 -r3738..3740 -r3741..3743 --- sql/log_event.cc | 29 ++-- sql/sql_alter.cc | 7 +- sql/sql_base.cc | 19 +++ sql/sql_connect.cc | 6 +- sql/sql_parse.cc | 203 ++++++++++++-------------- sql/sql_truncate.cc | 2 +- sql/sys_vars.cc | 3 + sql/transaction.cc | 2 +- sql/wsrep_hton.cc | 20 ++- sql/wsrep_mysqld.cc | 166 +++++++++++++++++++-- sql/wsrep_mysqld.h | 22 +-- sql/wsrep_utils.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 5 - storage/innobase/rem/rem0rec.c | 26 ++-- storage/xtradb/handler/ha_innodb.cc | 5 - storage/xtradb/rem/rem0rec.c | 26 ++-- 16 files changed, 351 insertions(+), 192 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index e02cfc6d20c..1536d9e899b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8130,19 +8130,20 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; /* A small test to verify that objects have consistent types */ DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); - if (open_and_lock_tables(thd, rli->tables_to_lock, FALSE, 0)) { -#ifdef WITH_WSREP - uint actual_error= ER_SERVER_SHUTDOWN; - if (WSREP(thd) && !thd->is_fatal_error) - { - sql_print_information("WSREP, BF applier interrupted in log_event.cc"); - } - else - actual_error= thd->stmt_da->sql_errno(); -#else uint actual_error= thd->stmt_da->sql_errno(); +#ifdef WITH_WSREP + if (WSREP(thd)) + { + WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d " + "wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)", + thd->stmt_da->sql_errno(), + thd->is_fatal_error, + thd->wsrep_exec_mode, + thd->wsrep_conflict_state, + (long long)thd->wsrep_trx_seqno); + } #endif if (thd->is_slave_error || thd->is_fatal_error) { @@ -10878,6 +10879,8 @@ Format_description_log_event *wsrep_format_desc; // TODO: free them at the end 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. */ +#define WSREP_MAX_ALLOWED_PACKET 1024*1024*1024 // current protocol max + Log_event* wsrep_read_log_event( char **arg_buf, size_t *arg_buf_len, const Format_description_log_event *description_event) @@ -10889,12 +10892,8 @@ Log_event* wsrep_read_log_event( char *buf= (*arg_buf); const char *error= 0; Log_event *res= 0; -#ifndef max_allowed_packet - THD *thd=current_thd; - uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0; -#endif - if (data_len > max_allowed_packet) + if (data_len > WSREP_MAX_ALLOWED_PACKET) { error = "Event too big"; goto err; diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index c4468ee8793..00691633aa8 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -100,11 +100,14 @@ bool Alter_table_statement::execute(THD *thd) thd->enable_slow_log= opt_log_slow_admin_statements; #ifdef WITH_WSREP -TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); + TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); if ((!thd->is_current_stmt_binlog_format_row() || !find_temporary_table(thd, first_table)) && - wsrep_to_isolation_begin(thd, first_table->db, first_table->table_name)) + wsrep_to_isolation_begin(thd, + lex->name.str ? select_lex->db : NULL, + lex->name.str ? lex->name.str : NULL, + first_table)) { WSREP_WARN("ALTER TABLE isolation failure"); DBUG_RETURN(TRUE); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d4aeedeb852..da93cfeb001 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,6 +62,7 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" + #endif // WITH_WSREP bool @@ -5077,6 +5078,24 @@ restart: } } } +#ifdef WITH_WSREP +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ + if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto err; + + if ((thd->lex->sql_command== SQLCOM_INSERT || + thd->lex->sql_command== SQLCOM_INSERT_SELECT || + thd->lex->sql_command== SQLCOM_REPLACE || + thd->lex->sql_command== SQLCOM_REPLACE_SELECT || + thd->lex->sql_command== SQLCOM_UPDATE || + thd->lex->sql_command== SQLCOM_UPDATE_MULTI || + thd->lex->sql_command== SQLCOM_LOAD || + thd->lex->sql_command== SQLCOM_DELETE) && + wsrep_replicate_myisam && + (*start)->table && (*start)->table->file->ht->db_type == DB_TYPE_MYISAM) + { + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); + } +#endif err: #ifdef WITH_WSREP diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 04e46bfa1e6..c0cdddeb561 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -100,9 +100,6 @@ int get_or_create_user_conn(THD *thd, const char *user, } thd->user_connect=uc; uc->connections++; -#ifdef WITH_WSREP - thd->wsrep_client_thread= 1; -#endif /* WITH_WSREP */ end: mysql_mutex_unlock(&LOCK_user_conn); return return_val; @@ -1203,6 +1200,9 @@ bool thd_prepare_connection(THD *thd) (char *) thd->security_ctx->host_or_ip); prepare_new_connection_state(thd); +#ifdef WITH_WSREP + thd->wsrep_client_thread= 1; +#endif /* WITH_WSREP */ return FALSE; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 51d81616c24..b4b7eb0b2cf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -105,19 +105,20 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" #include "rpl_rli.h" +static void wsrep_client_rollback(THD *thd); extern Format_description_log_event *wsrep_format_desc; #define WSREP_MYSQL_DB (char *)"mysql" -#define WSREP_TO_ISOLATION_BEGIN(db_, table_) \ - if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_)) goto error; +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ + if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; #define WSREP_TO_ISOLATION_END \ if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \ wsrep_to_isolation_end(thd); #else -#define WSREP_TO_ISOLATION_BEGIN(db_, table_) +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) #define WSREP_TO_ISOLATION_END #endif /* WITH_WSREP */ /** @@ -727,15 +728,7 @@ bool do_command(THD *thd) thd->wsrep_query_state= QUERY_IDLE; if (thd->wsrep_conflict_state==MUST_ABORT) { - thd->wsrep_conflict_state= ABORTING; - - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - trans_rollback(thd); - thd->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state= ABORTED; + wsrep_client_rollback(thd); } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } @@ -822,16 +815,7 @@ bool do_command(THD *thd) if (thd->wsrep_conflict_state == MUST_ABORT) { DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id)); - thd->wsrep_conflict_state= ABORTING; - - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - trans_rollback(thd); - thd->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state= ABORTED; + wsrep_client_rollback(thd); } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } @@ -1082,14 +1066,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (thd->wsrep_conflict_state== MUST_ABORT) { - thd->wsrep_conflict_state= ABORTING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - trans_rollback(thd); - thd->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state= ABORTED; + wsrep_client_rollback(thd); } if (thd->wsrep_conflict_state== ABORTED) { @@ -1641,43 +1618,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_wsrep_thd); if (thd->wsrep_conflict_state == MUST_ABORT) { - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - ha_rollback_trans(thd, 0); - thd->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - thd->transaction.stmt.reset(); + wsrep_client_rollback(thd); + WSREP_DEBUG("abort in exec query state, avoiding autocommit"); - goto wsrep_must_abort; } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - } -#endif /* WITH_WSREP */ -#ifdef WITH_WSREP - wsrep_must_abort: - if (WSREP(thd)) { - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) { - thd->wsrep_conflict_state= ABORTING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - WSREP_DEBUG("in dispatch_command, aborting %s", - (thd->query()) ? thd->query() : "void"); - trans_rollback(thd); - thd->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - - if (thd->get_binlog_table_maps()) { - thd->clear_binlog_table_maps(); - } - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state= ABORTED; - } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); /* checking if BF trx must be replayed */ if (thd->wsrep_conflict_state== MUST_REPLAY) { if (thd->wsrep_exec_mode!= REPL_RECV) { @@ -1692,11 +1637,18 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_reset_thd_for_next_command(thd, opt_userstat_running); thd->killed= NOT_KILLED; close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); thd_proc_info(thd, "wsrep replaying trx"); WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)thd->wsrep_trx_seqno); + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); struct wsrep_thd_shadow shadow; wsrep_prepare_bf_thd(thd, &shadow); int rcode = wsrep->replay_trx(wsrep, @@ -2547,7 +2499,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; #endif /* WITH_WSREP */ if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))) @@ -2557,7 +2509,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STATUS: { #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; #endif /* WITH_WSREP */ execute_show_status(thd, all_tables); break; @@ -2583,7 +2535,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_INDEX_STATS: case SQLCOM_SELECT: #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: @@ -3007,7 +2959,8 @@ case SQLCOM_PREPARE: #ifdef WITH_WSREP if (!thd->is_current_stmt_binlog_format_row() || !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) - WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, + NULL) #endif /* WITH_WSREP */ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) { @@ -3050,7 +3003,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_one_table_access(thd, INDEX_ACL, all_tables)) goto error; /* purecov: inspected */ - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name) + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) /* Currently CREATE INDEX or DROP INDEX cause a full table rebuild and thus classify as slow administrative statements just like @@ -3108,7 +3061,7 @@ end_with_restore_list: case SQLCOM_RENAME_TABLE: { - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name) + WSREP_TO_ISOLATION_BEGIN(0, 0, first_table) if (execute_rename_table(thd, first_table, all_tables)) goto error; break; @@ -3137,7 +3090,7 @@ end_with_restore_list: #else { #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; #endif /* WITH_WSREP */ /* @@ -3196,7 +3149,7 @@ end_with_restore_list: { DBUG_ASSERT(first_table == all_tables && first_table != 0); #ifdef WITH_WSREP - if (WSREP(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; #endif /* WITH_WSREP */ if (check_table_access(thd, SELECT_ACL, all_tables, @@ -3397,7 +3350,7 @@ end_with_restore_list: if (lex->sql_command == SQLCOM_INSERT_SELECT && thd->wsrep_consistency_check) { - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name); + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL); } #endif @@ -3568,9 +3521,9 @@ end_with_restore_list: for (TABLE_LIST *table= all_tables; table; table= table->next_global) { if (!thd->is_current_stmt_binlog_format_row() || - !find_temporary_table(thd, table)) + !find_temporary_table(thd, table)) { - WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name); + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables); break; } } @@ -3760,7 +3713,7 @@ end_with_restore_list: #endif if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) break; - WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL) + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name.str), &create_info, 0); break; @@ -3790,7 +3743,7 @@ end_with_restore_list: #endif if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) break; - WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL) + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } @@ -3819,7 +3772,7 @@ end_with_restore_list: res= 1; break; } - WSREP_TO_ISOLATION_BEGIN(db->str, NULL) + WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL) res= mysql_upgrade_db(thd, db); if (!res) my_ok(thd); @@ -3852,7 +3805,7 @@ end_with_restore_list: #endif if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0)) break; - WSREP_TO_ISOLATION_BEGIN(db->str, NULL) + WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL) res= mysql_alter_db(thd, db->str, &create_info); break; } @@ -3885,7 +3838,7 @@ end_with_restore_list: if (res) break; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: { @@ -3920,7 +3873,7 @@ end_with_restore_list: lex->spname->m_name); break; case SQLCOM_DROP_EVENT: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= Events::drop_event(thd, lex->spname->m_db, lex->spname->m_name, lex->drop_if_exists))) @@ -3935,7 +3888,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0)) break; #ifdef HAVE_DLOPEN - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res = mysql_create_function(thd, &lex->udf))) my_ok(thd); #else @@ -3950,7 +3903,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ if (!(res= mysql_create_user(thd, lex->users_list))) my_ok(thd); @@ -3962,7 +3915,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_drop_user(thd, lex->users_list))) my_ok(thd); break; @@ -3973,7 +3926,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_rename_user(thd, lex->users_list))) my_ok(thd); break; @@ -3988,7 +3941,7 @@ end_with_restore_list: thd->binlog_invoker(); /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res = mysql_revoke_all(thd, lex->users_list))) my_ok(thd); break; @@ -4055,7 +4008,7 @@ end_with_restore_list: lex->type == TYPE_ENUM_PROCEDURE, 0)) goto error; /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_routine_grant(thd, all_tables, lex->type == TYPE_ENUM_PROCEDURE, lex->users_list, grants, @@ -4069,7 +4022,7 @@ end_with_restore_list: all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_table_grant(thd, all_tables, lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE); @@ -4085,7 +4038,7 @@ end_with_restore_list: } else { - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, lex->sql_command == SQLCOM_REVOKE, @@ -4383,7 +4336,7 @@ end_with_restore_list: if (sp_process_definer(thd)) goto create_sp_error; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= (sp_result= sp_create_routine(thd, lex->sphead->m_type, lex->sphead)); switch (sp_result) { case SP_OK: { @@ -4595,7 +4548,7 @@ create_sp_error: already puts on CREATE FUNCTION. */ /* Conditionally writes to binlog */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) sp_result= sp_update_routine(thd, type, lex->spname, &lex->sp_chistics); switch (sp_result) { @@ -4667,7 +4620,7 @@ create_sp_error: if (check_routine_access(thd, ALTER_PROC_ACL, db, name, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) goto error; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ sp_result= sp_drop_routine(thd, type, lex->spname); @@ -4785,7 +4738,7 @@ create_sp_error: Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands as specified through the thd->lex->create_view_mode flag. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_view(thd, first_table, thd->lex->create_view_mode); break; } @@ -4794,14 +4747,14 @@ create_sp_error: if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(NULL, NULL) + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, NULL) res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); break; } case SQLCOM_CREATE_TRIGGER: { /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 1); break; @@ -4809,7 +4762,7 @@ create_sp_error: case SQLCOM_DROP_TRIGGER: { /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 0); break; } @@ -4860,13 +4813,13 @@ create_sp_error: my_ok(thd); break; case SQLCOM_INSTALL_PLUGIN: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (! (res= mysql_install_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); break; case SQLCOM_UNINSTALL_PLUGIN: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); @@ -7905,6 +7858,41 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) } #ifdef WITH_WSREP +/* must have (&thd->LOCK_wsrep_thd) */ +static void wsrep_client_rollback(THD *thd) +{ + WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", + thd->thread_id, thd->query()); + + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("unlocking tables for BF abort (%ld)", 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 (%ld)", thd->thread_id); + thd->global_read_lock.unlock_global_read_lock(thd); + } + + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + + if (thd->get_binlog_table_maps()) + { + WSREP_DEBUG("clearing binlog table map for BF abort (%ld)", thd->thread_id); + thd->clear_binlog_table_maps(); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; +} + static enum wsrep_status wsrep_apply_sql( THD *thd, const char *sql, size_t sql_len, time_t timeval, uint32 randseed) { @@ -8008,6 +7996,13 @@ static inline wsrep_status_t wsrep_apply_rbr( int error = 0; Log_event* ev= wsrep_read_log_event(&buf, &buf_len, wsrep_format_desc); + if (!ev) + { + WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", + (long long)thd->wsrep_trx_seqno, buf_len); + rcode= 1; + goto error; + } switch (ev->get_type_code()) { case WRITE_ROWS_EVENT: case UPDATE_ROWS_EVENT: @@ -8378,16 +8373,12 @@ void wsrep_rollback_process(THD *thd) aborting->store_globals(); - trans_rollback(aborting); - aborting->locked_tables_list.unlock_locked_tables(thd); - /* Release transactional metadata locks. */ - aborting->mdl_context.release_transactional_locks(); - mysql_mutex_lock(&aborting->LOCK_wsrep_thd); - aborting->wsrep_conflict_state= ABORTED; + wsrep_client_rollback(aborting); WSREP_DEBUG("WSREP rollbacker aborted thd: %llu", (long long)aborting->real_id); mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_rollback); } } diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index a66b2377fcb..6745d461df5 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -521,7 +521,7 @@ bool Truncate_statement::execute(THD *thd) #ifdef WITH_WSREP if (WSREP(thd) && wsrep_to_isolation_begin(thd, first_table->db, - first_table->table_name)) + first_table->table_name, NULL)) DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ if (! (res= truncate_table(thd, first_table))) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8edfa8f2a6e..b8c21f9621e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3779,6 +3779,9 @@ static Sys_var_mybool Sys_wsrep_recover_datadir( READ_ONLY GLOBAL_VAR(wsrep_recovery), CMD_LINE(OPT_ARG, OPT_WSREP_RECOVER), DEFAULT(FALSE)); +static Sys_var_mybool Sys_wsrep_replicate_myisam( + "wsrep_replicate_myisam", "To enable myisam replication", + GLOBAL_VAR(wsrep_replicate_myisam), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); #endif /* WITH_WSREP */ diff --git a/sql/transaction.cc b/sql/transaction.cc index d5f9436ae53..ef4383df0ea 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -158,7 +158,7 @@ bool trans_begin(THD *thd, uint flags) #ifdef WITH_WSREP thd->wsrep_PA_safe= true; - if (thd->wsrep_client_thread && wsrep_causal_wait(thd)) + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 9986d7c79cd..bb5faafc768 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -15,6 +15,7 @@ #include #include "sql_base.h" +#include "rpl_filter.h" #include #include "wsrep_mysqld.h" #include "wsrep_priv.h" @@ -174,6 +175,7 @@ int wsrep_commit(handlerton *hton, THD *thd, bool all) DBUG_RETURN(0); } +extern Rpl_filter* binlog_filter; extern my_bool opt_log_slave_updates; enum wsrep_trx_status wsrep_run_wsrep_commit( @@ -238,7 +240,8 @@ wsrep_run_wsrep_commit( while (wsrep_replaying > 0 && thd->wsrep_conflict_state == NO_CONFLICT && thd->killed == NOT_KILLED && - !shutdown_in_progress) { + !shutdown_in_progress) + { mysql_mutex_unlock(&LOCK_wsrep_replaying); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -278,7 +281,8 @@ wsrep_run_wsrep_commit( WSREP_DEBUG("innobase_commit abort after replaying wait %s", (thd->query()) ? thd->query() : "void"); DBUG_RETURN(WSREP_TRX_ROLLBACK); - } thd->wsrep_query_state = QUERY_COMMITTING; + } + thd->wsrep_query_state = QUERY_COMMITTING; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); cache = get_trans_log(thd); @@ -296,8 +300,18 @@ wsrep_run_wsrep_commit( { mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_exec_mode = LOCAL_COMMIT; - WSREP_DEBUG("empty rbr buffer, query: %s", thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (thd->stmt_da->is_ok() && + thd->stmt_da->affected_rows() > 0 && + !binlog_filter->is_on()) + { + WSREP_WARN("empty rbr buffer, query: %s, affected rows: %llu", + thd->query(), thd->stmt_da->affected_rows()); + } + else + { + WSREP_DEBUG("empty rbr buffer, query: %s", thd->query()); + } DBUG_RETURN(WSREP_TRX_OK); } if (!rcode) { diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 5a5250652b8..be2b8d7fa81 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -48,6 +48,7 @@ my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key long wsrep_max_protocol_version = 1; // maximum protocol version to use ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery +my_bool wsrep_replicate_myisam = 0; // enable myisam replication /* * End configuration options @@ -456,9 +457,25 @@ int wsrep_init() } } + char node_addr[256] = {0, }; + if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) + { + size_t node_addr_max= sizeof(node_addr); + size_t ret= default_ip(node_addr, node_addr_max); + if (!(ret > 0 && ret < node_addr_max)) + { + WSREP_WARN("Failed to autoguess base node address"); + node_addr[0]= 0; + } + } + else if (wsrep_node_address) + { + strncpy(node_addr, wsrep_node_address, sizeof(node_addr) - 1); + } + wsrep_args.data_dir = wsrep_data_home_dir; wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; - wsrep_args.node_address = (wsrep_node_address) ? wsrep_node_address : ""; + wsrep_args.node_address = node_addr; wsrep_args.node_incoming = wsrep_node_incoming_address; wsrep_args.options = (wsrep_provider_options) ? wsrep_provider_options : ""; @@ -629,7 +646,8 @@ bool wsrep_causal_wait (THD* thd) { if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on && - !thd->in_active_multi_stmt_transaction()) + !thd->in_active_multi_stmt_transaction() && + thd->wsrep_conflict_state != REPLAYING) { // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // TODO: modify to check if thd has locked any rows. @@ -667,10 +685,42 @@ wsrep_causal_wait (THD* thd) return false; } -bool wsrep_prepare_key_for_isolation(const char* db, - const char* table, - wsrep_key_part_t* key, - size_t* key_len) +/* + * Helpers to deal with TOI key arrays + */ +typedef struct wsrep_key_arr +{ + wsrep_key_t* keys; + size_t keys_len; +} wsrep_key_arr_t; + + +static void wsrep_keys_free(wsrep_key_arr_t* key_arr) +{ + for (size_t i= 0; i < key_arr->keys_len; ++i) + { + my_free((wsrep_key_part_t*)key_arr->keys[i].key_parts); + } + my_free(key_arr->keys); + key_arr->keys= 0; + key_arr->keys_len= 0; +} + + +/*! + * @param db Database string + * @param table Table string + * @param key Array of wsrep_key_t + * @param key_len In: number of elements in key array, Out: number of + * elements populated + * + * @return true if preparation was successful, otherwise false. + */ + +static bool wsrep_prepare_key_for_isolation(const char* db, + const char* table, + wsrep_key_part_t* key, + size_t* key_len) { if (*key_len < 2) return false; @@ -707,6 +757,89 @@ bool wsrep_prepare_key_for_isolation(const char* db, return true; } +/* Prepare key list from db/table and table_list */ +static bool wsrep_prepare_keys_for_isolation(THD* thd, + const char* db, + const char* table, + const TABLE_LIST* table_list, + wsrep_key_arr_t* ka) +{ + ka->keys= 0; + ka->keys_len= 0; + + extern TABLE* find_temporary_table(THD*, const TABLE_LIST*); + + if (db || table) + { + TABLE_LIST tmp_table; + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.table_name= (char*)db; + tmp_table.db= (char*)table; + if (!table || !find_temporary_table(thd, &tmp_table)) + { + if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0)))) + { + sql_print_error("Can't allocate memory for key_array"); + goto err; + } + ka->keys_len= 1; + if (!(ka->keys[0].key_parts= (wsrep_key_part_t*) + my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + { + sql_print_error("Can't allocate memory for key_parts"); + goto err; + } + ka->keys[0].key_parts_len= 2; + if (!wsrep_prepare_key_for_isolation( + db, table, + (wsrep_key_part_t*)ka->keys[0].key_parts, + &ka->keys[0].key_parts_len)) + { + sql_print_error("Preparing keys for isolation failed"); + goto err; + } + } + } + + for (const TABLE_LIST* table= table_list; table; table= table->next_global) + { + if (!find_temporary_table(thd, table)) + { + wsrep_key_t* tmp; + tmp= (wsrep_key_t*)my_realloc( + ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); + if (!tmp) + { + sql_print_error("Can't allocate memory for key_array"); + goto err; + } + ka->keys= tmp; + if (!(ka->keys[ka->keys_len].key_parts= (wsrep_key_part_t*) + my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + { + sql_print_error("Can't allocate memory for key_parts"); + goto err; + } + ka->keys[ka->keys_len].key_parts_len= 2; + ++ka->keys_len; + if (!wsrep_prepare_key_for_isolation( + table->db, table->table_name, + (wsrep_key_part_t*)ka->keys[ka->keys_len - 1].key_parts, + &ka->keys[ka->keys_len - 1].key_parts_len)) + { + sql_print_error("Preparing keys for isolation failed"); + goto err; + } + } + } + return true; +err: + wsrep_keys_free(ka); + return false; +} + + + bool wsrep_prepare_key_for_innodb(const uchar* cache_key, size_t cache_key_len, const uchar* row_id, @@ -842,15 +975,14 @@ create_view_query(THD *thd, uchar** buf, uint* buf_len) return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len); } -static int wsrep_TOI_begin(THD *thd, char *db_, char *table_) +static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list) { wsrep_status_t ret(WSREP_WARNING); uchar* buf(0); uint buf_len(0); int buf_err; - wsrep_key_part_t wkey_part[2]; - wsrep_key_t wkey = {wkey_part, 2}; WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, thd->wsrep_exec_mode, thd->query() ); switch (thd->lex->sql_command) @@ -874,17 +1006,18 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_) break; } + wsrep_key_arr_t key_arr= {0, 0}; if (!buf_err && - wsrep_prepare_key_for_isolation(db_, table_, wkey_part, - &wkey.key_parts_len) && + wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&& WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, - &wkey, 1, + key_arr.keys, key_arr.keys_len, buf, buf_len, &thd->wsrep_trx_seqno))) { thd->wsrep_exec_mode= TOTAL_ORDER; wsrep_to_isolation++; if (buf) my_free(buf); + wsrep_keys_free(&key_arr); WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)thd->wsrep_trx_seqno, thd->wsrep_exec_mode); } @@ -896,6 +1029,7 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_) my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " "your wsrep connection state and retry the query."); if (buf) my_free(buf); + wsrep_keys_free(&key_arr); return -1; } return 0; @@ -959,13 +1093,15 @@ static void wsrep_RSU_end(THD *thd) return; } -int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_) +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list) { int ret= 0; if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { - case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_); break; + case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_, + table_list); break; case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; } if (!ret) @@ -1046,7 +1182,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, } else { - WSREP_MDL_LOG(INFO, "MDL conflict -> BF abort", request_thd, granted_thd); + WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); return FALSE; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 90498c266ee..985431e74b9 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -60,6 +60,7 @@ extern long wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; extern ulong wsrep_OSU_method_options; extern my_bool wsrep_recovery; +extern my_bool wsrep_replicate_myisam; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; @@ -162,6 +163,9 @@ extern wsrep_seqno_t wsrep_locked_seqno; #define WSREP(thd) \ (WSREP_ON && (thd && thd->variables.wsrep_on)) +#define WSREP_CLIENT(thd) \ + (WSREP(thd) && thd->wsrep_client_thread) + #define WSREP_EMULATE_BINLOG(thd) \ (WSREP(thd) && wsrep_emulate_bin_log) @@ -206,20 +210,6 @@ class Ha_trx_info; struct THD_TRANS; void wsrep_register_hton(THD* thd, bool all); -/*! - * @param db Database string - * @param table Table string - * @param key Array of wsrep_key_t - * @param key_len In: number of elements in key array, Out: number of - * elements populated - * - * @return true if preparation was successful, otherwise false. - */ -bool wsrep_prepare_key_for_isolation(const char* db, - const char* table, - wsrep_key_part_t* key, - size_t *key_len); - void wsrep_replication_process(THD *thd); void wsrep_rollback_process(THD *thd); void wsrep_brute_force_killer(THD *thd); @@ -274,7 +264,9 @@ extern PSI_cond_key key_COND_wsrep_rollback; extern PSI_mutex_key key_LOCK_wsrep_replaying; extern PSI_cond_key key_COND_wsrep_replaying; -int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_); +struct TABLE_LIST; +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list); void wsrep_to_isolation_end(THD *thd); void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index f39353eda44..a6d7dcdbfc8 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -332,7 +332,7 @@ size_t default_ip (char* buf, size_t buf_len) "awk '{ print $2 }' | awk -F : '{ print $2 }'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " - "grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; + "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; #else char *cmd; #error "OS not supported" diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c9d4a28868d..050ebf7d505 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6945,11 +6945,6 @@ wsrep_append_foreign_key( byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; - if (!dict_index_is_clust(clust_index)) { - WSREP_ERROR("clustered index not passed for FK append"); - return DB_ERROR; - } - key[0] = '\0'; rcode = wsrep_rec_get_primary_key( &key[1], &len, clust_rec, clust_index); diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 9ba1c646d9d..dbfc41881ce 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1790,25 +1790,23 @@ wsrep_rec_get_primary_key( uint key_parts; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; + const ulint* offsets; ut_ad(index); - key_parts = dict_index_get_n_unique_in_tree(index); - *offsets_ = (sizeof offsets_) / sizeof *offsets_; - rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } + rec_offs_init(offsets_); + offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); - ut_ad(rec_offs_validate(rec, NULL, offsets_)); + ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec); + key_parts = dict_index_get_n_unique_in_tree(index); for (i = 0; i < key_parts; i++) { - dict_field_t* field = dict_index_get_nth_field(index, i); + dict_field_t* field = dict_index_get_nth_field(index, i); const dict_col_t* col = dict_field_get_col(field); - data = rec_get_nth_field(rec, offsets_, i, &len); + data = rec_get_nth_field(rec, offsets, i, &len); if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? *buf_len : *buf_len - 1)) { fprintf (stderr, @@ -1836,11 +1834,19 @@ wsrep_rec_get_primary_key( } } - rec_validate(rec, offsets_); + rec_validate(rec, offsets); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + *buf_len = key_len; return DB_SUCCESS; err_out: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } return DB_ERROR; } #endif // WITH_WSREP diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 9e10cbc5d34..a1119fc3d47 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -7589,11 +7589,6 @@ wsrep_append_foreign_key( byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; - if (!dict_index_is_clust(clust_index)) { - WSREP_ERROR("clustered index not passed for FK append"); - return DB_ERROR; - } - key[0] = '\0'; rcode = wsrep_rec_get_primary_key( &key[1], &len, clust_rec, clust_index); diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index 9ba1c646d9d..dbfc41881ce 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -1790,25 +1790,23 @@ wsrep_rec_get_primary_key( uint key_parts; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; + const ulint* offsets; ut_ad(index); - key_parts = dict_index_get_n_unique_in_tree(index); - *offsets_ = (sizeof offsets_) / sizeof *offsets_; - rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } + rec_offs_init(offsets_); + offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); - ut_ad(rec_offs_validate(rec, NULL, offsets_)); + ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec); + key_parts = dict_index_get_n_unique_in_tree(index); for (i = 0; i < key_parts; i++) { - dict_field_t* field = dict_index_get_nth_field(index, i); + dict_field_t* field = dict_index_get_nth_field(index, i); const dict_col_t* col = dict_field_get_col(field); - data = rec_get_nth_field(rec, offsets_, i, &len); + data = rec_get_nth_field(rec, offsets, i, &len); if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? *buf_len : *buf_len - 1)) { fprintf (stderr, @@ -1836,11 +1834,19 @@ wsrep_rec_get_primary_key( } } - rec_validate(rec, offsets_); + rec_validate(rec, offsets); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + *buf_len = key_len; return DB_SUCCESS; err_out: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } return DB_ERROR; } #endif // WITH_WSREP From 33ffe0dd29b6564e49dde8b1abda914da4b2f178 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 12 Jun 2012 10:55:11 +0300 Subject: [PATCH 004/294] References lp:1011983 Merged from codership-mysql/5.5 changes revisions 3743-3756 --- cmake/wsrep.cmake | 2 +- scripts/mysqld_safe.sh | 39 ++++++++++++++++++++++- sql/log_event.cc | 6 +++- sql/mysqld.cc | 23 ++++++++++++-- sql/sql_parse.cc | 8 ----- sql/wsrep_hton.cc | 11 +++++-- sql/wsrep_mysqld.cc | 12 ++++--- sql/wsrep_mysqld.h | 4 +-- sql/wsrep_sst.cc | 26 +++++++++++---- storage/innobase/handler/ha_innodb.cc | 30 +++++++++++------ storage/innobase/include/rem0rec.h | 3 +- storage/innobase/rem/rem0rec.c | 46 +++++++++++++++++++++++++-- storage/xtradb/handler/ha_innodb.cc | 30 +++++++++++------ storage/xtradb/include/rem0rec.h | 3 +- storage/xtradb/rem/rem0rec.c | 46 +++++++++++++++++++++++++-- 15 files changed, 236 insertions(+), 53 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 1fd747cddd6..3c10c5b3836 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "5") +SET(WSREP_PATCH_VERSION "6") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index aaf1936afe1..5a390a32f26 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -63,6 +63,7 @@ Usage: $0 [OPTIONS] --syslog Log messages to syslog with 'logger' --skip-syslog Log messages to error log (default) --syslog-tag=TAG Pass -t "mysqld-TAG" to 'logger' + --wsrep-urls=WSREP_URLS Comma-separated list of wsrep URLs All other options are passed to the mysqld program. @@ -161,6 +162,34 @@ shell_quote_string() { echo "$1" | sed -e 's,\([^a-zA-Z0-9/_.=-]\),\\\1,g' } +wsrep_pick_url() { + [ $# -eq 0 ] && return 0 + + if ! which nc >/dev/null; then + log_error "ERROR: nc tool not found in PATH! Make sure you have it installed." + return 1 + fi + + local url + # Assuming URL in the form scheme://host:port + # If host and port are not NULL, the liveness of URL is assumed to be tested + # If port part is absent, the url is returned literally and unconditionally + # If every URL has port but none is reachable, nothing is returned + for url in `echo $@ | sed s/,/\ /g` 0; do + local host=`echo $url | cut -d \: -f 2 | sed s/^\\\/\\\///` + local port=`echo $url | cut -d \: -f 3` + [ -z "$port" ] && break + nc -z "$host" $port >/dev/null && break + done + + if [ "$url" == "0" ]; then + log_error "ERROR: none of the URLs in '$@' is reachable." + return 1 + fi + + echo $url +} + parse_arguments() { # We only need to pass arguments through to the server if we don't # handle them here. So, we collect unrecognized options (passed on @@ -221,6 +250,7 @@ parse_arguments() { --skip-syslog) want_syslog=0 ;; --syslog-tag=*) syslog_tag="$val" ;; --timezone=*) TZ="$val"; export TZ; ;; + --wsrep[-_]urls=*) wsrep_urls="$val"; ;; --help) usage ;; @@ -772,9 +802,16 @@ while true do rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety + [ -n "$wsrep_urls" ] && url=`wsrep_pick_url $wsrep_urls` # check connect address + start_time=`date +%M%S` - eval_log_error "$cmd" + if [ -z "$url" ] + then + eval_log_error "$cmd" + else + eval_log_error "$cmd --wsrep_cluster_address=$url" + fi end_time=`date +%M%S` diff --git a/sql/log_event.cc b/sql/log_event.cc index 1536d9e899b..ccfa1ae73e2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9237,8 +9237,12 @@ check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list) { DBUG_ENTER("check_table_map"); enum_tbl_map_status res= OK_TO_PROCESS; - +#ifdef WITH_WSREP + if ((rli->sql_thd->slave_thread /* filtering is for slave only */ || + (WSREP(rli->sql_thd) && rli->sql_thd->wsrep_applier)) && +#else if (rli->sql_thd->slave_thread /* filtering is for slave only */ && +#endif /* WITH_WSREP */ (!rpl_filter->db_ok(table_list->db) || (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list)))) res= FILTERED_OUT; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ec6219b978f..a88e76972e4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4857,6 +4857,17 @@ WSREP_WARN("applier has wsrep_exec_mode = %d", thd->wsrep_exec_mode); #endif /* REMOVE */ } +static inline bool is_replaying_connection(THD *thd) +{ + bool ret; + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + return ret; +} + static bool have_client_connections() { THD *tmp; @@ -4932,6 +4943,12 @@ void wsrep_close_client_connections(my_bool wait_to_end) if (!is_client_connection(tmp)) continue; + if (is_replaying_connection(tmp)) + { + tmp->killed= KILL_CONNECTION; + continue; + } + /* replicated transactions must be skipped */ if (abort_replicated(tmp)) continue; @@ -4953,9 +4970,11 @@ void wsrep_close_client_connections(my_bool wait_to_end) while ((tmp=it2++)) { #ifndef __bsdi__ // Bug in BSDI kernel - if (is_client_connection(tmp) && !abort_replicated(tmp)) + if (is_client_connection(tmp) && + !abort_replicated(tmp) && + !is_replaying_connection(tmp)) { - WSREP_INFO("SST kill local trx: %ld",tmp->thread_id); + WSREP_INFO("killing local connection: %ld",tmp->thread_id); close_connection(tmp,0,0); } #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b4b7eb0b2cf..cce1aaf05d4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8297,14 +8297,6 @@ void wsrep_replication_process(THD *thd) break; } - if (thd->killed != KILL_CONNECTION) - { - mysql_mutex_lock(&LOCK_thread_count); - wsrep_close_applier(thd); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - } - if (thd->killed != KILL_CONNECTION) { mysql_mutex_lock(&LOCK_thread_count); diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index bb5faafc768..49b3ea5c0bf 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -305,8 +305,15 @@ wsrep_run_wsrep_commit( thd->stmt_da->affected_rows() > 0 && !binlog_filter->is_on()) { - WSREP_WARN("empty rbr buffer, query: %s, affected rows: %llu", - thd->query(), thd->stmt_da->affected_rows()); + 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->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 { diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index be2b8d7fa81..0bf0c2294d3 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -45,7 +45,7 @@ long long wsrep_max_ws_size = 1073741824LL; //max ws (RBR buffer) siz long wsrep_max_ws_rows = 65536; // max number of rows in ws int wsrep_to_isolation = 0; // # of active TO isolation threads my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key -long wsrep_max_protocol_version = 1; // maximum protocol version to use +long wsrep_max_protocol_version = 2; // maximum protocol version to use ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery my_bool wsrep_replicate_myisam = 0; // enable myisam replication @@ -90,7 +90,7 @@ const char* wsrep_provider_vendor = provider_vendor; wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; -long wsrep_protocol_version = 1; +long wsrep_protocol_version = 2; // action execute callback extern wsrep_status_t wsrep_apply_cb(void *ctx, @@ -229,6 +229,7 @@ static void wsrep_view_handler_cb (void* app_ctx, { case 0: case 1: + case 2: // version change if (view->proto_ver != wsrep_protocol_version) { @@ -278,9 +279,10 @@ static void wsrep_view_handler_cb (void* app_ctx, { /* * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized - * before. + * before - OR - it was reinitilized on startup (lp:992840) */ - if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t))) + if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) || + 0 == wsrep_cluster_conf_id) { if (wsrep_init_first()) { @@ -730,6 +732,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db, *key_len= 0; break; case 1: + case 2: { *key_len= 0; if (db) @@ -860,6 +863,7 @@ bool wsrep_prepare_key_for_innodb(const uchar* cache_key, break; } case 1: + case 2: { key[*key_len].buf = cache_key; key[*key_len].buf_len = strlen( (char*)cache_key ); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 985431e74b9..ebea44c9151 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -1,4 +1,4 @@ -/* Copyright 2008 Codership Oy +/* Copyright 2008-2012 Codership Oy 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 @@ -131,7 +131,7 @@ extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_init_first(); // initialize wsrep before storage - // engines or after + // engines (true) or after (false) extern int wsrep_init(); extern void wsrep_deinit(); extern void wsrep_recover(); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 4ce7fe84b0f..37779c4b96d 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2011 Codership Oy +/* Copyright 2008-2012 Codership Oy 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 @@ -25,10 +25,11 @@ extern const char wsrep_defaults_file[]; -#define WSREP_SST_MYSQLDUMP "mysqldump" -#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP +#define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_SKIP "skip" +#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP #define WSREP_SST_ADDRESS_AUTO "AUTO" -#define WSREP_SST_AUTH_MASK "********" +#define WSREP_SST_AUTH_MASK "********" const char* wsrep_sst_method = WSREP_SST_DEFAULT; const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; @@ -158,6 +159,7 @@ bool wsrep_init_first() { return (wsrep_provider != NULL && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_sst_method, WSREP_SST_SKIP) && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } @@ -439,8 +441,8 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in, ret= -ENOMEM; } - sql_print_error ("WSREP: Could not prepare state transfer request: " - "adding default port failed: %zd.", ret); + WSREP_ERROR ("Could not prepare state transfer request: " + "adding default port failed: %zd.", ret); } else { *addr_out= addr_in; @@ -458,6 +460,18 @@ ssize_t wsrep_sst_prepare (void** msg) const char* addr_in= NULL; const char* addr_out= NULL; + 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; + } + // Figure out SST address. Common for all SST methods if (wsrep_sst_receive_address && strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 050ebf7d505..52df97e5eee 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4751,14 +4751,17 @@ wsrep_store_key_val_for_row( wsrep_innobase_mysql_sort( mysql_type, cs->number, sorted, true_len); - /* Note that we always reserve the maximum possible + if (wsrep_protocol_version > 1) { + memcpy(buff, sorted, true_len); + /* Note that we always reserve the maximum possible length of the true VARCHAR in the key value, though only len first bytes after the 2 length bytes contain actual data. The rest of the space was reset to zero in the bzero() call above. */ - - buff += key_len; - + buff += true_len; + } else { + buff += key_len; + } } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB @@ -4825,8 +4828,11 @@ wsrep_store_key_val_for_row( /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ - - buff += key_len; + if (wsrep_protocol_version > 1) { + buff += true_len; + } else { + buff += key_len; + } } else { /* Here we handle all other data types except the true VARCHAR, BLOB and TEXT. Note that the column @@ -6947,20 +6953,24 @@ wsrep_append_foreign_key( key[0] = '\0'; rcode = wsrep_rec_get_primary_key( - &key[1], &len, clust_rec, clust_index); + &key[1], &len, clust_rec, clust_index, + wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { WSREP_ERROR("FK key set failed: %lu", rcode); return rcode; } #ifdef WSREP_DEBUG_PRINT ulint i; - fprintf(stderr, "FK parent key, len: %lu ", len+1); + fprintf(stderr, "FK parent key, table: %s shared: %d len: %lu ", + foreign->referenced_table_name, (int)shared, len+1); for (i=0; iforeign_table->name, 512); + strncpy(cache_key, (wsrep_protocol_version > 1) ? + foreign->referenced_table->name : + foreign->foreign_table->name, 512); char *p = strchr(cache_key, '/'); if (p) { *p = '\0'; diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index ab390f4fb3a..30ef3048ff1 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -837,7 +837,8 @@ int wsrep_rec_get_primary_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index); /* in: record descriptor */ + dict_index_t* index, /* in: record descriptor */ + ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index dbfc41881ce..15618a3fa02 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1781,7 +1781,8 @@ wsrep_rec_get_primary_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index) /* in: record descriptor */ + dict_index_t* index, /* in: record descriptor */ + ibool new_protocol) /* in: protocol > 1 */ { const byte* data; ulint len; @@ -1819,7 +1820,7 @@ wsrep_rec_get_primary_key( ut_a(!(col->prtype & DATA_NOT_NULL)); *buf++ = 1; key_len++; - } else { + } else if (!new_protocol) { if (!(col->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; @@ -1829,6 +1830,47 @@ wsrep_rec_get_primary_key( (int)(col->prtype & DATA_MYSQL_TYPE_MASK), (uint)dtype_get_charset_coll(col->prtype), buf, len); + } else { /* new protocol */ + if (!(col->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + switch (col->mtype) { + case DATA_INT: { + byte* ptr = buf+len; + for (;;) { + ptr--; + *ptr = *data; + if (ptr == buf) { + break; + } + data++; + } + + if (!(col->prtype & DATA_UNSIGNED)) { + buf[len-1] = (byte) (buf[len-1] ^ 128); + } + + break; + } + case DATA_VARCHAR: + case DATA_VARMYSQL: + case DATA_BINARY: + /* Copy the actual data */ + ut_memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col->prtype), + buf, len); + break; + case DATA_BLOB: + case DATA_MYSQL: + memcpy(buf, data, len); + break; + default: + break; + } + key_len += len; buf += len; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index a1119fc3d47..4a869cf64b0 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5131,14 +5131,17 @@ wsrep_store_key_val_for_row( wsrep_innobase_mysql_sort( mysql_type, cs->number, sorted, true_len); - /* Note that we always reserve the maximum possible + if (wsrep_protocol_version > 1) { + memcpy(buff, sorted, true_len); + /* Note that we always reserve the maximum possible length of the true VARCHAR in the key value, though only len first bytes after the 2 length bytes contain actual data. The rest of the space was reset to zero in the bzero() call above. */ - - buff += key_len; - + buff += true_len; + } else { + buff += key_len; + } } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB @@ -5205,8 +5208,11 @@ wsrep_store_key_val_for_row( /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ - - buff += key_len; + if (wsrep_protocol_version > 1) { + buff += true_len; + } else { + buff += key_len; + } } else { /* Here we handle all other data types except the true VARCHAR, BLOB and TEXT. Note that the column @@ -7591,20 +7597,24 @@ wsrep_append_foreign_key( key[0] = '\0'; rcode = wsrep_rec_get_primary_key( - &key[1], &len, clust_rec, clust_index); + &key[1], &len, clust_rec, clust_index, + wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { WSREP_ERROR("FK key set failed: %lu", rcode); return rcode; } #ifdef WSREP_DEBUG_PRINT ulint i; - fprintf(stderr, "FK parent key, len: %lu ", len+1); + fprintf(stderr, "FK parent key, table: %s shared: %d len: %lu ", + foreign->referenced_table_name, (int)shared, len+1); for (i=0; iforeign_table->name, 512); + strncpy(cache_key, (wsrep_protocol_version > 1) ? + foreign->referenced_table->name : + foreign->foreign_table->name, 512); char *p = strchr(cache_key, '/'); if (p) { *p = '\0'; diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h index ab390f4fb3a..30ef3048ff1 100644 --- a/storage/xtradb/include/rem0rec.h +++ b/storage/xtradb/include/rem0rec.h @@ -837,7 +837,8 @@ int wsrep_rec_get_primary_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index); /* in: record descriptor */ + dict_index_t* index, /* in: record descriptor */ + ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index dbfc41881ce..15618a3fa02 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -1781,7 +1781,8 @@ wsrep_rec_get_primary_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index) /* in: record descriptor */ + dict_index_t* index, /* in: record descriptor */ + ibool new_protocol) /* in: protocol > 1 */ { const byte* data; ulint len; @@ -1819,7 +1820,7 @@ wsrep_rec_get_primary_key( ut_a(!(col->prtype & DATA_NOT_NULL)); *buf++ = 1; key_len++; - } else { + } else if (!new_protocol) { if (!(col->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; @@ -1829,6 +1830,47 @@ wsrep_rec_get_primary_key( (int)(col->prtype & DATA_MYSQL_TYPE_MASK), (uint)dtype_get_charset_coll(col->prtype), buf, len); + } else { /* new protocol */ + if (!(col->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + switch (col->mtype) { + case DATA_INT: { + byte* ptr = buf+len; + for (;;) { + ptr--; + *ptr = *data; + if (ptr == buf) { + break; + } + data++; + } + + if (!(col->prtype & DATA_UNSIGNED)) { + buf[len-1] = (byte) (buf[len-1] ^ 128); + } + + break; + } + case DATA_VARCHAR: + case DATA_VARMYSQL: + case DATA_BINARY: + /* Copy the actual data */ + ut_memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col->prtype), + buf, len); + break; + case DATA_BLOB: + case DATA_MYSQL: + memcpy(buf, data, len); + break; + default: + break; + } + key_len += len; buf += len; } From f97e67ffaae5c49e207cc6436684d3fbe218ab46 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 13 Jun 2012 00:23:32 +0300 Subject: [PATCH 005/294] References lp:1011983 Merged from codership-mysql/5.5 revision 3758 --- storage/innobase/handler/ha_innodb.cc | 3 ++- storage/xtradb/handler/ha_innodb.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dbcf55e7495..a0b4ec43dad 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7097,7 +7097,8 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(rcode); } } - } else if (wsrep_protocol_version == 0) { + } + if (wsrep_protocol_version == 0) { uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char *key = &keyval[0]; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 82c69b0dc7a..61b14c2358a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -7737,7 +7737,8 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(rcode); } } - } else if (wsrep_protocol_version == 0) { + } + if (wsrep_protocol_version == 0) { uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char *key = &keyval[0]; From 1fd2e10736d6fd198e62054cb9006a3dc13fd55e Mon Sep 17 00:00:00 2001 From: jani Date: Mon, 23 Jul 2012 11:15:59 +0300 Subject: [PATCH 006/294] New version of mysqld_multi. Building Galera tree fully first time in buildbot --- scripts/mysqld_multi.sh | 130 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 13 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 99ce187fcd4..7bf66da99e7 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -38,7 +38,7 @@ use Getopt::Long; use POSIX qw(strftime getcwd); $|=1; -$VER="2.16"; +$VER="2.20"; my @defaults_options; # Leading --no-defaults, --defaults-file, etc. @@ -116,6 +116,7 @@ sub main print "will be disabled\nand some will be enabled.\n\n"; } + init_log() if (!defined($opt_log)); $groupids = $ARGV[1]; if ($opt_version) { @@ -141,7 +142,6 @@ sub main !($ARGV[0] =~ m/^stop$/i) && !($ARGV[0] =~ m/^report$/i))); - init_log() if (!defined($opt_log)); if (!$opt_no_log) { w2log("$my_progname log file version $VER; run: ", @@ -184,9 +184,9 @@ sub main } } -# -# Quote word for shell -# +#### +#### Quote word for shell +#### sub quote_shell_word { @@ -196,6 +196,10 @@ sub quote_shell_word return $option; } +#### +#### get options for a group +#### + sub defaults_for_group { my ($group) = @_; @@ -297,8 +301,12 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); + my (@groups, $com, $com2, $tmp, $i, @options, $j, $mysqld_found, + $info_sent, $curdir, $mysql_install_db, $srcdir, $basedir, + $datadir); + $mysql_install_db= undef(); + $srcdir= undef(); if (!$opt_no_log) { w2log("\nStarting MySQL servers\n","$opt_log",0,0); @@ -312,8 +320,9 @@ sub start_mysqlds() { @options = defaults_for_group($groups[$i]); - $basedir_found= 0; # The default - $mysqld_found= 1; # The default + my $basedir_found= 0; # The default + my $datadir_found= 0; # The default + my $mysqld_found= 1; # The default $mysqld_found= 0 if (!length($mysqld)); $com= "$mysqld"; for ($j = 0, $tmp= ""; defined($options[$j]); $j++) @@ -328,6 +337,47 @@ sub start_mysqlds() $com= $options[$j]; $mysqld_found= 1; } + elsif ("--mysql-install-db=" eq substr($options[$j], 0, 19)) + { + # mysql_install_db related option + + $options[$j]=~ s/\-\-mysql\-install\-db\=//; + $mysql_install_db= $options[$j]; + } + elsif ("--srcdir=" eq substr($options[$j], 0, 9)) + { + # mysql_install_db related option + + $options[$j]=~ s/\-\-srcdir\=//; + $srcdir= $options[$j]; + } + elsif ("--include-config=" eq substr($options[$j], 0, 17)) + { + $options[$j]=~ s/\-\-include\-config\=//; + $com2= "my_print_defaults --config-file=$options[$j] $groups[$i]"; + + # we need to reorder the array so that options in extra config file + # come in the middle. Needed if someone wants to overwrite an option + + my ($k, @tmp_array); + for ($k= $j + 1; defined($options[$k]); $k++) + { + push (@tmp_array, $options[$k]); + undef($options[$k]); + } + pop(@options); # pop out last null array element + push (@options, `$com2`); + chomp(@options); # new lines away + push (@options, @tmp_array); + } + elsif ("--datadir=" eq substr($options[$j], 0, 10)) + { + $datadir= $options[$j]; + $datadir =~ s/^--datadir=//; + $datadir_found= 1; + $options[$j]= quote_shell_word($options[$j]); + $tmp.= " $options[$j]"; + } elsif ("--basedir=" eq substr($options[$j], 0, 10)) { $basedir= $options[$j]; @@ -351,6 +401,25 @@ sub start_mysqlds() print "wanted mysqld binary.\n\n"; $info_sent= 1; } + if (defined($mysql_install_db)) + { + $com2= "$mysql_install_db"; + $com2.= " --srcdir=$srcdir" if (defined($srcdir)); + $com2.= " --datadir=$datadir" if ($datadir_found); + + if (-d "$datadir/mysql") + { + my $wstr= "WARNING: $datadir/mysql already exists. Not going to\n"; + $wstr.= "run $mysql_install_db on $datadir\n"; + print $wstr if ($opt_verbose); + w2log($wstr, 0, 0); + } + else + { + w2log("Installing databases on $datadir..\n", 0, 0); + `$com2`; + } + } $com.= $tmp; $com.= " >> $opt_log 2>&1" if (!$opt_no_log); $com.= " &"; @@ -420,7 +489,7 @@ sub stop_mysqlds() sub get_mysqladmin_options { my ($i, @groups)= @_; - my ($mysqladmin_found, $com, $tmp, $j); + my ($mysqladmin_found, $com, $com2, $tmp, $j); @options = defaults_for_group($groups[$i]); @@ -443,6 +512,25 @@ sub get_mysqladmin_options $com= $options[$j]; $mysqladmin_found= 1; } + elsif ("--include-config=" eq substr($options[$j], 0, 17)) + { + $options[$j]=~ s/\-\-include\-config\=//; + $com2= "my_print_defaults --config-file=$options[$j] $groups[$i]"; + + # we need to reorder the array so that options in extra config file + # come in the middle. Needed if someone wants to overwrite an option + + my ($k, @tmp_array); + for ($k= $j + 1; defined($options[$k]); $k++) + { + push (@tmp_array, $options[$k]); + undef($options[$k]); + } + pop(@options); # pop out last null array element + push (@options, `$com2`); + chomp(@options); # new lines away + push (@options, @tmp_array); + } elsif ((($options[$j] =~ m/^(\-\-socket\=)(.*)$/) && !$opt_tcp_ip) || ($options[$j] =~ m/^(\-\-port\=)(.*)$/)) { @@ -462,8 +550,11 @@ sub get_mysqladmin_options return $com; } -# Return a list of option files which can be opened. Similar, but not -# identical, to behavior of my_search_option_files() +#### +#### Return a list of option files which can be opened. Similar, but not +#### identical, to behavior of my_search_option_files() +#### + sub list_defaults_files { my %opt; @@ -485,9 +576,11 @@ sub list_defaults_files ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); } +#### +#### Takes a specification of GNRs (see --help), and returns a list of matching +#### groups which actually are mentioned in a relevant config file +#### -# Takes a specification of GNRs (see --help), and returns a list of matching -# groups which actually are mentioned in a relevant config file sub find_groups { my ($raw_gids) = @_; @@ -802,6 +895,17 @@ Using: @{[join ' ', @defaults_options]} question. This will be recognised as a special option and will not be passed to the mysqld. This will allow one to start different mysqld versions with mysqld_multi. +--include-config= An optional config file inside a group [mysqld#] which + the program is currently reading. It will read any extra + options of that group from additional file and insert them + where this option was found. Note that the group name + [mysqld#] must be the same in order for options to be found. +--mysql-install-db=... + mysql_install_db script to be used for creating internal + databases. Used when installing datadir for the first time. + This option will be skipped with info in the log file if + 'mysql' database already exists in the given datadir. +--srcdir=... srcdir argument for mysql_install_db script. Optional. --no-log Print to stdout instead of the log file. By default the log file is turned on. --password=... Password for mysqladmin user. From 8e84b9e740ff3641f1fc500a616962cb3bc75a64 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 30 Aug 2012 12:22:37 +0300 Subject: [PATCH 007/294] Merged in change sets 3772-3779 from lp:codership-mysql/5.5 --- Docs/README-wsrep | 11 +++- cmake/wsrep.cmake | 2 +- scripts/wsrep_sst_rsync.sh | 8 +-- sql/mysqld.cc | 2 +- sql/sql_class.cc | 2 + sql/sql_class.h | 1 + sql/sql_parse.cc | 2 +- sql/wsrep_mysqld.cc | 103 +++++++++++++++++++++------------ sql/wsrep_mysqld.h | 3 +- sql/wsrep_priv.h | 6 +- sql/wsrep_sst.cc | 13 ++--- sql/wsrep_utils.cc | 103 +++++++++++++++++++-------------- sql/wsrep_var.cc | 29 ++++++---- storage/innobase/row/row0ins.c | 30 ++-------- storage/xtradb/row/row0ins.c | 30 ++-------- 15 files changed, 186 insertions(+), 159 deletions(-) diff --git a/Docs/README-wsrep b/Docs/README-wsrep index ea6a62621ed..78934811984 100644 --- a/Docs/README-wsrep +++ b/Docs/README-wsrep @@ -236,7 +236,7 @@ mysql> SHOW STATUS LIKE 'wsrep%'; - If performing a rolling upgrade on a running cluster, set wsrep_sst_method=mysqldump. You might also need to configure wsrep_sst_receive_address and - wsrep_sst_auth appropriately. Mysqldump is the only way to transfer data + wsrep_sst_auth appropriately. mysqldump is the only way to transfer data from 5.1.x to 5.5.x reliably. - remove innodb_plugin settings from configuration files. @@ -292,6 +292,15 @@ wsrep_cluster_address= wsrep_cluster_name="my_wsrep_cluster" Logical cluster name, must be the same for all nodes of the cluster. +wsrep_node_address= + An option to explicitly specify the network address of the node in the form +
[:port] if autoguessing for some reason does not produce desirable + results (multiple network interfaces, NAT, etc.) + If not explicitly overridden by wsrep_sst_receive_address, the
part + will be used to listen for SST (see below). And the whole
[:port] + will be passed to wsrep provider to be used as a base address in its + communications. + wsrep_node_name= Human readable node name (for easier log reading only). Defaults to hostname. diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 3c10c5b3836..bb646028285 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "6") +SET(WSREP_PATCH_VERSION "7") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index c0b54159eda..ef3dda8231f 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -23,14 +23,14 @@ RSYNC_CONF= cleanup_joiner() { - echo "Joiner cleanup:" >&2 -set -x + echo -n "Joiner rsync SST cleanup..." >&2 local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) - [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID || : -set +x + [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \ + || : rm -rf "$RSYNC_CONF" rm -rf "$MAGIC_FILE" rm -rf "$RSYNC_PID" + echo " done." >&2 } check_pid() diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dfdf1c41c0f..c4ed7c1e31b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5080,7 +5080,7 @@ void wsrep_wait_appliers_close(THD *thd) /* and wait for them to die */ mysql_mutex_lock(&LOCK_thread_count); while (have_wsrep_appliers(thd) > 0) - { + { mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 99d54e437d2..795e1524390 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1005,6 +1005,7 @@ THD::THD() wsrep_retry_query_len = 0; wsrep_retry_command = COM_CONNECT; wsrep_consistency_check = NO_CONSISTENCY_CHECK; + wsrep_status_vars = 0; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1557,6 +1558,7 @@ THD::~THD() mysql_mutex_unlock(&LOCK_wsrep_thd); mysql_mutex_destroy(&LOCK_wsrep_thd); if (wsrep_rli) delete wsrep_rli; + if (wsrep_status_vars) wsrep->stats_free(wsrep, wsrep_status_vars); #endif /* Close connection */ #ifndef EMBEDDED_LIBRARY diff --git a/sql/sql_class.h b/sql/sql_class.h index 844f56fac6f..e2c528ab05f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2400,6 +2400,7 @@ public: enum enum_server_command wsrep_retry_command; enum wsrep_consistency_check_mode wsrep_consistency_check; + wsrep_stats_var* wsrep_status_vars; #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0ca412be17d..fbb47b5c03b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2535,7 +2535,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STATUS: { #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); #endif /* WITH_WSREP */ execute_show_status(thd, all_tables); break; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a5d7134a201..8627d0ff53b 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -54,7 +54,7 @@ my_bool wsrep_replicate_myisam = 0; // enable myisam replication * End configuration options */ -static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; +static const wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; const wsrep_uuid_t* wsrep_cluster_uuid() { return &cluster_uuid; @@ -120,11 +120,11 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { } } -static void wsrep_log_states (wsrep_log_level_t level, - wsrep_uuid_t* group_uuid, - wsrep_seqno_t group_seqno, - wsrep_uuid_t* node_uuid, - wsrep_seqno_t node_seqno) +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]; @@ -195,7 +195,7 @@ static void wsrep_view_handler_cb (void* app_ctx, if (memcmp(&cluster_uuid, &view->uuid, sizeof(wsrep_uuid_t))) { - cluster_uuid= view->uuid; + memcpy((wsrep_uuid_t*)&cluster_uuid, &view->uuid, sizeof(cluster_uuid)); wsrep_uuid_print (&cluster_uuid, cluster_uuid_str, sizeof(cluster_uuid_str)); } @@ -213,7 +213,7 @@ static void wsrep_view_handler_cb (void* app_ctx, /* Proceed further only if view is PRIMARY */ if (WSREP_VIEW_PRIMARY != view->status) { - wsrep_ready= FALSE; + wsrep_ready_set(FALSE); new_status= WSREP_MEMBER_UNDEFINED; /* Always record local_uuid and local_seqno in non-prim since this * may lead to re-initializing provider and start position is @@ -234,13 +234,13 @@ static void wsrep_view_handler_cb (void* app_ctx, if (view->proto_ver != wsrep_protocol_version) { my_bool wsrep_ready_saved= wsrep_ready; - wsrep_ready= FALSE; + 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= wsrep_ready_saved; + wsrep_ready_set(wsrep_ready_saved); } break; default: @@ -255,7 +255,7 @@ static void wsrep_view_handler_cb (void* app_ctx, /* After that wsrep will call wsrep_sst_prepare. */ /* keep ready flag 0 until we receive the snapshot */ - wsrep_ready= FALSE; + wsrep_ready_set(FALSE); /* Close client connections to ensure that they don't interfere * with SST */ @@ -411,7 +411,7 @@ int wsrep_init() { int rcode= -1; - wsrep_ready= FALSE; + wsrep_ready_set(FALSE); assert(wsrep_provider); wsrep_init_position(); @@ -438,8 +438,9 @@ int wsrep_init() !strcmp(wsrep_provider, WSREP_NONE)) { // enable normal operation in case no provider is specified - wsrep_ready= TRUE; + wsrep_ready_set(TRUE); global_system_variables.wsrep_on = 0; + return 0; } else { @@ -452,41 +453,69 @@ int wsrep_init() wsrep->provider_vendor, sizeof(provider_vendor) - 1); } - struct wsrep_init_args wsrep_args; - if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) wsrep_data_home_dir = mysql_real_data_home; - if (strcmp (wsrep_provider, WSREP_NONE) && - (!wsrep_node_incoming_address || - !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { - static char inc_addr[256]; - size_t inc_addr_max = sizeof (inc_addr); - size_t ret = default_address (inc_addr, inc_addr_max); - if (ret > 0 && ret < inc_addr_max) { - wsrep_node_incoming_address = inc_addr; - } - else { - wsrep_node_incoming_address = NULL; - } - } - - char node_addr[256] = {0, }; + char node_addr[512]= { 0, }; if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) { - size_t node_addr_max= sizeof(node_addr); - size_t ret= default_ip(node_addr, node_addr_max); + size_t const node_addr_max= sizeof(node_addr); + size_t const ret= guess_ip(node_addr, node_addr_max); if (!(ret > 0 && ret < node_addr_max)) { - WSREP_WARN("Failed to autoguess base node address"); - node_addr[0]= 0; + WSREP_WARN("Failed to guess base node address. Set it explicitly via " + "wsrep_node_address."); + node_addr[0]= '\0'; } } - else if (wsrep_node_address) + else { strncpy(node_addr, wsrep_node_address, sizeof(node_addr) - 1); } + static char inc_addr[512]= { 0, }; + if ((!wsrep_node_incoming_address || + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + size_t const node_addr_len= strlen(node_addr); + if (node_addr_len > 0) + { + const char* const colon= strrchr(node_addr, ':'); + if (strchr(node_addr, ':') == colon) // 1 or 0 ':' + { + size_t const inc_addr_max= sizeof (inc_addr); + size_t const ip_len= colon ? colon - node_addr : node_addr_len; + if (ip_len + 7 /* :55555\0 */ < inc_addr_max) + { + memcpy (inc_addr, node_addr, ip_len); + snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",mysqld_port); + } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "address too long."); + inc_addr[0]= '\0'; + } + } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "too many colons :) ."); + inc_addr[0]= '\0'; + } + } + + // this is to display detected address on SHOW VARIABLES... + wsrep_node_incoming_address = inc_addr; + + if (!strlen(wsrep_node_incoming_address)) + { + WSREP_WARN("Guessing address for incoming client connections failed. " + "Try setting wsrep_node_incoming_address explicitly."); + } + } + + struct wsrep_init_args wsrep_args; + wsrep_args.data_dir = wsrep_data_home_dir; wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; wsrep_args.node_address = node_addr; @@ -599,14 +628,14 @@ bool wsrep_start_replication() !strcmp(wsrep_provider, WSREP_NONE)) { // enable normal operation in case no provider is specified - wsrep_ready = TRUE; + wsrep_ready_set(TRUE); return true; } if (!wsrep_cluster_address || strlen(wsrep_cluster_address)== 0) { // if provider is non-trivial, but no address is specified, wait for address - wsrep_ready = FALSE; + wsrep_ready_set(FALSE); return true; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 968281a2c98..ce74cef4e64 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -18,10 +18,8 @@ #include "mysqld.h" typedef struct st_mysql_show_var SHOW_VAR; -//#include #include #include "../wsrep/wsrep_api.h" -//#include class set_var; class THD; @@ -77,6 +75,7 @@ extern const char* wsrep_provider_name; extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); +extern void wsrep_free_status(THD *thd); #define WSREP_SST_ADDRESS_AUTO "AUTO" // MySQL variables funcs diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h index 32d0cebfd33..700639ebcb1 100644 --- a/sql/wsrep_priv.h +++ b/sql/wsrep_priv.h @@ -37,14 +37,14 @@ extern int wsrep_sst_donate_cb (void* app_ctx, const char* state, size_t state_len, bool bypass); -extern size_t default_ip (char* buf, size_t buf_len); -extern size_t default_address(char* buf, size_t buf_len); +extern size_t guess_ip (char* buf, size_t buf_len); +extern size_t guess_address(char* buf, size_t buf_len); extern wsrep_uuid_t local_uuid; extern wsrep_seqno_t local_seqno; /*! SST thread signals init thread about sst completion */ -extern void wsrep_sst_complete(wsrep_uuid_t* uuid, wsrep_seqno_t seqno, bool); +extern void wsrep_sst_complete(const wsrep_uuid_t* uuid, wsrep_seqno_t, bool); extern void wsrep_notify_status (wsrep_member_status_t new_status, const wsrep_view_info_t* view = 0); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index df39db3caa4..8beadeb2ff2 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -202,7 +202,7 @@ bool wsrep_sst_wait () } // Signal end of SST -void wsrep_sst_complete (wsrep_uuid_t* sst_uuid, +void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, wsrep_seqno_t sst_seqno, bool needed) { @@ -242,8 +242,7 @@ struct sst_thread_arg sst_thread_arg (const char* c) : cmd(c), err(-1), ret_str(0) { - mysql_mutex_init(key_LOCK_wsrep_sst_thread, - &lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_sst_thread, &lock, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL); } @@ -382,8 +381,8 @@ static ssize_t sst_prepare_other (const char* method, const char* sst_dir= mysql_real_data_home; int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s 'joiner' '%s' '%s' '%s' '%s' '%d' 2>sst.err", - method, addr_in, (sst_auth_real) ? sst_auth_real : "", + "wsrep_sst_%s 'joiner' '%s' '%s' '%s' '%s' '%d'", + method, addr_in, (sst_auth_real) ? sst_auth_real : "", sst_dir, wsrep_defaults_file, (int)getpid()); if (ret < 0 || ret >= cmd_len) @@ -416,7 +415,7 @@ static ssize_t sst_prepare_other (const char* method, //extern ulong my_bind_addr; extern uint mysqld_port; -/*! Just tells donor where ti sent mysqldump */ +/*! Just tells donor where to send mysqldump */ static ssize_t sst_prepare_mysqldump (const char* addr_in, const char** addr_out) { @@ -497,7 +496,7 @@ ssize_t wsrep_sst_prepare (void** msg) } else { - ssize_t ret= default_ip (ip_buf, ip_max); + ssize_t ret= guess_ip (ip_buf, ip_max); if (ret && ret < ip_max) { diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 00919b3163e..b1bd6de07cf 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -316,7 +316,7 @@ thd::~thd () extern ulong my_bind_addr; extern uint mysqld_port; -size_t default_ip (char* buf, size_t buf_len) +size_t guess_ip (char* buf, size_t buf_len) { size_t ip_len = 0; @@ -325,64 +325,83 @@ size_t default_ip (char* buf, size_t buf_len) return 0; } - if (htonl(INADDR_ANY) == my_bind_addr) { - // binds to all interfaces, try to find the address of the first one -#if (TARGET_OS_LINUX == 1) - const char cmd[] = "/sbin/ifconfig | " - "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "awk '{ print $2 }' | awk -F : '{ print $2 }'"; -#elif defined(__sun__) - const char cmd[] = "/sbin/ifconfig -a | " - "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; -#else - char *cmd; -#error "OS not supported" -#endif - wsp::process proc (cmd, "r"); + if (htonl(INADDR_ANY) != my_bind_addr) { + uint8_t* b = (uint8_t*)&my_bind_addr; + ip_len = snprintf (buf, buf_len, + "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); + return ip_len; + } - if (NULL != proc.pipe()) { - char* ret; + // mysqld binds to all interfaces - try IP from wsrep_node_address + if (wsrep_node_address && wsrep_node_address[0] != '\0') { + const char* const colon_ptr = strchr(wsrep_node_address, ':'); - ret = fgets (buf, buf_len, proc.pipe()); + if (colon_ptr) + ip_len = colon_ptr - wsrep_node_address; + else + ip_len = strlen(wsrep_node_address); - if (proc.wait()) return 0; - - if (NULL == ret) { - WSREP_ERROR("Failed to read output of: '%s'", cmd); - return 0; - } - } - else { - WSREP_ERROR("Failed to execute: '%s'", cmd); + if (ip_len >= buf_len) { + WSREP_WARN("default_ip(): buffer too short: %zu <= %zd", buf_len, ip_len); return 0; } - // clear possible \n at the end of ip string left by fgets() - ip_len = strlen (buf); - if (ip_len > 0 && '\n' == buf[ip_len - 1]) { - ip_len--; - buf[ip_len] = '\0'; - } + memcpy (buf, wsrep_node_address, ip_len); + buf[ip_len] = '\0'; + return ip_len; + } - if (INADDR_NONE == inet_addr(buf)) { - if (strlen(buf) != 0) { - WSREP_WARN("Shell command returned invalid address: '%s'", buf); - } + // try to find the address of the first one +#if (TARGET_OS_LINUX == 1) + const char cmd[] = "/sbin/ifconfig | " + "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +#elif defined(__sun__) + const char cmd[] = "/sbin/ifconfig -a | " + "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; +#else + char *cmd; +#error "OS not supported" +#endif + wsp::process proc (cmd, "r"); + + if (NULL != proc.pipe()) { + char* ret; + + ret = fgets (buf, buf_len, proc.pipe()); + + if (proc.wait()) return 0; + + if (NULL == ret) { + WSREP_ERROR("Failed to read output of: '%s'", cmd); return 0; } } else { - uint8_t* b = (uint8_t*)&my_bind_addr; - ip_len = snprintf (buf, buf_len, - "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); + WSREP_ERROR("Failed to execute: '%s'", cmd); + return 0; + } + + // clear possible \n at the end of ip string left by fgets() + ip_len = strlen (buf); + if (ip_len > 0 && '\n' == buf[ip_len - 1]) { + ip_len--; + buf[ip_len] = '\0'; + } + + if (INADDR_NONE == inet_addr(buf)) { + if (strlen(buf) != 0) { + WSREP_WARN("Shell command returned invalid address: '%s'", buf); + } + return 0; } return ip_len; } -size_t default_address(char* buf, size_t buf_len) +size_t guess_address(char* buf, size_t buf_len) { - size_t addr_len = default_ip (buf, buf_len); + size_t addr_len = guess_ip (buf, buf_len); if (addr_len && addr_len < buf_len) { addr_len += snprintf (buf + addr_len, buf_len - addr_len, diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index fb5c3b339cd..3136f905109 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -464,31 +464,27 @@ wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep) } } -static wsrep_stats_var* wsrep_status_vars = NULL; - #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[100 + 1]; -static const int mysql_status_len = 100; +static SHOW_VAR mysql_status_vars[512 + 1]; +static const int mysql_status_len = 512; #endif -static void export_wsrep_status_to_mysql() +static void export_wsrep_status_to_mysql(THD* thd) { int wsrep_status_len, i; - if (wsrep_status_vars) wsrep->stats_free (wsrep, wsrep_status_vars); + thd->wsrep_status_vars = wsrep->stats_get(wsrep); - wsrep_status_vars = wsrep->stats_get (wsrep); - - if (!wsrep_status_vars) { + if (!thd->wsrep_status_vars) { return; } for (wsrep_status_len = 0; - wsrep_status_vars[wsrep_status_len].name != NULL; + thd->wsrep_status_vars[wsrep_status_len].name != NULL; wsrep_status_len++); #if DYNAMIC @@ -511,7 +507,7 @@ static void export_wsrep_status_to_mysql() #endif for (i = 0; i < wsrep_status_len; i++) - wsrep_assign_to_mysql (mysql_status_vars + i, wsrep_status_vars + i); + wsrep_assign_to_mysql (mysql_status_vars + i, thd->wsrep_status_vars + i); mysql_status_vars[wsrep_status_len].name = NullS; mysql_status_vars[wsrep_status_len].value = NullS; @@ -520,8 +516,17 @@ static void export_wsrep_status_to_mysql() int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) { - export_wsrep_status_to_mysql(); + export_wsrep_status_to_mysql(thd); var->type= SHOW_ARRAY; var->value= (char *) &mysql_status_vars; return 0; } + +void wsrep_free_status (THD* thd) +{ + if (thd->wsrep_status_vars) + { + wsrep->stats_free (wsrep, thd->wsrep_status_vars); + thd->wsrep_status_vars = 0; + } +} diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index d7823c140bf..7164295098c 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1423,22 +1423,12 @@ run_again: if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP - if (thr->fk_cascade_depth == 0) { - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - check_ref, TRUE); - } else { - fprintf(stderr, "WSREP: skipping FK key append\n"); - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - TRUE, TRUE); - } + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + check_ref, TRUE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { @@ -1469,14 +1459,6 @@ run_again: goto end_scan; } -#ifdef WITH_WSREP_REMOVED - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - FALSE); -#endif /* WITH_WSREP */ /* row_ins_foreign_check_on_constraint may have repositioned pcur on a different block */ diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 9fbb5122a82..67b94315772 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1429,22 +1429,12 @@ run_again: if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP - if (thr->fk_cascade_depth == 0) { - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - check_ref, TRUE); - } else { - fprintf(stderr, "WSREP: skipping FK key append\n"); - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - TRUE, TRUE); - } + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + check_ref, TRUE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { @@ -1475,14 +1465,6 @@ run_again: goto end_scan; } -#ifdef WITH_WSREP_REMOVED - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - check_index, - FALSE); -#endif /* WITH_WSREP */ /* row_ins_foreign_check_on_constraint may have repositioned pcur on a different block */ From 02abef584c607667395bbfc3686b7c7063f57206 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 4 Sep 2012 22:13:46 +0200 Subject: [PATCH 008/294] Fixes for galera build - compile with WITH_WSREP on - fix package name --- cmake/package_name.cmake | 2 +- cmake/wsrep.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index 5c99a110e7c..37f619e7177 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -120,7 +120,7 @@ IF(NOT VERSION) ELSEIF(MYSQL_SERVER_SUFFIX) SET(PRODUCT_TAG "${MYSQL_SERVER_SUFFIX}") # Already has a leading dash ELSE() - SET(PRODUCT_TAG) + SET(PRODUCT_TAG "-galera") ENDIF() IF("${VERSION}" MATCHES "-ndb-") diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index bb646028285..5bfc39c66e6 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -47,7 +47,7 @@ SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" ) -OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" OFF) +OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ON) IF (WITH_WSREP) SET(WSREP_C_FLAGS "-DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") From 5f76c15a3b5c4f39370fe21764088ee88dab9f47 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 8 Sep 2012 09:51:16 +0200 Subject: [PATCH 009/294] MDEV-507 deb/rpm packages for galera builds rpm part. --- cmake/cpack_rpm.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index e915e732612..72ceb0816b8 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -27,7 +27,7 @@ SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts ManPagesTest Readme ManPagesClient Test Common Client SharedLibraries) -SET(CPACK_RPM_PACKAGE_NAME "MariaDB") +SET(CPACK_RPM_PACKAGE_NAME "MariaDB-Galera") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") SET(CPACK_RPM_PACKAGE_RELEASE 1) # FIX: add distribution name here @@ -81,6 +81,7 @@ SET(CPACK_RPM_devel_PACKAGE_PROVIDES "MariaDB-devel MySQL-devel mysql-devel") SET(CPACK_RPM_server_PACKAGE_OBSOLETES "MariaDB mysql mysql-server MySQL-server MySQL-OurDelta-server") SET(CPACK_RPM_server_PACKAGE_PROVIDES "MariaDB MariaDB-server MySQL-server config(MariaDB-server) msqlormysql mysql mysql-server") +SET(CPACK_RPM_server_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES} galera") SET(CPACK_RPM_server_PRE_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-prein.sh) SET(CPACK_RPM_server_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-preun.sh) SET(CPACK_RPM_server_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-postin.sh) @@ -118,7 +119,7 @@ IF (compat_rpm) # Make sure that for these distribuions all our rpms require # MariaDB-compat, that will replace mysql-libs-5.1 IF(RPM MATCHES "(rhel|centos)6") - SET(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-compat") + SET(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-Galera-compat") ENDIF() ENDIF(compat_rpm) From 0892c7ec5d7bbca00e042047c4220e6830491c37 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 17 Sep 2012 11:34:57 +0300 Subject: [PATCH 010/294] References lp:1051808 - merged with lp:codership-mysql 5.5.27 based trunk patched with: bzr diff lp:codership-mysql/5.5 -r3779..3790 --- .bzrignore | 5 + Docs/README-wsrep | 18 ++- scripts/CMakeLists.txt | 2 +- scripts/mysqld_safe.sh | 34 +++- scripts/wsrep_sst_common.sh | 106 ++++++++++++ scripts/wsrep_sst_mysqldump.sh | 52 +++--- scripts/wsrep_sst_rsync.sh | 48 +++--- scripts/wsrep_sst_xtrabackup.sh | 222 ++++++++++++++++++++++++++ sql/handler.cc | 4 +- sql/mysqld.cc | 49 ++++++ sql/sql_parse.cc | 6 +- sql/wsrep_mysqld.cc | 38 ++++- sql/wsrep_mysqld.h | 3 +- sql/wsrep_sst.cc | 98 ++++++++---- storage/innobase/handler/ha_innodb.cc | 5 +- support-files/mysql.spec.sh | 11 +- support-files/wsrep.cnf.sh | 3 +- 17 files changed, 598 insertions(+), 106 deletions(-) create mode 100644 scripts/wsrep_sst_common.sh create mode 100644 scripts/wsrep_sst_xtrabackup.sh diff --git a/.bzrignore b/.bzrignore index 409b6148125..943c9bf8c50 100644 --- a/.bzrignore +++ b/.bzrignore @@ -969,6 +969,8 @@ support-files/mysql.server support-files/mysql.spec support-files/mysqld_multi.server support-files/ndb-config-2-node.ini +support-files/wsrep.cnf +support-files/wsrep_notify TAGS test/ndbapi/bank/bankCreator test/ndbapi/bank/bankMakeGL @@ -1092,6 +1094,9 @@ sql/share/slovak sql/share/spanish sql/share/swedish sql/share/ukrainian +scripts/wsrep_sst_mysqldump +scripts/wsrep_sst_rsync +scripts/wsrep_sst_xtrabackup CPackConfig.cmake CPackSourceConfig.cmake Docs/INFO_BIN diff --git a/Docs/README-wsrep b/Docs/README-wsrep index 78934811984..025379764b2 100644 --- a/Docs/README-wsrep +++ b/Docs/README-wsrep @@ -137,6 +137,7 @@ Additional packages to consider (if not yet installed): * galera (multi-master replication provider, https://launchpad.net/galera) * MySQL-client-community (for connecting to server and mysqldump-based SST) * rsync (for rsync-based SST) + * xtrabackup and nc (for xtrabackup-based SST) 2.2 Upgrade system tables. @@ -379,9 +380,20 @@ to join or start a cluster. wsrep_sst_method=mysqldump What method to use to copy database state to a newly joined node. Supported methods: - - mysqldump: slow (except for small datasets) but most tested. - - rsync: much faster on large datasets. - - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. + - mysqldump: slow (except for small datasets) but most tested. + - rsync: much faster on large datasets. + - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. + - xtrabackup: very fast and practically non-blocking SST method based on + Percona's xtrabackup tool. + + (for xtrabackup to work the following settings must be present in my.cnf + on all nodes: + [mysqld] + wsrep_sst_auth=root: + datadir= + [client] + socket= + ) wsrep_sst_receive_address= Address (hostname:port) at which this node wants to receive state snapshot. diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 5576f32e0c4..b7559b2358d 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -311,7 +311,7 @@ IF(WIN32) ENDFOREACH() ELSE() IF(WITH_WSREP) - SET(WSREP_BINARIES wsrep_sst_mysqldump wsrep_sst_rsync) + SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup) ENDIF() # On Unix, most of the files end up in the bin directory SET(mysql_config_COMPONENT COMPONENT Development) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 5a390a32f26..72430cd19f6 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -190,6 +190,31 @@ wsrep_pick_url() { echo $url } +# Run mysqld with --wsrep-recover and parse recovered position from log. +# Position will be stored in wsrep_start_position_opt global. +wsrep_recovery() { + cmd="$@" + wr_logfile=$(mktemp) + log_notice "WSREP: Running position recovery" + $cmd --log_error=$wr_logfile --wsrep-recover + rp=$(grep "WSREP: Recovered position:" $wr_logfile) + if [ -z "$rp" ]; then + skipped=$(grep WSREP $wr_logfile | grep "skipping position recovery") + if [ -z "$skipped" ]; then + log_error "WSREP: Failed to recover position: " \ + `cat $wr_logfile`; + else + log_notice "WSREP: Position recovery skipped" + fi + else + start_pos=$(echo $rp | sed 's/.*WSREP\:\ Recovered\ position://' \ + | sed 's/^[ \t]*//') + wsrep_start_position_opt="--wsrep_start_position=$start_pos" + log_notice "WSREP: Recovered position $start_pos" + fi + rm $wr_logfile +} + parse_arguments() { # We only need to pass arguments through to the server if we don't # handle them here. So, we collect unrecognized options (passed on @@ -787,7 +812,8 @@ do done cmd="$cmd $args" # Avoid 'nohup: ignoring input' warning -test -n "$NOHUP_NICENESS" && cmd="$cmd < /dev/null" +nohup_redir="" +test -n "$NOHUP_NICENESS" && nohup_redir=" < /dev/null" log_notice "Starting $MYSQLD daemon with databases from $DATADIR" @@ -808,9 +834,11 @@ do if [ -z "$url" ] then - eval_log_error "$cmd" + wsrep_recovery "$cmd" + eval_log_error "$cmd $wsrep_start_position_opt $nohup_redir" else - eval_log_error "$cmd --wsrep_cluster_address=$url" + wsrep_recovery "$cmd" + eval_log_error "$cmd $wsrep_start_position_opt --wsrep_cluster_address=$url $nohup_redir" fi end_time=`date +%M%S` diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh new file mode 100644 index 00000000000..a3ad90769e9 --- /dev/null +++ b/scripts/wsrep_sst_common.sh @@ -0,0 +1,106 @@ +# Copyright (C) 2010 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a common command line parser to be sourced by other SST scripts + +set -u + +WSREP_SST_OPT_BYPASS=0 + +while [ $# -gt 0 ]; do +case "$1" in + '--address') + readonly WSREP_SST_OPT_ADDR="$2" + shift + ;; + '--auth') + readonly WSREP_SST_OPT_AUTH="$2" + shift + ;; + '--bypass') + WSREP_SST_OPT_BYPASS=1 + ;; + '--datadir') + readonly WSREP_SST_OPT_DATA="$2" + shift + ;; + '--defaults-file') + readonly WSREP_SST_OPT_CONF="$2" + shift + ;; + '--host') + readonly WSREP_SST_OPT_HOST="$2" + shift + ;; + '--local-port') + readonly WSREP_SST_OPT_LPORT="$2" + shift + ;; + '--parent') + readonly WSREP_SST_OPT_PARENT="$2" + shift + ;; + '--password') + readonly WSREP_SST_OPT_PSWD="$2" + shift + ;; + '--port') + readonly WSREP_SST_OPT_PORT="$2" + shift + ;; + '--role') + readonly WSREP_SST_OPT_ROLE="$2" + shift + ;; + '--socket') + readonly WSREP_SST_OPT_SOCKET="$2" + shift + ;; + '--user') + readonly WSREP_SST_OPT_USER="$2" + shift + ;; + '--gtid') + readonly WSREP_SST_OPT_GTID="$2" + shift + ;; + *) # must be command + # usage + # exit 1 + ;; +esac +shift +done +readonly WSREP_SST_OPT_BYPASS + +wsrep_log() +{ + # echo everything to stderr so that it gets into common error log + # deliberately made to look different from the rest of the log + local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" + echo "WSREP_SST: $* ($tst)" >/dev/stderr +} + +wsrep_log_error() +{ + wsrep_log "[ERROR] $*" +} + +wsrep_log_info() +{ + wsrep_log "[INFO] $*" +} + diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 8106850e918..120533edc4e 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -17,23 +17,10 @@ # This is a reference script for mysqldump-based state snapshot tansfer -USER=$1 -PSWD=$2 -HOST=$3 -PORT=$4 -LOCAL_HOST="127.0.0.1" -LOCAL_PORT=$5 -UUID=$6 -SEQNO=$7 -BYPASS=$8 +. $(dirname $0)/wsrep_sst_common EINVAL=22 -err() -{ - echo "SST error: $*" >&2 -} - local_ip() { PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin @@ -51,16 +38,18 @@ local_ip() return 1 } -if test -z "$USER"; then err "USER cannot be nil"; exit $EINVAL; fi -if test -z "$HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi -if test -z "$PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi -if test -z "$LOCAL_PORT"; then err "LOCAL_PORT cannot be nil"; exit $EINVAL; fi -if test -z "$UUID"; then err "UUID cannot be nil"; exit $EINVAL; fi -if test -z "$SEQNO"; then err "SEQNO cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_USER"; then err "USER cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_LPORT"; then err "LPORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_SOCKET";then err "SOCKET cannot be nil";exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_GTID"; then err "GTID cannot be nil"; exit $EINVAL; fi -if local_ip $HOST && [ "$PORT" = "$LOCAL_PORT" ] +if local_ip $WSREP_SST_OPT_HOST && \ + [ "$WSREP_SST_OPT_PORT" = "$WSREP_SST_OPT_LPORT" ] then - err "destination address '$HOST:$PORT' matches source address." + wsrep_log_error \ + "destination address '$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT' matches source address." exit $EINVAL fi @@ -68,18 +57,17 @@ fi if ! mysql --version | grep 'Distrib 5.5' >/dev/null then mysql --version >&2 - err "this procedure requires MySQL client version 5.5.x" + err "this operation requires MySQL client version 5.5.x" exit $EINVAL fi -AUTH="-u$USER" -if test -n "$PSWD"; then AUTH="$AUTH -p$PSWD"; fi +AUTH="-u$WSREP_SST_OPT_USER" +if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi STOP_WSREP="SET wsrep_on=OFF;" # NOTE: we don't use --routines here because we're dumping mysql.proc table -#MYSQLDUMP="@bindir@/mysqldump $AUTH -h$LOCAL_HOST -P$LOCAL_PORT \ -MYSQLDUMP="mysqldump $AUTH -h$LOCAL_HOST -P$LOCAL_PORT \ +MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ --add-drop-database --add-drop-table --skip-add-locks --create-options \ --disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ --skip-comments --flush-privileges --all-databases" @@ -102,10 +90,10 @@ PREPARE stmt FROM @str; EXECUTE stmt; DROP PREPARE stmt;" -SET_START_POSITION="SET GLOBAL wsrep_start_position='$UUID:$SEQNO';" +SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" -#MYSQL="@bindir@/mysql -u'$USER' -p'$PSWD' -h'$HOST' -P'$PORT'" -MYSQL="mysql $AUTH -h$HOST -P$PORT --disable-reconnect --connect_timeout=10" +MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ +"--disable-reconnect --connect_timeout=10" # need to disable logging when loading the dump # reason is that dump contains ALTER TABLE for log tables, and @@ -119,14 +107,14 @@ $MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF" RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" -if [ $BYPASS -eq 0 ] +if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then (echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX \ && echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG \ && echo $SET_START_POSITION \ || echo "SST failed to complete;") | $MYSQL else - echo "Bypassing state dump." >&2 + wsrep_log_info "Bypassing state dump." echo $SET_START_POSITION | $MYSQL fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index ef3dda8231f..d346eb240f2 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -21,9 +21,11 @@ RSYNC_PID= RSYNC_CONF= +. $(dirname $0)/wsrep_sst_common + cleanup_joiner() { - echo -n "Joiner rsync SST cleanup..." >&2 + wsrep_log_info "Joiner cleanup." local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \ || : @@ -50,25 +52,16 @@ check_pid_and_port() grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null } -ROLE=$1 -ADDR=$2 -AUTH=$3 -DATA=$4 -CONF=$5 - -MAGIC_FILE="$DATA/rsync_sst_complete" +MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" rm -rf "$MAGIC_FILE" -if [ "$ROLE" = "donor" ] +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then - UUID=$6 - SEQNO=$7 - BYPASS=$8 - if [ $BYPASS -eq 0 ] + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then - FLUSHED="$DATA/tables_flushed" + FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" rm -rf "$FLUSHED" # Use deltaxfer only for WAN @@ -100,7 +93,8 @@ then RC=0 rsync --archive --no-times --ignore-times --inplace --delete --quiet \ - $WHOLE_FILE_OPT "${FILTER[@]}" "$DATA" rsync://$ADDR || RC=$? + $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA" \ + rsync://$WSREP_SST_OPT_ADDR || RC=$? [ $RC -ne 0 ] && echo "rsync returned code $RC:" >> /dev/stderr @@ -108,9 +102,9 @@ then 0) RC=0 # Success ;; 12) RC=71 # EPROTO - echo "rsync server on the other end has incompatible protocol. " \ - "Make sure you have the same version of rsync on all nodes."\ - >> /dev/stderr + wsrep_log_error \ + "rsync server on the other end has incompatible protocol. " \ + "Make sure you have the same version of rsync on all nodes." ;; 22) RC=12 # ENOMEM ;; @@ -121,23 +115,24 @@ then [ $RC -ne 0 ] && exit $RC else # BYPASS - STATE="$UUID:$SEQNO" + wsrep_log_info "Bypassing state dump." + STATE="$WSREP_SST_OPT_GTID" fi echo "continue" # now server can resume updating data echo "$STATE" > "$MAGIC_FILE" - rsync -aqc "$MAGIC_FILE" rsync://$ADDR + rsync -aqc "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR echo "done $STATE" -elif [ "$ROLE" = "joiner" ] +elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ] then - MYSQLD_PID=$6 + MYSQLD_PID=$WSREP_SST_OPT_PARENT MODULE="rsync_sst" - RSYNC_PID="$DATA/$MODULE.pid" + RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" if check_pid $RSYNC_PID then @@ -146,6 +141,7 @@ then fi rm -rf "$RSYNC_PID" + ADDR=$WSREP_SST_OPT_ADDR RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }') if [ -z "$RSYNC_PORT" ] then @@ -159,13 +155,13 @@ then MYUID=$(id -u) MYGID=$(id -g) - RSYNC_CONF="$DATA/$MODULE.conf" + RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" cat << EOF > "$RSYNC_CONF" pid file = $RSYNC_PID use chroot = no [$MODULE] - path = $DATA + path = $WSREP_SST_OPT_DATA read only = no timeout = 300 uid = $MYUID @@ -207,7 +203,7 @@ EOF # cleanup_joiner else - echo "Unrecognized role: $ROLE" + echo "Unrecognized role: '$WSREP_SST_OPT_ROLE'" exit 22 # EINVAL fi diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh new file mode 100644 index 00000000000..5dad320e0f8 --- /dev/null +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -0,0 +1,222 @@ +#!/bin/bash -ue + +# Copyright (C) 2011 Percona Inc +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for Percona XtraBackup-based state snapshot tansfer + +TMPDIR="/tmp" + +. $(dirname $0)/wsrep_sst_common + +cleanup_joiner() +{ +#set -x + local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') + wsrep_log_info "Killing nc pid $PID" + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$MAGIC_FILE" +#set +x +} + +check_pid() +{ + local pid_file=$1 + [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 +} + +kill_xtrabackup() +{ +#set -x + local PID=$(cat $XTRABACKUP_PID) + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$XTRABACKUP_PID" +#set +x +} + +# waits ~10 seconds for nc to open the port and then reports ready +# (regardless of timeout) +wait_for_nc() +{ + local PORT=$1 + local ADDR=$2 + local MODULE=$3 + for i in $(seq 1 50) + do + netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \ + sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break + sleep 0.2 + done + echo "ready ${ADDR}/${MODULE}" +} + +INNOBACKUPEX_BIN=innobackupex +INNOBACKUPEX_ARGS="" +NC_BIN=nc + +for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do + which ${!TOOL_BIN} > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Can't find ${!TOOL_BIN} in the path" + exit 22 # EINVAL + fi +done + +#ROLE=$1 +#ADDR=$2 +readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) +readonly DATA="${WSREP_SST_OPT_DATA}" +#CONF=$5 + +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" + +MAGIC_FILE="${DATA}/${INFO_FILE}" +rm -f "${MAGIC_FILE}" + +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] +then + +# UUID=$6 +# SEQNO=$7 +# BYPASS=$8 + + NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') + REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + + INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar + --defaults-file=${WSREP_SST_OPT_CONF} + --socket=${WSREP_SST_OPT_SOCKET}" + + if [ "${AUTH[0]}" != "(null)" ]; then + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}" + fi + + if [ ${#AUTH[*]} -eq 2 ]; then + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" + fi + + set +e + + # This file and variable seems to have no effect and probably should be deleted + XTRABACKUP_PID=$(mktemp --tmpdir wsrep_sst_xtrabackupXXXX.pid) + + ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ + 2> ${DATA}/innobackup.backup.log | \ + ${NC_BIN} ${REMOTEIP} ${NC_PORT} + + RC=( "${PIPESTATUS[@]}" ) + set -e + + if [ ${RC[0]} -ne 0 ]; then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ + "Check ${DATA}/innobackup.backup.log" + exit 22 + elif [ ${RC[1]} -ne 0 ]; then + wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}" + exit 22 + fi + + if check_pid ${XTRABACKUP_PID} + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + exit 22 + fi + + rm -f ${XTRABACKUP_PID} + + else # BYPASS + STATE="${WSREP_SST_OPT_GTID}" + echo "continue" # now server can resume updating data + echo "${STATE}" > "${MAGIC_FILE}" + echo "1" > "${DATA}/${IST_FILE}" + (cd ${DATA}; tar cf - ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + rm -f ${DATA}/${IST_FILE} + fi + + echo "done ${WSREP_SST_OPT_GTID}" + +elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] +then + MODULE="xtrabackup_sst" + + rm -f ${DATA}/xtrabackup_* + + ADDR=${WSREP_SST_OPT_ADDR} + NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }') + if [ -z "${NC_PORT}" ] + then + NC_PORT=4444 + ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}" + fi + + wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & + +# trap "exit 32" HUP PIPE +# trap "exit 3" INT TERM + trap cleanup_joiner HUP PIPE INT TERM + + set +e + ${NC_BIN} -dl ${NC_PORT} | tar xfi - -C ${DATA} 1>&2 + RC=( "${PIPESTATUS[@]}" ) + set -e + + wait %% # join wait_for_nc thread + + if [ ${RC[0]} -ne 0 -o ${RC[1]} -ne 0 ]; + then + wsrep_log_error "Error while getting st data from donor node: " \ + "${RC[0]}, ${RC[1]}" + exit 32 + fi + + if [ ! -r "${MAGIC_FILE}" ] + then + # this message should cause joiner to abort + wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" + exit 32 + fi + + if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null + then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." >&2 + exit 32 + fi + + if [ ! -r "${IST_FILE}" ] + then + rm -f ${DATA}/ib_logfile* + ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \ + --ibbackup=xtrabackup ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log + if [ $? -ne 0 ]; + then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" >&2 + exit 22 + fi + fi + + cat "${MAGIC_FILE}" # output UUID:seqno + +else + wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}" + exit 22 # EINVAL +fi + +exit 0 diff --git a/sql/handler.cc b/sql/handler.cc index cb220783e33..b10deec6862 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5233,7 +5233,9 @@ void signal_log_not_needed(struct handlerton, char *log_file) int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) { DBUG_ENTER("ha_wsrep_abort_transaction"); - if (!WSREP(bf_thd)) { + if (!WSREP(bf_thd) && + !(wsrep_OSU_method_options == WSREP_OSU_RSU && + bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { DBUG_RETURN(0); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c4ed7c1e31b..a04dd01e943 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4884,6 +4884,17 @@ static inline bool is_replaying_connection(THD *thd) return ret; } +static inline bool is_committing_connection(THD *thd) +{ + bool ret; + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + return ret; +} + static bool have_client_connections() { THD *tmp; @@ -4937,6 +4948,44 @@ static void wsrep_close_thread(THD *thd) } } +static my_bool have_committing_connections() +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + I_List_iterator it(threads); + while ((tmp=it++)) + { + if (!is_client_connection(tmp)) + continue; + + if (is_committing_connection(tmp)) + { + mysql_mutex_unlock(&LOCK_thread_count); + return TRUE; + } + } + mysql_mutex_unlock(&LOCK_thread_count); + return FALSE; +} + +int wsrep_wait_committing_connections_close(int wait_time) +{ + int sleep_time= 100; + + while (have_committing_connections() && wait_time > 0) + { + WSREP_DEBUG("wait for committing transaction to close: %d", wait_time); + my_sleep(sleep_time); + wait_time -= sleep_time; + } + if (have_committing_connections()) + { + return 1; + } + return 0; +} + void wsrep_close_client_connections(my_bool wait_to_end) { /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fbb47b5c03b..4e582a238e1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8436,8 +8436,10 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) THD *bf_thd = (THD *) bf_thd_ptr; DBUG_ENTER("wsrep_abort_thd"); - if ( (WSREP(bf_thd) || - (WSREP_ON && bf_thd->wsrep_exec_mode == TOTAL_ORDER)) && victim_thd) + if ( (WSREP(bf_thd) || + ( (WSREP_ON || wsrep_OSU_method_options == WSREP_OSU_RSU) && + bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && + victim_thd) { WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 8627d0ff53b..eedd763b784 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -581,6 +581,15 @@ void wsrep_deinit() void wsrep_recover() { + if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) && + local_seqno == -2) + { + char uuid_str[40]; + wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str)); + WSREP_INFO("Position %s:%lld given at startup, skipping position recovery", + uuid_str, (long long)local_seqno); + return; + } XID xid; memset(&xid, 0, sizeof(xid)); xid.formatID= -1; @@ -1103,9 +1112,31 @@ static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) ret = wsrep->desync(wsrep); if (ret != WSREP_OK) { - WSREP_WARN("desync failed %d for %s", ret, thd->query()); + WSREP_WARN("RSU desync failed %d for %s", ret, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0)); return(ret); } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying++; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + if (wsrep_wait_committing_connections_close(5000)) + { + /* no can do, bail out from DDL */ + WSREP_WARN("RSU failed due to pending transactions, %s", thd->query()); + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for %s", ret, thd->query()); + } + my_error(ER_LOCK_DEADLOCK, MYF(0)); + return(1); + } + wsrep_seqno_t seqno = wsrep->pause(wsrep); if (seqno == WSREP_SEQNO_UNDEFINED) { @@ -1123,6 +1154,11 @@ static void wsrep_RSU_end(THD *thd) WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, thd->wsrep_exec_mode, thd->query() ); + + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + ret = wsrep->resume(wsrep); if (ret != WSREP_OK) { diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index ce74cef4e64..af6c66609d4 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -143,6 +143,7 @@ extern void wsrep_recover(); extern void wsrep_init_startup(bool first); extern void wsrep_close_client_connections(my_bool wait_to_end); +extern int wsrep_wait_committing_connections_close(int wait_time); extern void wsrep_close_applier(THD *thd); extern void wsrep_wait_appliers_close(THD *thd); extern void wsrep_close_applier_threads(int count); @@ -176,7 +177,7 @@ extern wsrep_seqno_t wsrep_locked_seqno; // This is a workaround. It also prefixes all messages with "WSREP" #define WSREP_LOG(fun, ...) \ { \ - char msg[256] = {'\0'}; \ + char msg[1024] = {'\0'}; \ snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ fun("WSREP: %s", msg); \ } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 8beadeb2ff2..53e3bbcfc79 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -25,6 +25,25 @@ extern const char wsrep_defaults_file[]; +#define WSREP_SST_OPT_ROLE "--role" +#define WSREP_SST_OPT_ADDR "--address" +#define WSREP_SST_OPT_AUTH "--auth" +#define WSREP_SST_OPT_DATA "--datadir" +#define WSREP_SST_OPT_CONF "--defaults-file" +#define WSREP_SST_OPT_PARENT "--parent" + +// mysqldump-specific options +#define WSREP_SST_OPT_USER "--user" +#define WSREP_SST_OPT_PSWD "--password" +#define WSREP_SST_OPT_HOST "--host" +#define WSREP_SST_OPT_PORT "--port" +#define WSREP_SST_OPT_LPORT "--local-port" + +// donor-specific +#define WSREP_SST_OPT_SOCKET "--socket" +#define WSREP_SST_OPT_GTID "--gtid" +#define WSREP_SST_OPT_BYPASS "--bypass" + #define WSREP_SST_MYSQLDUMP "mysqldump" #define WSREP_SST_SKIP "skip" #define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP @@ -41,31 +60,19 @@ static const char* sst_auth_real = NULL; my_bool wsrep_sst_donor_rejects_queries = FALSE; -static const char *sst_methods[] = { - "mysqldump", - "rsync", - "rsync_wan", - "xtrabackup", - NULL -}; - bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) { char buff[FN_REFLEN]; String str(buff, sizeof(buff), system_charset_info), *res; const char* c_str = NULL; - if ((res = var->value->val_str(&str))) { - c_str = res->c_ptr(); - int i = 0; + if ((res = var->value->val_str(&str)) && + (c_str = res->c_ptr()) && + strlen(c_str) > 0) + return 0; - while (sst_methods[i] && strcasecmp(sst_methods[i], c_str)) i++; - if (!sst_methods[i]) { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); - return 1; - } - } - return 0; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); + return 1; } bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) @@ -381,7 +388,13 @@ static ssize_t sst_prepare_other (const char* method, const char* sst_dir= mysql_real_data_home; int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s 'joiner' '%s' '%s' '%s' '%s' '%d'", + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'joiner' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_PARENT" '%d'", method, addr_in, (sst_auth_real) ? sst_auth_real : "", sst_dir, wsrep_defaults_file, (int)getpid()); @@ -394,7 +407,13 @@ static ssize_t sst_prepare_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str); mysql_mutex_lock (&arg.lock); - 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)", + ret, strerror(ret)); + return ret; + } mysql_cond_wait (&arg.cond, &arg.lock); *addr_out= arg.ret_str; @@ -665,9 +684,17 @@ static int sst_donate_mysqldump (const char* addr, if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); snprintf (cmd_str, cmd_len, - "wsrep_sst_mysqldump '%s' '%s' '%s' '%s' '%u' '%s' '%lld' '%d'", - user, pswd, host, port, mysqld_port, uuid_str, (long long)seqno, - bypass); + "wsrep_sst_mysqldump " + WSREP_SST_OPT_USER" '%s' " + WSREP_SST_OPT_PSWD" '%s' " + WSREP_SST_OPT_HOST" '%s' " + WSREP_SST_OPT_PORT" '%s' " + WSREP_SST_OPT_LPORT" '%u' " + WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_GTID" '%s:%lld'" + "%s", + user, pswd, host, port, mysqld_port, mysqld_unix_port, uuid_str, + (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); WSREP_DEBUG("Running: '%s'", cmd_str); @@ -880,10 +907,19 @@ static int sst_donate_other (const char* method, char cmd_str[cmd_len]; int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s 'donor' '%s' '%s' '%s' '%s' '%s' '%lld' '%d'" - , - method, addr, sst_auth_real, mysql_real_data_home, - wsrep_defaults_file, uuid, (long long) seqno, bypass); + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'donor' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_GTID" '%s:%lld'" + "%s", + method, addr, sst_auth_real, mysqld_unix_port, + mysql_real_data_home, wsrep_defaults_file, + uuid, (long long) seqno, + bypass ? " "WSREP_SST_OPT_BYPASS : ""); if (ret < 0 || ret >= cmd_len) { @@ -896,7 +932,13 @@ static int sst_donate_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str); mysql_mutex_lock (&arg.lock); - 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)", + ret, strerror(ret)); + return ret; + } mysql_cond_wait (&arg.cond, &arg.lock); WSREP_INFO("sst_donor_thread signaled with %d", arg.err); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0b3ea633829..22782dad174 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5581,7 +5581,10 @@ ha_innobase::write_row( || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { #ifdef WITH_WSREP - WSREP_DEBUG("forced commit: %s", wsrep_thd_query(user_thd)); + if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + WSREP_DEBUG("forced trx split for LOAD: %s", + wsrep_thd_query(user_thd)); + } #endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 93222c1d3ac..f52fee5de61 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -30,7 +30,7 @@ %define mysqld_group mysql %define mysqldatadir /var/lib/mysql -%define release 2 +%define release 1 # # Macros we use which are not available in all supported versions of RPM @@ -73,9 +73,6 @@ %if %{defined with_wsrep} %define mysql_version @VERSION@_wsrep_@WSREP_API_VERSION@.@WSREP_PATCH_VERSION@ %define wsrep_version @WSREP_VERSION@ -%define wsrep_comment , wsrep_%{wsrep_version} -%else -%define wsrep_comment %{nil} %endif # ---------------------------------------------------------------------------- @@ -104,10 +101,10 @@ # Server comment strings # ---------------------------------------------------------------------------- %if %{undefined compilation_comment_debug} -%define compilation_comment_debug MySQL Community Server - Debug (GPL)%{wsrep_comment} +%define compilation_comment_debug MySQL Community Server - Debug (GPL) %endif %if %{undefined compilation_comment_release} -%define compilation_comment_release MySQL Community Server (GPL)%{wsrep_comment} +%define compilation_comment_release MySQL Community Server (GPL) %endif # ---------------------------------------------------------------------------- @@ -1098,9 +1095,11 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip %if %{defined with_wsrep} +%attr(755, root, root) %{_bindir}/wsrep_sst_common %attr(755, root, root) %{_bindir}/wsrep_sst_mysqldump %attr(755, root, root) %{_bindir}/wsrep_sst_rsync %attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan +%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup %endif %attr(755, root, root) %{_sbindir}/mysqld diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh index c04e5ddaf43..507f83324b9 100644 --- a/support-files/wsrep.cnf.sh +++ b/support-files/wsrep.cnf.sh @@ -110,7 +110,8 @@ wsrep_notify_cmd= # State Snapshot Transfer method wsrep_sst_method=mysqldump -# Address on THIS node to receive SST at. DON'T SET IT TO DONOR ADDRESS!!! +# Address which donor should send State Snapshot to. +# Should be the address of THIS node. DON'T SET IT TO DONOR ADDRESS!!! # (SST method dependent. Defaults to the first IP of the first interface) #wsrep_sst_receive_address= From f4862acfc389864f99100f66abe905c1f5be9e80 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 17 Sep 2012 12:06:39 +0300 Subject: [PATCH 011/294] References lp:1051808 - merged with lp:codership-mysql 5.5.27 based trunk merged xtradb storage engine part --- storage/xtradb/handler/ha_innodb.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 12a9abd443e..60ef7875a1c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6305,7 +6305,10 @@ ha_innobase::write_row( || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { #ifdef WITH_WSREP - WSREP_DEBUG("forced commit: %s", wsrep_thd_query(user_thd)); + if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + WSREP_DEBUG("forced trx split for LOAD: %s", + wsrep_thd_query(user_thd)); + } #endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. From 456b01b09b7675396fbf8525b0bbaa497a7fa0a4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 17 Sep 2012 15:33:19 +0200 Subject: [PATCH 012/294] MDEV-507 deb/rpm packages for galera builds rpm part: only build the server rpm, not client or shared or anything else --- cmake/cpack_rpm.cmake | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 72ceb0816b8..7bb5c64f337 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -23,9 +23,7 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared") SET(CPACK_COMPONENT_COMMON_GROUP "common") SET(CPACK_COMPONENT_COMPAT_GROUP "compat") SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts - SupportFiles Development ManPagesDevelopment - ManPagesTest Readme ManPagesClient Test - Common Client SharedLibraries) + SupportFiles Readme) SET(CPACK_RPM_PACKAGE_NAME "MariaDB-Galera") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") @@ -97,32 +95,6 @@ SET(CPACK_RPM_test_PACKAGE_PROVIDES "MariaDB-test MySQL-test mysql-test") # workaround for lots of perl dependencies added by rpmbuild SET(CPACK_RPM_test_PACKAGE_PROVIDES "${CPACK_RPM_test_PACKAGE_PROVIDES} perl(lib::mtr_gcov.pl) perl(lib::mtr_gprof.pl) perl(lib::mtr_io.pl) perl(lib::mtr_misc.pl) perl(lib::mtr_process.pl) perl(lib::v1/mtr_cases.pl) perl(lib::v1/mtr_gcov.pl) perl(lib::v1/mtr_gprof.pl) perl(lib::v1/mtr_im.pl) perl(lib::v1/mtr_io.pl) perl(lib::v1/mtr_match.pl) perl(lib::v1/mtr_misc.pl) perl(lib::v1/mtr_process.pl) perl(lib::v1/mtr_report.pl) perl(lib::v1/mtr_stress.pl) perl(lib::v1/mtr_timer.pl) perl(lib::v1/mtr_unique.pl) perl(mtr_misc.pl)") -# If we want to build build MariaDB-shared-compat, -# extract compat libraries from MariaDB-shared-5.3 rpm -FILE(GLOB compat_rpm RELATIVE ${CMAKE_SOURCE_DIR} - "${CMAKE_SOURCE_DIR}/../MariaDB-shared-5.3.*.rpm") -IF (compat_rpm) - MESSAGE("Using ${compat_rpm} to build MariaDB-compat") - INSTALL(CODE "EXECUTE_PROCESS( - COMMAND rpm2cpio ${CMAKE_SOURCE_DIR}/${compat_rpm} - COMMAND cpio --extract --make-directories */libmysqlclient*.so.* - - WORKING_DIRECTORY \$ENV{DESTDIR}) - EXECUTE_PROCESS( - COMMAND chmod -R a+rX . - WORKING_DIRECTORY \$ENV{DESTDIR})" - COMPONENT Compat) - SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} Compat) - - # RHEL6/CentOS6 install Postfix by default, and it requires - # libmysqlclient.so.16 that pulls in mysql-libs-5.1.x - # And the latter conflicts with our rpms. - # Make sure that for these distribuions all our rpms require - # MariaDB-compat, that will replace mysql-libs-5.1 - IF(RPM MATCHES "(rhel|centos)6") - SET(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-Galera-compat") - ENDIF() -ENDIF(compat_rpm) - SET(CPACK_RPM_compat_PACKAGE_REQUIRES "/bin/sh") # to mask CPACK_RPM_PACKAGE_REQUIRES SET(CPACK_RPM_compat_PACKAGE_PROVIDES "mysql-libs = 5.3.5") # exact version doesn't matter as long as it greater than 5.1 SET(CPACK_RPM_compat_PACKAGE_OBSOLETES "mysql-libs < 5.3.5") From 076f2f322e6e983f69c73878c9d56dde964d1d59 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 17 Sep 2012 17:42:14 +0200 Subject: [PATCH 013/294] really disable embedded server in galera builds --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 5bfc39c66e6..bfdf477d421 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -53,7 +53,7 @@ IF (WITH_WSREP) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WSREP_C_FLAGS}") SET(COMPILATION_COMMENT "${COMPILATION_COMMENT}, wsrep_${WSREP_VERSION}") - SET(WITH_EMBEDDED_SERVER OFF) + SET(WITH_EMBEDDED_SERVER OFF CACHE INTERNAL "" FORCE) ENDIF() # From 42b69efd5df8318a5d74edf32d4bba07454e1449 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 18 Sep 2012 22:49:13 +0300 Subject: [PATCH 014/294] References lp:1051808 - merged with lp:codership-mysql 5.5.27 based trunk patched with: bzr diff lp:codership-mysql/5.5 -r3790..3793 --- scripts/wsrep_sst_common.sh | 2 +- sql/sql_base.cc | 4 +- sql/sql_insert.cc | 18 ++- sql/sql_parse.cc | 294 ++++++++++++++++++++---------------- sql/sql_parse.h | 15 ++ 5 files changed, 197 insertions(+), 136 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index a3ad90769e9..5c292465ecc 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -91,7 +91,7 @@ wsrep_log() # echo everything to stderr so that it gets into common error log # deliberately made to look different from the rest of the log local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" - echo "WSREP_SST: $* ($tst)" >/dev/stderr + echo "WSREP_SST: $* ($tst)" >>/dev/stderr } wsrep_log_error() diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a5172cd9a3f..f0ddf16bd0f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5078,9 +5078,6 @@ restart: } } #ifdef WITH_WSREP -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ - if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto err; - if ((thd->lex->sql_command== SQLCOM_INSERT || thd->lex->sql_command== SQLCOM_INSERT_SELECT || thd->lex->sql_command== SQLCOM_REPLACE || @@ -5094,6 +5091,7 @@ restart: { WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); } + error: #endif err: diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 230384d0a43..93b6ea11cc1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4090,7 +4090,7 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) #else if (mysql_bin_log.is_open()) -#endif +#endif /* WITH_WSREP */ { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); result= thd->binlog_query(THD::STMT_QUERY_TYPE, @@ -4100,7 +4100,23 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* suppress_use */ FALSE, errcode); } +#ifdef WITH_WSREP + const CSET_STRING query_save = thd->query_string; + thd->set_query_inner((char*)query.ptr(), query.length(), system_charset_info); + + WSREP_TO_ISOLATION_BEGIN((*tables)->s->db.str, (*tables)->s->table_name.str, NULL); + WSREP_TO_ISOLATION_END; + + thd_binlog_trx_reset(thd); + thd->query_string = query_save; + thd->wsrep_exec_mode = LOCAL_STATE; +#endif /* WITH_WSREP */ return result; +#ifdef WITH_WSREP + error: + WSREP_WARN("TO isolation failed: %s", thd->query()); + return 0; +#endif } void select_create::store_values(List &values) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9e30209cc31..bbe74aa9f68 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -110,16 +110,8 @@ static void wsrep_client_rollback(THD *thd); extern Format_description_log_event *wsrep_format_desc; #define WSREP_MYSQL_DB (char *)"mysql" -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ - if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; - -#define WSREP_TO_ISOLATION_END \ - if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \ - wsrep_to_isolation_end(thd); - -#else -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) -#define WSREP_TO_ISOLATION_END +static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, + Parser_state *parser_state); #endif /* WITH_WSREP */ /** @defgroup Runtime_Environment Runtime Environment @@ -905,7 +897,7 @@ bool do_command(THD *thd) thd->wsrep_retry_query_len); } } - if (thd->wsrep_retry_query) + if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING) { my_free(thd->wsrep_retry_query); thd->wsrep_retry_query = NULL; @@ -1009,8 +1001,7 @@ static void wsrep_copy_query(THD *thd) thd->wsrep_retry_query_len = thd->query_length(); thd->wsrep_retry_query = (char *)my_malloc( thd->wsrep_retry_query_len + 1, MYF(0)); - thd->wsrep_retry_command = thd->command; - strcpy(thd->wsrep_retry_query, thd->query()); + 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 */ @@ -1044,8 +1035,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_PRINT("info", ("command: %d", command)); #ifdef WITH_WSREP - bool is_autocommit= false; - if (WSREP(thd)) { if (!thd->in_multi_stmt_transaction_mode()) { @@ -1058,12 +1047,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { thd->wsrep_conflict_state= NO_CONFLICT; } - - 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); - if (thd->wsrep_conflict_state== MUST_ABORT) { wsrep_client_rollback(thd); @@ -1237,7 +1220,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (parser_state.init(thd, thd->query(), thd->query_length())) break; +#ifdef WITH_WSREP + wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); +#else mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); +#endif while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) @@ -1296,7 +1283,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ +#ifdef WITH_WSREP + wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); +#else mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); +#endif } DBUG_PRINT("info",("query ready")); @@ -1617,116 +1608,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (WSREP(thd)) { /* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) { - wsrep_client_rollback(thd); - - WSREP_DEBUG("abort in exec query state, avoiding autocommit"); - } - - /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) { - if (thd->wsrep_exec_mode!= REPL_RECV) { - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay issue, thd has reported status already"); - } - thd->stmt_da->reset_diagnostics_area(); - - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - mysql_reset_thd_for_next_command(thd, opt_userstat_running); - thd->killed= NOT_KILLED; - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%ld)", thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); - - thd_proc_info(thd, "wsrep replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)thd->wsrep_trx_seqno); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_trx_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_wsrep_thd); - - switch (rcode) { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); - WSREP_DEBUG("trx_replay successful for: %ld %llu", - thd->thread_id, (long long)thd->real_id); - break; - case WSREP_TRX_FAIL: - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - } - thd->wsrep_conflict_state= ABORTED; - wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, query: %s", - rcode, thd->query() ? thd->query() : "void"); - /* we're now in inconsistent state, must abort */ - unireg_abort(1); - break; - } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - } - /* setting error code for BF aborted trxs */ - if (thd->wsrep_conflict_state == ABORTED) - { - mysql_reset_thd_for_next_command(thd, opt_userstat_running); - thd->killed= NOT_KILLED; - if (is_autocommit && - (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) - { - WSREP_DEBUG("wsrep retrying AC query: %s", - (thd->query()) ? thd->query() : "void"); - thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; - thd->wsrep_retry_counter++; // grow - wsrep_copy_query(thd); - } - else - { - WSREP_DEBUG("BF aborted, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", - thd->thread_id, is_autocommit, thd->wsrep_retry_counter, - thd->variables.wsrep_retry_autocommit, thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - thd->killed= NOT_KILLED; - thd->wsrep_conflict_state= NO_CONFLICT; - thd->wsrep_retry_counter= 0; // reset - } - } - else - { - set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok - } if ((thd->wsrep_conflict_state != REPLAYING) && - (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) { - + (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) + { thd->update_server_status(); thd->protocol->end_statement(); query_cache_end_of_result(thd); @@ -1734,7 +1618,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } else { /* if (WSREP(thd))... */ - #endif /* WITH_WSREP */ DBUG_ASSERT(thd->derived_tables == NULL && (thd->open_tables == NULL || @@ -6142,6 +6025,155 @@ void mysql_init_multi_delete(LEX *lex) lex->query_tables_last= &lex->query_tables; } +#ifdef WITH_WSREP +static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, + Parser_state *parser_state) +{ + 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); + + do + { + if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + thd->wsrep_conflict_state= NO_CONFLICT; + } + mysql_parse(thd, rawbuf, length, parser_state); + + if (WSREP(thd)) { + /* wsrep BF abort in query exec phase */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + wsrep_client_rollback(thd); + + WSREP_DEBUG("abort in exec query state, avoiding autocommit"); + } + + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) { + if (thd->wsrep_exec_mode!= REPL_RECV) { + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); + + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); + + thd_proc_info(thd, "wsrep replaying trx"); + WSREP_DEBUG("replay trx: %s %lld", + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + int rcode = wsrep->replay_trx(wsrep, + &thd->wsrep_trx_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_wsrep_thd); + + switch (rcode) { + case WSREP_OK: + thd->wsrep_conflict_state= NO_CONFLICT; + wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); + WSREP_DEBUG("trx_replay successful for: %ld %llu", + thd->thread_id, (long long)thd->real_id); + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + } + /* setting error code for BF aborted trxs */ + if (thd->wsrep_conflict_state == ABORTED) + { + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + if (is_autocommit && + (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) + { + WSREP_DEBUG("wsrep retrying AC query: %s", + (thd->query()) ? thd->query() : "void"); + + + close_thread_tables(thd); + + thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; + thd->wsrep_retry_counter++; // grow + wsrep_copy_query(thd); + thd->set_time(); + parser_state->reset(rawbuf, length); + } + else + { + WSREP_DEBUG("BF aborted, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + thd->killed= NOT_KILLED; + thd->wsrep_conflict_state= NO_CONFLICT; + if (thd->wsrep_conflict_state != REPLAYING) + thd->wsrep_retry_counter= 0; // reset + } + } + else + { + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT); + + if (thd->wsrep_retry_query) + { + WSREP_DEBUG("releasing retry_query: %s", 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 */ /* When you modify mysql_parse(), you may need to mofify diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 4510ebe94e2..d7063291fde 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -202,6 +202,21 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs) { return test(cs->mbminlen == 1); } +#ifdef WITH_WSREP + +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ + if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; + +#define WSREP_TO_ISOLATION_END \ + if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \ + wsrep_to_isolation_end(thd); + +#else + +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) +#define WSREP_TO_ISOLATION_END + +#endif /* WITH_WSREP */ #endif /* SQL_PARSE_INCLUDED */ From 6475ef7db3efff08da352cc90b55c4295c1bd6c2 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 19 Sep 2012 00:23:06 +0300 Subject: [PATCH 015/294] References lp:1052668 - DBUG macro issue in start_wsrep_THD merged fix from upstream: bzr diff lp:codership-mysql/5.5 -r3793..3794 --- sql/mysqld.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 93290309498..1742392fb92 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4699,16 +4699,15 @@ pthread_handler_t start_wsrep_THD(void *arg) THD *thd; wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; - DBUG_ENTER("start_wsrep_THD"); if (my_thread_init()) { WSREP_ERROR("Could not initialize thread"); - DBUG_RETURN(NULL); + return(NULL); } if (!(thd= new THD(true))) { - DBUG_RETURN(NULL); + return(NULL); } mysql_mutex_lock(&LOCK_thread_count); thd->thread_id=thread_id++; @@ -4740,7 +4739,7 @@ pthread_handler_t start_wsrep_THD(void *arg) statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - DBUG_RETURN(NULL); + return(NULL); } // @@ -4764,7 +4763,7 @@ pthread_handler_t start_wsrep_THD(void *arg) MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); delete thd; - DBUG_RETURN(NULL); + return(NULL); } thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; @@ -4810,7 +4809,7 @@ pthread_handler_t start_wsrep_THD(void *arg) // 'Error in my_thread_global_end(): 2 threads didn't exit' // at server shutdown } - DBUG_RETURN(NULL); + return(NULL); } void wsrep_create_rollbacker() From 20df56c1002e809daa68fa7431a9dd7e3d899642 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 20 Sep 2012 09:35:22 +0300 Subject: [PATCH 016/294] References lp:1051808 lp:1049024 https://mariadb.atlassian.net/browse/MDEV-541 patched with: bzr diff lp:codership-mysql/5.5 -r3794..3795 --- sql/sql_parse.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bbe74aa9f68..c008870b1df 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1056,8 +1056,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); WSREP_DEBUG("Deadlock error for: %s", thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - thd->killed= NOT_KILLED; - thd->mysys_var->abort= 0; + thd->killed = NOT_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_wsrep_thd); From ef6f9a8250804efb047ad6f28e476c59d7223e85 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 23 Oct 2012 22:38:11 +0300 Subject: [PATCH 017/294] References lp:1066784 merged with patch: bzr diff lp:codership-mysql/5.5 -r3795..3809 --- scripts/wsrep_sst_xtrabackup.sh | 6 +- sql/handler.cc | 21 +++ sql/handler.h | 2 + sql/log.cc | 7 + sql/mdl.cc | 8 ++ sql/slave.cc | 17 +++ sql/sql_acl.cc | 38 +++++- sql/sql_class.cc | 60 +++++++-- sql/sql_class.h | 32 +---- sql/sql_insert.cc | 23 ++-- sql/sql_parse.cc | 164 ++++++++++++----------- sql/sql_parse.h | 1 + sql/sys_vars.cc | 9 ++ sql/wsrep_hton.cc | 9 ++ sql/wsrep_mysqld.cc | 22 +-- sql/wsrep_mysqld.h | 88 ++++++++++++ storage/innobase/handler/ha_innodb.cc | 40 +++++- storage/innobase/handler/ha_innodb.h | 3 + storage/innobase/include/ha_prototypes.h | 2 +- storage/innobase/lock/lock0lock.c | 59 ++++---- storage/innobase/rem/rem0rec.c | 4 +- 21 files changed, 431 insertions(+), 184 deletions(-) diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 5dad320e0f8..dd8532d6485 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -67,9 +67,9 @@ INNOBACKUPEX_BIN=innobackupex INNOBACKUPEX_ARGS="" NC_BIN=nc -for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do - which ${!TOOL_BIN} > /dev/null 2>&1 - if [ $? -ne 0 ]; then +for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do + if ! which ${!TOOL_BIN} > /dev/null 2>&1 + then echo "Can't find ${!TOOL_BIN} in the path" exit 22 # EINVAL fi diff --git a/sql/handler.cc b/sql/handler.cc index e95c903fd47..bce48feab89 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5268,6 +5268,27 @@ int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) DBUG_RETURN(0); } + +void ha_wsrep_fake_trx_id(THD *thd) +{ + DBUG_ENTER("ha_wsrep_fake_trx_id"); + if (!WSREP(thd)) + { + DBUG_VOID_RETURN; + } + + handlerton *hton= installed_htons[DB_TYPE_INNODB]; + if (hton && hton->wsrep_fake_trx_id) + { + hton->wsrep_fake_trx_id(hton, thd); + } + else + { + WSREP_WARN("cannot get get fake InnoDB transaction ID"); + } + + DBUG_VOID_RETURN; +} #endif /* WITH_WSREP */ #ifdef TRANS_LOG_MGM_EXAMPLE_CODE /* diff --git a/sql/handler.h b/sql/handler.h index 47593845ad6..13444a1095d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1047,6 +1047,7 @@ struct handlerton THD *victim_thd, my_bool signal); int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); + void (*wsrep_fake_trx_id)(handlerton *hton, THD *thd); uint32 license; /* Flag for Engine License */ /* @@ -3033,6 +3034,7 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); #ifdef WITH_WSREP int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); +void ha_wsrep_fake_trx_id(THD *thd); #endif /* WITH_WSREP */ /* these are called by storage engines */ diff --git a/sql/log.cc b/sql/log.cc index 22d2a3c0647..4dd5bb561e5 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1833,6 +1833,13 @@ static inline int binlog_commit_flush_stmt_cache(THD *thd, bool all, binlog_cache_mngr *cache_mngr) { +#ifdef WITH_WSREP + if (thd->wsrep_mysql_replicated > 0) + { + WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated); + return 0; + } +#endif Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"), FALSE, TRUE, TRUE, 0); return (binlog_flush_cache(thd, cache_mngr, &end_evt, all, TRUE, FALSE)); diff --git a/sql/mdl.cc b/sql/mdl.cc index 8ff420e4f50..2e279c19592 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1575,6 +1575,14 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket)) { 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" + ); + } } else { diff --git a/sql/slave.cc b/sql/slave.cc index fe3ce480367..b928b658f51 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2600,6 +2600,23 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) ev->thd = thd; // because up to this point, ev->thd == 0 int reason= ev->shall_skip(rli); +#ifdef WITH_WSREP + if (ev->get_type_code() == XID_EVENT || + (ev->get_type_code() == QUERY_EVENT && thd->wsrep_mysql_replicated > 0 && + (!strncasecmp(((Query_log_event*)ev)->query , "BEGIN", 5) || + !strncasecmp(((Query_log_event*)ev)->query , "COMMIT", 6) ))) + { + if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) + { + WSREP_DEBUG("skipping wsrep commit %d", thd->wsrep_mysql_replicated); + reason = Log_event::EVENT_SKIP_IGNORE; + } + else + { + thd->wsrep_mysql_replicated = 0; + } + } +#endif if (reason == Log_event::EVENT_SKIP_COUNT) sql_slave_skip_counter= --rli->slave_skip_counter; mysql_mutex_unlock(&rli->data_lock); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8f27c45247e..22fb5ee74cd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1830,6 +1830,9 @@ int check_change_password(THD *thd, const char *host, const char *user, return(1); } if (!thd->slave_thread && +#ifdef WITH_WSREP + (!WSREP(thd) || !thd->wsrep_applier) && +#endif /* WITH_WSREP */ (strcmp(thd->security_ctx->user, user) || my_strcasecmp(system_charset_info, host, thd->security_ctx->priv_host))) @@ -1837,7 +1840,12 @@ int check_change_password(THD *thd, const char *host, const char *user, if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 0)) return(1); } +#ifdef WITH_WSREP + if ((!WSREP(thd) || !thd->wsrep_applier) && + !thd->slave_thread && !thd->security_ctx->user[0]) +#else if (!thd->slave_thread && !thd->security_ctx->user[0]) +#endif /* WITH_WSREP */ { my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), MYF(0)); @@ -1876,10 +1884,13 @@ bool change_password(THD *thd, const char *host, const char *user, TABLE *table; /* Buffer should be extended when password length is extended. */ char buff[512]; - ulong query_length; + ulong query_length=0; bool save_binlog_row_based; uint new_password_len= (uint) strlen(new_password); bool result= 1; +#ifdef WITH_WSREP + const CSET_STRING query_save = thd->query_string; +#endif /* WITH_WSREP */ DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); @@ -1887,6 +1898,18 @@ bool change_password(THD *thd, const char *host, const char *user, if (check_change_password(thd, host, user, new_password, new_password_len)) DBUG_RETURN(1); +#ifdef WITH_WSREP + if (WSREP(thd) && !thd->wsrep_applier) + { + query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", + user ? user : "", + host ? host : "", + new_password); + thd->set_query_inner(buff, query_length, system_charset_info); + + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); + } +#endif /* WITH_WSREP */ tables.init_one_table("mysql", 5, "user", 4, "user", TL_WRITE); @@ -1965,13 +1988,26 @@ bool change_password(THD *thd, const char *host, const char *user, } end: close_mysql_tables(thd); +#ifdef WITH_WSREP + if (WSREP(thd) && !thd->wsrep_applier) + { + WSREP_TO_ISOLATION_END; + thd->query_string = query_save; + thd->wsrep_exec_mode = LOCAL_STATE; + } +#endif /* WITH_WSREP */ /* Restore the state of binlog format */ DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(result); +#ifdef WITH_WSREP + error: + WSREP_ERROR("Replication of SET PASSWORD failed: %s", buff); + DBUG_RETURN(result); +#endif /* WITH_WSREP */ } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ff92eda7c1f..7604227740f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -733,14 +733,49 @@ extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) { return thd->wsrep_exec_mode; } + +extern "C" 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"; +} + extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd) { return thd->wsrep_query_state; } + +extern "C" 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"; +} + extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd) { return thd->wsrep_conflict_state; } +extern "C" 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"; +} extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd) { @@ -769,7 +804,7 @@ extern "C" my_thread_id wsrep_thd_thread_id(THD *thd) } extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd) { - return thd->wsrep_trx_seqno; + return (thd) ? thd->wsrep_trx_seqno : -1; } extern "C" query_id_t wsrep_thd_query_id(THD *thd) { @@ -777,7 +812,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd) } extern "C" char *wsrep_thd_query(THD *thd) { - return thd->query(); + return (thd) ? thd->query() : NULL; } extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) { @@ -995,17 +1030,19 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); - wsrep_trx_handle.trx_id= -1; - wsrep_trx_handle.opaque= NULL; + wsrep_trx_handle.trx_id = -1; + wsrep_trx_handle.opaque = NULL; //wsrep_retry_autocommit= ::wsrep_retry_autocommit; - wsrep_retry_counter= 0; - wsrep_PA_safe = true; - wsrep_seqno_changed= false; - wsrep_retry_query = NULL; - wsrep_retry_query_len = 0; - wsrep_retry_command = COM_CONNECT; + wsrep_retry_counter = 0; + wsrep_PA_safe = true; + wsrep_seqno_changed = false; + wsrep_retry_query = NULL; + wsrep_retry_query_len = 0; + wsrep_retry_command = COM_CONNECT; wsrep_consistency_check = NO_CONSISTENCY_CHECK; - wsrep_status_vars = 0; + wsrep_status_vars = 0; + wsrep_mysql_replicated = 0; + #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1359,6 +1396,7 @@ void THD::init(void) wsrep_PA_safe= true; wsrep_seqno_changed= false; wsrep_consistency_check = NO_CONSISTENCY_CHECK; + wsrep_mysql_replicated = 0; #endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; diff --git a/sql/sql_class.h b/sql/sql_class.h index b6e2069fe17..98766cabeca 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -20,37 +20,6 @@ #define SQL_CLASS_INCLUDED /* Classes in mysql */ -#ifdef WITH_WSREP -#include "../wsrep/wsrep_api.h" -//#include "wsrep_mysqld.h" - enum wsrep_exec_mode { - LOCAL_STATE, - REPL_RECV, - TOTAL_ORDER, - LOCAL_COMMIT, - }; - enum wsrep_query_state { - QUERY_IDLE, - QUERY_EXEC, - QUERY_COMMITTING, - QUERY_EXITING, - QUERY_ROLLINGBACK, - }; - enum wsrep_conflict_state { - NO_CONFLICT, - MUST_ABORT, - ABORTING, - ABORTED, - MUST_REPLAY, - REPLAYING, - RETRY_AUTOCOMMIT, - }; - enum wsrep_consistency_check_mode { - NO_CONSISTENCY_CHECK, - CONSISTENCY_CHECK_DECLARED, - CONSISTENCY_CHECK_RUNNING, - }; -#endif #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ @@ -2405,6 +2374,7 @@ public: enum wsrep_consistency_check_mode wsrep_consistency_check; wsrep_stats_var* wsrep_status_vars; + int wsrep_mysql_replicated; #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 93b6ea11cc1..5c165e4ec7d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3573,8 +3573,14 @@ bool select_insert::send_eof() DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", trans_table, table->file->table_type())); +#ifdef WITH_WSREP + error= (thd->wsrep_conflict_state == MUST_ABORT) ? -1 : + (thd->locked_tables_mode <= LTM_LOCK_TABLES ? + table->file->ha_end_bulk_insert() : 0); +#else error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ? table->file->ha_end_bulk_insert() : 0); +#endif /* WITH_WSREP */ if (!error && thd->is_error()) error= thd->stmt_da->sql_errno(); @@ -4101,22 +4107,9 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) errcode); } #ifdef WITH_WSREP - const CSET_STRING query_save = thd->query_string; - thd->set_query_inner((char*)query.ptr(), query.length(), system_charset_info); - - WSREP_TO_ISOLATION_BEGIN((*tables)->s->db.str, (*tables)->s->table_name.str, NULL); - WSREP_TO_ISOLATION_END; - - thd_binlog_trx_reset(thd); - thd->query_string = query_save; - thd->wsrep_exec_mode = LOCAL_STATE; -#endif /* WITH_WSREP */ - return result; -#ifdef WITH_WSREP - error: - WSREP_WARN("TO isolation failed: %s", thd->query()); - return 0; + ha_wsrep_fake_trx_id(thd); #endif + return result; } void select_create::store_values(List &values) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c008870b1df..6a9063d0edb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -108,7 +108,6 @@ static void wsrep_client_rollback(THD *thd); extern Format_description_log_event *wsrep_format_desc; -#define WSREP_MYSQL_DB (char *)"mysql" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state); @@ -6050,85 +6049,88 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, /* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_wsrep_thd); if (thd->wsrep_conflict_state == MUST_ABORT) { - wsrep_client_rollback(thd); + wsrep_client_rollback(thd); - WSREP_DEBUG("abort in exec query state, avoiding autocommit"); + WSREP_DEBUG("abort in exec query state, avoiding autocommit"); } /* checking if BF trx must be replayed */ if (thd->wsrep_conflict_state== MUST_REPLAY) { - if (thd->wsrep_exec_mode!= REPL_RECV) { - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay issue, thd has reported status already"); - } - thd->stmt_da->reset_diagnostics_area(); + if (thd->wsrep_exec_mode!= REPL_RECV) { + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - mysql_reset_thd_for_next_command(thd, opt_userstat_running); - thd->killed= NOT_KILLED; - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%ld)", thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); - thd_proc_info(thd, "wsrep replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)thd->wsrep_trx_seqno); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_trx_handle, - (void *)thd); + thd_proc_info(thd, "wsrep replaying trx"); + WSREP_DEBUG("replay trx: %s %lld", + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + int rcode = wsrep->replay_trx(wsrep, + &thd->wsrep_trx_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 ); + 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_wsrep_thd); - - switch (rcode) { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); - WSREP_DEBUG("trx_replay successful for: %ld %llu", - thd->thread_id, (long long)thd->real_id); - break; - case WSREP_TRX_FAIL: - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - } - thd->wsrep_conflict_state= ABORTED; - wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, query: %s", - rcode, thd->query() ? thd->query() : "void"); - /* we're now in inconsistent state, must abort */ - unireg_abort(1); - break; - } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + switch (rcode) { + case WSREP_OK: + thd->wsrep_conflict_state= NO_CONFLICT; + wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); + WSREP_DEBUG("trx_replay successful for: %ld %llu", + thd->thread_id, (long long)thd->real_id); + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); } } + /* setting error code for BF aborted trxs */ - if (thd->wsrep_conflict_state == ABORTED) + if (thd->wsrep_conflict_state == ABORTED || + thd->wsrep_conflict_state == CERT_FAILURE) { mysql_reset_thd_for_next_command(thd, opt_userstat_running); thd->killed= NOT_KILLED; @@ -6143,25 +6145,27 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; thd->wsrep_retry_counter++; // grow - wsrep_copy_query(thd); + wsrep_copy_query(thd); thd->set_time(); parser_state->reset(rawbuf, length); - } - else - { - WSREP_DEBUG("BF aborted, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", - thd->thread_id, is_autocommit, thd->wsrep_retry_counter, - thd->variables.wsrep_retry_autocommit, thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - thd->killed= NOT_KILLED; - thd->wsrep_conflict_state= NO_CONFLICT; + } + else + { + WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + (thd->wsrep_conflict_state == ABORTED) ? + "BF Aborted" : "cert failure", + thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + thd->killed= NOT_KILLED; + thd->wsrep_conflict_state= NO_CONFLICT; if (thd->wsrep_conflict_state != REPLAYING) - thd->wsrep_retry_counter= 0; // reset - } + thd->wsrep_retry_counter= 0; // reset + } } else { - set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index d7063291fde..1303eba84b7 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -204,6 +204,7 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs) } #ifdef WITH_WSREP +#define WSREP_MYSQL_DB (char *)"mysql" #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 89bb2e1a812..08277b9f624 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3826,6 +3826,15 @@ static Sys_var_mybool Sys_wsrep_replicate_myisam( "wsrep_replicate_myisam", "To enable myisam replication", GLOBAL_VAR(wsrep_replicate_myisam), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); +static Sys_var_mybool Sys_wsrep_log_conflicts( + "wsrep_log_conflicts", "To log multi-master conflicts", + GLOBAL_VAR(wsrep_log_conflicts), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_wsrep_mysql_replication_bundle( + "wsrep_mysql_replication_bundle", "mysql replication group commit ", + GLOBAL_VAR(wsrep_mysql_replication_bundle), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1000), DEFAULT(0), BLOCK_SIZE(1)); + #endif /* WITH_WSREP */ static Sys_var_ulong Sys_sp_cache_size( diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 219e0e8a244..1fc2372a57c 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -378,6 +378,15 @@ wsrep_run_wsrep_commit( 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_wsrep_thd); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index eedd763b784..c31c02e6d33 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -49,6 +49,8 @@ long wsrep_max_protocol_version = 2; // maximum protocol version to use ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery my_bool wsrep_replicate_myisam = 0; // enable myisam replication +my_bool wsrep_log_conflicts = 0; // +ulong wsrep_mysql_replication_bundle = 0; /* * End configuration options @@ -725,7 +727,8 @@ wsrep_causal_wait (THD* thd) break; default: msg= "Causal wait failed."; - err= ER_ERROR_ON_READ; + err= ER_LOCK_WAIT_TIMEOUT; // NOTE: the above msg won't be displayed + // with ER_LOCK_WAIT_TIMEOUT } my_error(err, MYF(0), msg); @@ -1225,6 +1228,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, THD *request_thd = requestor_ctx->get_thd(); THD *granted_thd = ticket->get_ctx()->get_thd(); + bool ret = FALSE; mysql_mutex_lock(&request_thd->LOCK_wsrep_thd); if (request_thd->wsrep_exec_mode == TOTAL_ORDER || @@ -1239,39 +1243,39 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, { WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - return TRUE; + ret = TRUE; } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) { WSREP_DEBUG("mdl granted over FLUSH BF"); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - return TRUE; - } + ret = TRUE; + } else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) { WSREP_DEBUG("DROP caused BF abort"); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - return FALSE; - } + ret = FALSE; + } else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) { WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - return FALSE; + ret = FALSE; } else { WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - return FALSE; + ret = FALSE; } } else { mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); } - return FALSE; + return ret; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index af6c66609d4..d1c72e6001f 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -24,6 +24,39 @@ typedef struct st_mysql_show_var SHOW_VAR; class set_var; class THD; +#ifdef WITH_WSREP +#include "../wsrep/wsrep_api.h" +//#include "wsrep_mysqld.h" + enum wsrep_exec_mode { + LOCAL_STATE, + REPL_RECV, + TOTAL_ORDER, + LOCAL_COMMIT, + }; + enum wsrep_query_state { + QUERY_IDLE, + QUERY_EXEC, + QUERY_COMMITTING, + QUERY_EXITING, + QUERY_ROLLINGBACK, + }; + enum wsrep_conflict_state { + NO_CONFLICT, + MUST_ABORT, + ABORTING, + ABORTED, + MUST_REPLAY, + REPLAYING, + RETRY_AUTOCOMMIT, + CERT_FAILURE, + }; + enum wsrep_consistency_check_mode { + NO_CONSISTENCY_CHECK, + CONSISTENCY_CHECK_DECLARED, + CONSISTENCY_CHECK_RUNNING, + }; +#endif + // Global wsrep parameters extern wsrep_t* wsrep; @@ -60,6 +93,8 @@ extern ulong wsrep_forced_binlog_format; extern ulong wsrep_OSU_method_options; extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; +extern my_bool wsrep_log_conflicts; +extern ulong wsrep_mysql_replication_bundle; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; @@ -138,6 +173,38 @@ extern int wsrep_init(); extern void wsrep_deinit(); extern void wsrep_recover(); + + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); +extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); +extern "C" const char * wsrep_thd_query_state_str(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(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_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); + + + /* wsrep initialization sequence at startup * @param first wsrep_init_first() value */ extern void wsrep_init_startup(bool first); @@ -188,6 +255,27 @@ extern wsrep_seqno_t wsrep_locked_seqno; #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: %ld\n " \ + " SQL: %s", \ + role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ + wsrep_thd_query_state_str(thd), \ + wsrep_thd_conflict_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"); \ + } + /*! Synchronizes applier thread start with init thread */ extern void wsrep_sst_grab(); /*! Init thread waits for SST completion */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e1f18c84800..a1b7eab5deb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -927,6 +927,8 @@ innobase_release_temporary_latches( 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 @@ -2317,6 +2319,7 @@ innobase_init( innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; + innobase_hton->wsrep_fake_trx_id=wsrep_fake_trx_id; #endif /* WITH_WSREP */ ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -7004,7 +7007,12 @@ wsrep_append_foreign_key( &key[1], &len, rec, index, wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { - WSREP_ERROR("FK key set failed: %lu", rcode); + WSREP_ERROR( + "FK key set failed: %lu (%lu %lu), index: %s %s, %s", + rcode, referenced, shared, + (index->name) ? index->name : "void index", + (index->table_name) ? index->table_name : "void table", + wsrep_thd_query(thd)); return rcode; } strncpy(cache_key, @@ -12168,18 +12176,27 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) abort(); } int -wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) +wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, ibool signal) { DBUG_ENTER("wsrep_innobase_kill_one_trx"); + THD *bf_thd = (THD *)bf_thd_ptr; THD *thd = (THD *) victim_trx->mysql_thd; - THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + if (!bf_thd) bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + if (!thd) { DBUG_PRINT("wsrep", ("no thd for conflicting lock")); WSREP_WARN("no THD for trx: %llu", victim_trx->id); DBUG_RETURN(1); } + if (!bf_thd) { + DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); + WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0); + DBUG_RETURN(1); + } + + WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", signal, (long long)bf_seqno, @@ -12368,8 +12385,8 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { mutex_enter(&kernel_mutex); - int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, - signal); + int rcode = wsrep_innobase_kill_one_trx( + bf_thd, bf_trx, victim_trx, signal); mutex_exit(&kernel_mutex); DBUG_RETURN(rcode); } else { @@ -12403,6 +12420,19 @@ static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) return 0; } +static void +wsrep_fake_trx_id( +/*==================*/ + handlerton *hton, + THD *thd) /*!< in: user thread handle */ +{ + mutex_enter(&kernel_mutex); + trx_id_t trx_id = trx_sys_get_new_trx_id(); + mutex_exit(&kernel_mutex); + + (void *)wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), trx_id); +} + #endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 8f211d6e38c..aa653adcabf 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -304,6 +304,9 @@ extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); +extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); +extern "C" const char * wsrep_thd_query_state_str(THD *thd); extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 4ac365d5c40..664e18c52a8 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -288,7 +288,7 @@ thd_set_lock_wait_time( #ifdef WITH_WSREP UNIV_INTERN int -wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal); +wsrep_innobase_kill_one_trx(void *bf_thd, trx_t *bf_trx, trx_t *victim_trx, ibool signal); int wsrep_thd_is_brute_force(void *thd_ptr); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index b24bd05e0b3..bb864937751 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -42,6 +42,7 @@ Created 5/7/1996 Heikki Tuuri #ifdef WITH_WSREP extern my_bool wsrep_debug; +extern my_bool wsrep_log_conflicts; #endif /* Restricts the length of search we will do in the waits-for graph of transactions */ @@ -1528,7 +1529,34 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) { /* cannot release lock, until our lock is in the queue*/ } else if (lock->trx != trx) { - wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE); + if (wsrep_log_conflicts) { + if (bf_this) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, trx, 3000); + + if (bf_other) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, lock->trx, 3000); + + fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", + stderr); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(stderr, lock); + } else { + lock_table_print(stderr, lock); + } + } + wsrep_innobase_kill_one_trx( + trx->mysql_thd, trx, lock->trx, TRUE); } } } @@ -4091,33 +4119,12 @@ lock_table_other_has_incompatible( if ((lock->trx != trx) && (!lock_mode_compatible(lock_get_mode(lock), mode)) && (wait || !(lock_get_wait(lock)))) { - #ifdef WITH_WSREP - int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - int bf_other = wsrep_thd_is_brute_force( - lock->trx->mysql_thd); - if ((bf_this && !bf_other) || - (bf_this && bf_other && - wsrep_trx_order_before( - trx->mysql_thd, lock->trx->mysql_thd) - ) - ) { - if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) fprintf(stderr, - "WSREP: BF victim waiting"); - return(lock); - } else { - if (bf_this && bf_other) - wsrep_innobase_kill_one_trx( - (trx_t *)trx, lock->trx, TRUE); - return(lock); - } - } else { - return(lock); - } -#else - return(lock); + if (wsrep_debug) + fprintf(stderr, "WSREP: table lock abort"); + wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); #endif + return(lock); } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 0cee1ffb3c8..44249c3a87e 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1811,8 +1811,8 @@ wsrep_rec_get_primary_key( const dict_col_t* col = dict_field_get_col(field); data = rec_get_nth_field(rec, offsets, i, &len); - if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? - *buf_len : *buf_len - 1)) { + if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > + *buf_len) { fprintf (stderr, "WSREP: FK key len exceeded %lu %lu %lu\n", key_len, len, *buf_len); From c9c458fa6e2e215c783794b11b30ed3a27904383 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 18 Nov 2012 18:07:02 +0400 Subject: [PATCH 018/294] MDEV 507 deb/rpm packages for galera builds. Debian/Ubuntu packages fixed. The mariadb-server-5.5 and mariadb-server packages became mariadb-galera-server-5.5 and mariadb-galera-server respectively. The rest of packages are removed from the build. This patch reflects only files that were changed. Second part of this patch has only file renaming/deletions. --- debian/dist/Debian/control | 221 ++------------------ debian/dist/Debian/mariadb-server-5.5.files | 26 +++ debian/dist/Debian/rules | 8 +- debian/dist/Ubuntu/control | 207 ++---------------- debian/dist/Ubuntu/mariadb-server-5.5.files | 26 +++ debian/dist/Ubuntu/rules | 8 +- 6 files changed, 92 insertions(+), 404 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 95bde727093..3a5510650d1 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -10,190 +10,25 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria -Package: libmariadbclient18 -Section: libs -Architecture: any -Depends: mariadb-common, libmysqlclient18 (= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database client library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client library. - -Package: libmysqlclient18 -Section: libs -Architecture: any -Depends: libmariadbclient18 (= ${source:Version}) -Replaces: libmysqlclient18 (<< ${source:Version}) -Description: Virtual package to satisfy external depends - This is an empty package that provides an updated "best" version of - libmysqlclient18 that does not conflict with the libmariadbclient18 - package. - . - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - -Package: libmariadbd-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient-dev (>= ${source:Version}), ${misc:Depends} -Provides: libmysqld-dev -Conflicts: libmysqld-dev -Replaces: libmysqld-dev -Description: MariaDB embedded database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the embedded server library and header files. - -Package: libmariadbclient-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient18 (>= ${source:Version}), zlib1g-dev, , ${shlibs:Depends}, ${misc:Depends} -Replaces: libmariadbclient16-dev, libmysqlclient16-dev -Conflicts: libmysqlclient-dev, libmariadbclient16-dev, libmysqlclient14-dev, libmysqlclient12-dev, libmysqlclient10-dev, libmysqlclient15-dev, libmysqlclient16-dev -Provides: libmysqlclient-dev -Description: MariaDB database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes development libraries and header files. - -Package: mysql-common -Section: database -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/my.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/my.cnf). - -Package: mariadb-common -Section: database -Architecture: all -Depends: mysql-common, ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/conf.d/mariadb.cnf). - -Package: mariadb-client-core-5.5 -Architecture: any -Depends: mariadb-common, libmariadbclient18 (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Provides: mysql-client-core, mysql-client-core-5.1, mysql-client-core-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1 (<< ${source:Version}), mysql-client-5.5 (<< ${source:Version}), - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1, mysql-client-5.5, - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Description: MariaDB database core client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core client files, as used by Akonadi. - -Package: mariadb-client-5.5 -Architecture: any -Depends: debianutils (>=1.6), libdbi-perl, libdbd-mysql-perl (>= 1.2202), mariadb-common, libmariadbclient18 (>= ${source:Version}), mariadb-client-core-5.5 (>= ${source:Version}), ${perl:Depends}, ${shlibs:Depends}, ${misc:Depends} -Provides: virtual-mysql-client, mysql-client, - mysql-client-4.1, mysql-client-5.1, mysql-client-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, mysql-client-5.5 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mysql-client-5.5, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3 -Description: MariaDB database client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client binaries and the additional tools - innotop and mysqlreport. - -Package: mariadb-server-core-5.5 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5 -Conflicts: mariadb-server-5.1 (<< 5.1.60), - mariadb-server-5.2 (<< 5.2.10), - mariadb-server-5.3 (<< 5.3.3), - mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Replaces: mariadb-server-5.1 (<< 5.1.60), - mariadb-server-5.2 (<< 5.2.10), - mariadb-server-5.3 (<< 5.3.3), - mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Description: MariaDB database core server files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core server files, as used by Akonadi. - -Package: mariadb-test-5.5 -Section: database -Architecture: all -Depends: mariadb-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) -Conflicts: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Replaces: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Description: MariaDB database regression test suite - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the regression test suite. - -Package: mariadb-server-5.5 +Package: mariadb-galera-server-5.5 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}) -Provides: mariadb-server, mysql-server, virtual-mysql-server -Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), - mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 -Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=23.2) +Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mariadb-galera-server, mysql-server, virtual-mysql-server +Conflicts: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, - libmariadbclient16 (<< 5.3.4), - libmariadbclient-dev (<< 5.5.0) -Description: MariaDB database server binaries + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 +Replaces: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), + mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, + mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, + libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 +Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and @@ -201,14 +36,15 @@ Description: MariaDB database server binaries . This package includes the server binaries. -Package: mariadb-server +Package: mariadb-galera-server Section: database Architecture: all -Depends: mariadb-server-5.5, ${misc:Depends} -Description: MariaDB database server (metapackage depending on the latest version) +Depends: mariadb-galera-server-5.5, ${misc:Depends} +Description: MariaDB database server with Galera cluster + (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-server (currently mariadb-server-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB + mariadb-galera-server (currently mariadb-galera-server-5.5), as determined by the MariaDB + maintainers. Install this package if in doubt about which MariaDB-Galera version you need. That will install the version recommended by the package maintainers. . @@ -216,22 +52,3 @@ Description: MariaDB database server (metapackage depending on the latest versio server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. - -Package: mariadb-client -Section: database -Architecture: all -Depends: mariadb-client-5.5, ${misc:Depends} -Description: MariaDB database client (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB version - you want, as this is the one we consider to be in the best shape. - -Package: mariadb-test -Section: database -Architecture: all -Depends: mariadb-test-5.5 -Description: MariaDB database regression test suite (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB - maintainers. diff --git a/debian/dist/Debian/mariadb-server-5.5.files b/debian/dist/Debian/mariadb-server-5.5.files index b236d19a2c5..e68be4f9b86 100644 --- a/debian/dist/Debian/mariadb-server-5.5.files +++ b/debian/dist/Debian/mariadb-server-5.5.files @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ usr/lib/libhsclient.so.* etc/mysql/debian-start @@ -55,6 +56,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index 96ad527542d..ba6db422486 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -190,15 +190,13 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common - cp debian/mariadb-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 - cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 + cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ mkdir -p $$d; \ - cp debian/mariadb-server-5.5.mysql.init $$d/_etc_init.d_mysql; \ - cp debian/mariadb-server-5.5.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ + cp debian/mariadb-galera-server-5.5.mysql.init $$d/_etc_init.d_mysql; \ + cp debian/mariadb-galera-server-5.5.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ cp debian/additions/debian-start $$d/_etc_mysql_debian-start; dh_movefiles diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 70ef5fd2ecf..7c1a087b598 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -10,184 +10,25 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria -Package: libmariadbclient18 -Section: libs -Architecture: any -Depends: mariadb-common, libmysqlclient18 (= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database client library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client library. - -Package: libmysqlclient18 -Section: libs -Architecture: any -Depends: libmariadbclient18 (= ${source:Version}) -Replaces: libmysqlclient18 (<< ${source:Version}) -Description: Virtual package to satisfy external depends - This is an empty package that provides an updated "best" version of - libmysqlclient18 that does not conflict with the libmariadbclient18 - package. - . - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - -Package: libmariadbd-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient-dev (>= ${source:Version}), ${misc:Depends} -Provides: libmysqld-dev -Conflicts: libmysqld-dev -Replaces: libmysqld-dev -Description: MariaDB embedded database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the embedded server library and header files. - -Package: libmariadbclient-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient18 (>= ${source:Version}), zlib1g-dev, , ${shlibs:Depends}, ${misc:Depends} -Replaces: libmariadbclient16-dev, libmysqlclient16-dev -Conflicts: libmysqlclient-dev, libmariadbclient16-dev, libmysqlclient14-dev, libmysqlclient12-dev, libmysqlclient10-dev, libmysqlclient15-dev, libmysqlclient16-dev -Provides: libmysqlclient-dev -Description: MariaDB database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes development libraries and header files. - -Package: mysql-common -Section: database -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/my.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/my.cnf). - -Package: mariadb-common -Section: database -Architecture: all -Depends: mysql-common, ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/conf.d/mariadb.cnf). - -Package: mariadb-client-core-5.5 -Architecture: any -Depends: mariadb-common, libmariadbclient18 (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Provides: mysql-client-core, mysql-client-core-5.1, mysql-client-core-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1 (<< ${source:Version}), mysql-client-5.5 (<< ${source:Version}), - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1, mysql-client-5.5, - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Description: MariaDB database core client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core client files, as used by Akonadi. - -Package: mariadb-client-5.5 -Architecture: any -Depends: debianutils (>=1.6), libdbi-perl, libdbd-mysql-perl (>= 1.2202), mariadb-common, libmariadbclient18 (>= ${source:Version}), mariadb-client-core-5.5 (>= ${source:Version}), ${perl:Depends}, ${shlibs:Depends}, ${misc:Depends} -Provides: virtual-mysql-client, mysql-client, - mysql-client-4.1, mysql-client-5.1, mysql-client-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, mysql-client-5.5 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mysql-client-5.5, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3 -Description: MariaDB database client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client binaries and the additional tools - innotop and mysqlreport. - -Package: mariadb-server-core-5.5 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5 -Conflicts: mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Replaces: mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Description: MariaDB database core server files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core server files, as used by Akonadi. - -Package: mariadb-test-5.5 -Section: database -Architecture: all -Depends: mariadb-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) -Conflicts: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Replaces: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Description: MariaDB database regression test suite - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the regression test suite. - Package: mariadb-server-5.5 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}) -Provides: mariadb-server, mysql-server, virtual-mysql-server -Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), - mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 -Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}) +Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mariadb-galera-server, mysql-server, virtual-mysql-server +Conflicts: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, - libmariadbclient16 (<< 5.3.4), - libmariadbclient-dev (<< 5.5.0) -Description: MariaDB database server binaries + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 +Replaces: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), + mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, + mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, + libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 +Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and @@ -195,11 +36,11 @@ Description: MariaDB database server binaries . This package includes the server binaries. -Package: mariadb-server +Package: mariadb-galera-server Section: database Architecture: all -Depends: mariadb-server-5.5, ${misc:Depends} -Description: MariaDB database server (metapackage depending on the latest version) +Depends: mariadb-galera-server-5.5, ${misc:Depends} +Description: MariaDB database with Galera cluster server (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of mariadb-server (currently mariadb-server-5.5), as determined by the MariaDB maintainers. Install this package if in doubt about which MariaDB @@ -211,21 +52,3 @@ Description: MariaDB database server (metapackage depending on the latest versio language in the world. The main goals of MariaDB are speed, robustness and ease of use. -Package: mariadb-client -Section: database -Architecture: all -Depends: mariadb-client-5.5, ${misc:Depends} -Description: MariaDB database client (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB version - you want, as this is the one we consider to be in the best shape. - -Package: mariadb-test -Section: database -Architecture: all -Depends: mariadb-test-5.5 -Description: MariaDB database regression test suite (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB - maintainers. diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.files b/debian/dist/Ubuntu/mariadb-server-5.5.files index e88e52689ae..d20f8a0af91 100644 --- a/debian/dist/Ubuntu/mariadb-server-5.5.files +++ b/debian/dist/Ubuntu/mariadb-server-5.5.files @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ usr/lib/libhsclient.so.* etc/apparmor.d/usr.sbin.mysqld @@ -57,6 +58,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index bb413ad83cc..d88d55b3043 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -190,15 +190,13 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common - cp debian/mariadb-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 - cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 + cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ mkdir -p $$d; \ - cp debian/mariadb-server-5.5.mysql.init $$d/_etc_init.d_mysql; \ - cp debian/mariadb-server-5.5.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ + cp debian/mariadb-galera-server-5.5.mysql.init $$d/_etc_init.d_mysql; \ + cp debian/mariadb-galera-server-5.5.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ cp debian/additions/debian-start $$d/_etc_mysql_debian-start; # install AppArmor profile From ab6d729816b2877bfe76b7163b1322ac8b83153a Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 19 Nov 2012 13:01:38 +0400 Subject: [PATCH 019/294] MDEV-507 deb/rpm packages for galera builds. Debian packaging, part II. Changes in the set of package-related files. Some were removed, some renamed, as we only keep the mariadb-galera-server package. --- ...> mariadb-galera-server-5.5.README.Debian} | 0 ....5.dirs => mariadb-galera-server-5.5.dirs} | 0 ....files => mariadb-galera-server-5.5.files} | 0 ...nst => mariadb-galera-server-5.5.postinst} | 0 ...ostrm => mariadb-galera-server-5.5.postrm} | 0 ...> mariadb-galera-server-5.5.README.Debian} | 0 ....5.dirs => mariadb-galera-server-5.5.dirs} | 0 ....files => mariadb-galera-server-5.5.files} | 0 ...nst => mariadb-galera-server-5.5.postinst} | 0 ...ostrm => mariadb-galera-server-5.5.postrm} | 0 debian/libmariadbclient-dev.README.Maintainer | 4 - debian/libmariadbclient-dev.dirs | 2 - debian/libmariadbclient-dev.examples | 1 - debian/libmariadbclient-dev.files | 7 -- debian/libmariadbclient-dev.links | 2 - debian/libmariadbclient18.dirs | 1 - debian/libmariadbclient18.files | 1 - debian/libmariadbclient18.postinst | 12 --- debian/libmariadbd-dev.files | 2 - debian/mariadb-client-5.5.README.Debian | 4 - debian/mariadb-client-5.5.dirs | 3 - debian/mariadb-client-5.5.docs | 2 - debian/mariadb-client-5.5.files | 31 ------ debian/mariadb-client-5.5.links | 3 - debian/mariadb-client-5.5.lintian-overrides | 3 - debian/mariadb-client-5.5.menu | 3 - debian/mariadb-client-core-5.5.files | 4 - debian/mariadb-common.files | 1 - debian/mariadb-common.postrm | 8 -- ....5.NEWS => mariadb-galera-server-5.5.NEWS} | 0 ...onfig => mariadb-galera-server-5.5.config} | 0 ...riadb-galera-server-5.5.lintian-overrides} | 0 ...alera-server-5.5.logcheck.ignore.paranoid} | 0 ...-galera-server-5.5.logcheck.ignore.server} | 0 ...ra-server-5.5.logcheck.ignore.workstation} | 0 ...-galera-server-5.5.mysql-server.logrotate} | 0 ...t => mariadb-galera-server-5.5.mysql.init} | 0 ...inst => mariadb-galera-server-5.5.preinst} | 0 ....prerm => mariadb-galera-server-5.5.prerm} | 0 debian/mariadb-server-core-5.5.files | 26 ----- debian/mariadb-test-5.5.dirs | 98 ------------------- debian/mariadb-test-5.5.files | 9 -- debian/mariadb-test-5.5.links | 2 - debian/mysql-common.dirs | 1 - debian/mysql-common.files | 3 - debian/mysql-common.lintian-overrides | 2 - debian/mysql-common.postrm | 7 -- 47 files changed, 242 deletions(-) rename debian/dist/Debian/{mariadb-server-5.5.README.Debian => mariadb-galera-server-5.5.README.Debian} (100%) rename debian/dist/Debian/{mariadb-server-5.5.dirs => mariadb-galera-server-5.5.dirs} (100%) rename debian/dist/Debian/{mariadb-server-5.5.files => mariadb-galera-server-5.5.files} (100%) rename debian/dist/Debian/{mariadb-server-5.5.postinst => mariadb-galera-server-5.5.postinst} (100%) rename debian/dist/Debian/{mariadb-server-5.5.postrm => mariadb-galera-server-5.5.postrm} (100%) rename debian/dist/Ubuntu/{mariadb-server-5.5.README.Debian => mariadb-galera-server-5.5.README.Debian} (100%) rename debian/dist/Ubuntu/{mariadb-server-5.5.dirs => mariadb-galera-server-5.5.dirs} (100%) rename debian/dist/Ubuntu/{mariadb-server-5.5.files => mariadb-galera-server-5.5.files} (100%) rename debian/dist/Ubuntu/{mariadb-server-5.5.postinst => mariadb-galera-server-5.5.postinst} (100%) rename debian/dist/Ubuntu/{mariadb-server-5.5.postrm => mariadb-galera-server-5.5.postrm} (100%) delete mode 100644 debian/libmariadbclient-dev.README.Maintainer delete mode 100644 debian/libmariadbclient-dev.dirs delete mode 100644 debian/libmariadbclient-dev.examples delete mode 100644 debian/libmariadbclient-dev.files delete mode 100644 debian/libmariadbclient-dev.links delete mode 100644 debian/libmariadbclient18.dirs delete mode 100644 debian/libmariadbclient18.files delete mode 100644 debian/libmariadbclient18.postinst delete mode 100644 debian/libmariadbd-dev.files delete mode 100644 debian/mariadb-client-5.5.README.Debian delete mode 100644 debian/mariadb-client-5.5.dirs delete mode 100644 debian/mariadb-client-5.5.docs delete mode 100644 debian/mariadb-client-5.5.files delete mode 100644 debian/mariadb-client-5.5.links delete mode 100644 debian/mariadb-client-5.5.lintian-overrides delete mode 100644 debian/mariadb-client-5.5.menu delete mode 100644 debian/mariadb-client-core-5.5.files delete mode 100644 debian/mariadb-common.files delete mode 100644 debian/mariadb-common.postrm rename debian/{mariadb-server-5.5.NEWS => mariadb-galera-server-5.5.NEWS} (100%) rename debian/{mariadb-server-5.5.config => mariadb-galera-server-5.5.config} (100%) rename debian/{mariadb-server-5.5.lintian-overrides => mariadb-galera-server-5.5.lintian-overrides} (100%) rename debian/{mariadb-server-5.5.logcheck.ignore.paranoid => mariadb-galera-server-5.5.logcheck.ignore.paranoid} (100%) rename debian/{mariadb-server-5.5.logcheck.ignore.server => mariadb-galera-server-5.5.logcheck.ignore.server} (100%) rename debian/{mariadb-server-5.5.logcheck.ignore.workstation => mariadb-galera-server-5.5.logcheck.ignore.workstation} (100%) rename debian/{mariadb-server-5.5.mysql-server.logrotate => mariadb-galera-server-5.5.mysql-server.logrotate} (100%) rename debian/{mariadb-server-5.5.mysql.init => mariadb-galera-server-5.5.mysql.init} (100%) rename debian/{mariadb-server-5.5.preinst => mariadb-galera-server-5.5.preinst} (100%) rename debian/{mariadb-server-5.5.prerm => mariadb-galera-server-5.5.prerm} (100%) delete mode 100644 debian/mariadb-server-core-5.5.files delete mode 100644 debian/mariadb-test-5.5.dirs delete mode 100644 debian/mariadb-test-5.5.files delete mode 100644 debian/mariadb-test-5.5.links delete mode 100644 debian/mysql-common.dirs delete mode 100644 debian/mysql-common.files delete mode 100644 debian/mysql-common.lintian-overrides delete mode 100644 debian/mysql-common.postrm diff --git a/debian/dist/Debian/mariadb-server-5.5.README.Debian b/debian/dist/Debian/mariadb-galera-server-5.5.README.Debian similarity index 100% rename from debian/dist/Debian/mariadb-server-5.5.README.Debian rename to debian/dist/Debian/mariadb-galera-server-5.5.README.Debian diff --git a/debian/dist/Debian/mariadb-server-5.5.dirs b/debian/dist/Debian/mariadb-galera-server-5.5.dirs similarity index 100% rename from debian/dist/Debian/mariadb-server-5.5.dirs rename to debian/dist/Debian/mariadb-galera-server-5.5.dirs diff --git a/debian/dist/Debian/mariadb-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files similarity index 100% rename from debian/dist/Debian/mariadb-server-5.5.files rename to debian/dist/Debian/mariadb-galera-server-5.5.files diff --git a/debian/dist/Debian/mariadb-server-5.5.postinst b/debian/dist/Debian/mariadb-galera-server-5.5.postinst similarity index 100% rename from debian/dist/Debian/mariadb-server-5.5.postinst rename to debian/dist/Debian/mariadb-galera-server-5.5.postinst diff --git a/debian/dist/Debian/mariadb-server-5.5.postrm b/debian/dist/Debian/mariadb-galera-server-5.5.postrm similarity index 100% rename from debian/dist/Debian/mariadb-server-5.5.postrm rename to debian/dist/Debian/mariadb-galera-server-5.5.postrm diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.README.Debian b/debian/dist/Ubuntu/mariadb-galera-server-5.5.README.Debian similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.README.Debian rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.README.Debian diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.dirs b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.dirs rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.files rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.files diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.postinst b/debian/dist/Ubuntu/mariadb-galera-server-5.5.postinst similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.postinst rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.postinst diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.postrm b/debian/dist/Ubuntu/mariadb-galera-server-5.5.postrm similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.postrm rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.postrm diff --git a/debian/libmariadbclient-dev.README.Maintainer b/debian/libmariadbclient-dev.README.Maintainer deleted file mode 100644 index f24cdcd519d..00000000000 --- a/debian/libmariadbclient-dev.README.Maintainer +++ /dev/null @@ -1,4 +0,0 @@ -The examples directory includes files that might be needed by some -developers: -- header files not installed by default -- the example file udf_example.c diff --git a/debian/libmariadbclient-dev.dirs b/debian/libmariadbclient-dev.dirs deleted file mode 100644 index f6ad2870431..00000000000 --- a/debian/libmariadbclient-dev.dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/include/ -usr/lib/ diff --git a/debian/libmariadbclient-dev.examples b/debian/libmariadbclient-dev.examples deleted file mode 100644 index f1649c311c4..00000000000 --- a/debian/libmariadbclient-dev.examples +++ /dev/null @@ -1 +0,0 @@ -sql/udf_example.c diff --git a/debian/libmariadbclient-dev.files b/debian/libmariadbclient-dev.files deleted file mode 100644 index 8f56a3065d5..00000000000 --- a/debian/libmariadbclient-dev.files +++ /dev/null @@ -1,7 +0,0 @@ -usr/bin/mysql_config -usr/include/mysql -usr/lib/libmysqlclient.a -usr/lib/libmysqlclient_r.a -usr/lib/libmysqlservices.a -usr/share/aclocal/mysql.m4 -usr/share/man/man1/mysql_config.1 diff --git a/debian/libmariadbclient-dev.links b/debian/libmariadbclient-dev.links deleted file mode 100644 index 0076791dcfa..00000000000 --- a/debian/libmariadbclient-dev.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/libmysqlclient.so.18 usr/lib/libmysqlclient.so -usr/lib/libmysqlclient_r.so.18 usr/lib/libmysqlclient_r.so diff --git a/debian/libmariadbclient18.dirs b/debian/libmariadbclient18.dirs deleted file mode 100644 index 2964de6141b..00000000000 --- a/debian/libmariadbclient18.dirs +++ /dev/null @@ -1 +0,0 @@ -usr/lib/ diff --git a/debian/libmariadbclient18.files b/debian/libmariadbclient18.files deleted file mode 100644 index 5162b7b9639..00000000000 --- a/debian/libmariadbclient18.files +++ /dev/null @@ -1 +0,0 @@ -usr/lib/libmysqlclient*.so.* diff --git a/debian/libmariadbclient18.postinst b/debian/libmariadbclient18.postinst deleted file mode 100644 index 29d3b86f978..00000000000 --- a/debian/libmariadbclient18.postinst +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -e - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - -# vim: ts=4 - - diff --git a/debian/libmariadbd-dev.files b/debian/libmariadbd-dev.files deleted file mode 100644 index 26cb8d0a606..00000000000 --- a/debian/libmariadbd-dev.files +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/mysql/*.a -usr/lib/mysql/*.la diff --git a/debian/mariadb-client-5.5.README.Debian b/debian/mariadb-client-5.5.README.Debian deleted file mode 100644 index b245638f9c9..00000000000 --- a/debian/mariadb-client-5.5.README.Debian +++ /dev/null @@ -1,4 +0,0 @@ -FAQ: - -Q: My completition is gone, why? -A: You have "no-auto-rehash" in the "[mysql]" section of /etc/mysql/my.cnf! diff --git a/debian/mariadb-client-5.5.dirs b/debian/mariadb-client-5.5.dirs deleted file mode 100644 index ceda5922c5d..00000000000 --- a/debian/mariadb-client-5.5.dirs +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/ -usr/share/man/man1/ -usr/share/perl5/ diff --git a/debian/mariadb-client-5.5.docs b/debian/mariadb-client-5.5.docs deleted file mode 100644 index 21446855f51..00000000000 --- a/debian/mariadb-client-5.5.docs +++ /dev/null @@ -1,2 +0,0 @@ -debian/additions/innotop/changelog.innotop -README diff --git a/debian/mariadb-client-5.5.files b/debian/mariadb-client-5.5.files deleted file mode 100644 index 9cb949ea53e..00000000000 --- a/debian/mariadb-client-5.5.files +++ /dev/null @@ -1,31 +0,0 @@ -usr/bin/innochecksum -usr/bin/innotop -usr/bin/mysqlaccess -usr/bin/mysqladmin -usr/bin/mysqlbug -usr/bin/mysqldump -usr/bin/mysqldumpslow -usr/bin/mysql_find_rows -usr/bin/mysql_fix_extensions -usr/bin/mysqlimport -usr/bin/mysqlreport -usr/bin/mysqlshow -usr/bin/mysqlslap -usr/bin/mysql_waitpid -usr/share/lintian/overrides/mariadb-client-5.5 -usr/share/man/man1/innotop.1 -usr/share/man/man1/mysqlaccess.1 -usr/share/man/man1/mysqladmin.1 -usr/share/man/man1/mysqlbug.1 -usr/share/man/man1/mysqldump.1 -usr/share/man/man1/mysqldumpslow.1 -usr/share/man/man1/mysql_find_rows.1 -usr/share/man/man1/mysql_fix_extensions.1 -usr/share/man/man1/mysqlimport.1 -usr/share/man/man1/mysqlman.1 -usr/share/man/man1/mysqlreport.1 -usr/share/man/man1/mysqlshow.1 -usr/share/man/man1/mysqlslap.1 -usr/share/man/man1/mysql_tableinfo.1 -usr/share/man/man1/mysql_waitpid.1 -usr/share/man/man8/mysqlmanager.8 diff --git a/debian/mariadb-client-5.5.links b/debian/mariadb-client-5.5.links deleted file mode 100644 index 247369fa218..00000000000 --- a/debian/mariadb-client-5.5.links +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/mysqlcheck usr/bin/mysqlrepair -usr/bin/mysqlcheck usr/bin/mysqlanalyze -usr/bin/mysqlcheck usr/bin/mysqloptimize diff --git a/debian/mariadb-client-5.5.lintian-overrides b/debian/mariadb-client-5.5.lintian-overrides deleted file mode 100644 index d4dc1a70b1e..00000000000 --- a/debian/mariadb-client-5.5.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -mariadb-client-5.3: package-has-a-duplicate-relation -mariadb-client-5.3: wrong-name-for-upstream-changelog usr/share/doc/mariadb-client-5.3/changelog.innotop.gz -mariadb-client-5.3: pkg-not-in-package-test innotop diff --git a/debian/mariadb-client-5.5.menu b/debian/mariadb-client-5.5.menu deleted file mode 100644 index 1378555c423..00000000000 --- a/debian/mariadb-client-5.5.menu +++ /dev/null @@ -1,3 +0,0 @@ -# According to /usr/share/menu/ policy 1.4, not /usr/share/doc/debian-policy/ -?package(innotop):needs="text" section="Applications/Data Management"\ - title="innotop" command="/usr/bin/innotop" diff --git a/debian/mariadb-client-core-5.5.files b/debian/mariadb-client-core-5.5.files deleted file mode 100644 index a2781309439..00000000000 --- a/debian/mariadb-client-core-5.5.files +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin/mysql -usr/bin/mysqlcheck -usr/share/man/man1/mysql.1 -usr/share/man/man1/mysqlcheck.1 diff --git a/debian/mariadb-common.files b/debian/mariadb-common.files deleted file mode 100644 index f37e46c45fe..00000000000 --- a/debian/mariadb-common.files +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/mariadb.cnf diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm deleted file mode 100644 index 027592f816e..00000000000 --- a/debian/mariadb-common.postrm +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql/conf.d 2>/dev/null || true - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# diff --git a/debian/mariadb-server-5.5.NEWS b/debian/mariadb-galera-server-5.5.NEWS similarity index 100% rename from debian/mariadb-server-5.5.NEWS rename to debian/mariadb-galera-server-5.5.NEWS diff --git a/debian/mariadb-server-5.5.config b/debian/mariadb-galera-server-5.5.config similarity index 100% rename from debian/mariadb-server-5.5.config rename to debian/mariadb-galera-server-5.5.config diff --git a/debian/mariadb-server-5.5.lintian-overrides b/debian/mariadb-galera-server-5.5.lintian-overrides similarity index 100% rename from debian/mariadb-server-5.5.lintian-overrides rename to debian/mariadb-galera-server-5.5.lintian-overrides diff --git a/debian/mariadb-server-5.5.logcheck.ignore.paranoid b/debian/mariadb-galera-server-5.5.logcheck.ignore.paranoid similarity index 100% rename from debian/mariadb-server-5.5.logcheck.ignore.paranoid rename to debian/mariadb-galera-server-5.5.logcheck.ignore.paranoid diff --git a/debian/mariadb-server-5.5.logcheck.ignore.server b/debian/mariadb-galera-server-5.5.logcheck.ignore.server similarity index 100% rename from debian/mariadb-server-5.5.logcheck.ignore.server rename to debian/mariadb-galera-server-5.5.logcheck.ignore.server diff --git a/debian/mariadb-server-5.5.logcheck.ignore.workstation b/debian/mariadb-galera-server-5.5.logcheck.ignore.workstation similarity index 100% rename from debian/mariadb-server-5.5.logcheck.ignore.workstation rename to debian/mariadb-galera-server-5.5.logcheck.ignore.workstation diff --git a/debian/mariadb-server-5.5.mysql-server.logrotate b/debian/mariadb-galera-server-5.5.mysql-server.logrotate similarity index 100% rename from debian/mariadb-server-5.5.mysql-server.logrotate rename to debian/mariadb-galera-server-5.5.mysql-server.logrotate diff --git a/debian/mariadb-server-5.5.mysql.init b/debian/mariadb-galera-server-5.5.mysql.init similarity index 100% rename from debian/mariadb-server-5.5.mysql.init rename to debian/mariadb-galera-server-5.5.mysql.init diff --git a/debian/mariadb-server-5.5.preinst b/debian/mariadb-galera-server-5.5.preinst similarity index 100% rename from debian/mariadb-server-5.5.preinst rename to debian/mariadb-galera-server-5.5.preinst diff --git a/debian/mariadb-server-5.5.prerm b/debian/mariadb-galera-server-5.5.prerm similarity index 100% rename from debian/mariadb-server-5.5.prerm rename to debian/mariadb-galera-server-5.5.prerm diff --git a/debian/mariadb-server-core-5.5.files b/debian/mariadb-server-core-5.5.files deleted file mode 100644 index 5c60ca5ec67..00000000000 --- a/debian/mariadb-server-core-5.5.files +++ /dev/null @@ -1,26 +0,0 @@ -usr/sbin/mysqld -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian diff --git a/debian/mariadb-test-5.5.dirs b/debian/mariadb-test-5.5.dirs deleted file mode 100644 index 2c10b45efba..00000000000 --- a/debian/mariadb-test-5.5.dirs +++ /dev/null @@ -1,98 +0,0 @@ -usr/bin -usr/share/man/man1 -usr/share/mysql/mysql-test -usr/share/mysql/mysql-test/extra -usr/share/mysql/mysql-test/extra/binlog_tests -usr/share/mysql/mysql-test/extra/rpl_tests -usr/share/mysql/mysql-test/lib -usr/share/mysql/mysql-test/lib/My -usr/share/mysql/mysql-test/lib/My/SafeProcess -usr/share/mysql/mysql-test/lib/My/File -usr/share/mysql/mysql-test/lib/v1 -usr/share/mysql/mysql-test/lib/v1/My -usr/share/mysql/mysql-test/collections -usr/share/mysql/mysql-test/t -usr/share/mysql/mysql-test/r -usr/share/mysql/mysql-test/include -usr/share/mysql/mysql-test/suite -usr/share/mysql/mysql-test/suite/parts -usr/share/mysql/mysql-test/suite/parts/inc -usr/share/mysql/mysql-test/suite/parts/t -usr/share/mysql/mysql-test/suite/parts/r -usr/share/mysql/mysql-test/suite/rpl_ndb -usr/share/mysql/mysql-test/suite/rpl_ndb/t -usr/share/mysql/mysql-test/suite/rpl_ndb/r -usr/share/mysql/mysql-test/suite/bugs -usr/share/mysql/mysql-test/suite/bugs/t -usr/share/mysql/mysql-test/suite/bugs/r -usr/share/mysql/mysql-test/suite/bugs/data -usr/share/mysql/mysql-test/suite/rpl -usr/share/mysql/mysql-test/suite/rpl/t -usr/share/mysql/mysql-test/suite/rpl/r -usr/share/mysql/mysql-test/suite/rpl/include -usr/share/mysql/mysql-test/suite/innodb -usr/share/mysql/mysql-test/suite/innodb/t -usr/share/mysql/mysql-test/suite/innodb/r -usr/share/mysql/mysql-test/suite/innodb/include -usr/share/mysql/mysql-test/suite/manual -usr/share/mysql/mysql-test/suite/manual/t -usr/share/mysql/mysql-test/suite/manual/r -usr/share/mysql/mysql-test/suite/stress -usr/share/mysql/mysql-test/suite/stress/t -usr/share/mysql/mysql-test/suite/stress/r -usr/share/mysql/mysql-test/suite/stress/include -usr/share/mysql/mysql-test/suite/jp -usr/share/mysql/mysql-test/suite/jp/t -usr/share/mysql/mysql-test/suite/jp/r -usr/share/mysql/mysql-test/suite/jp/include -usr/share/mysql/mysql-test/suite/jp/std_data -usr/share/mysql/mysql-test/suite/ndb -usr/share/mysql/mysql-test/suite/ndb/t -usr/share/mysql/mysql-test/suite/ndb/r -usr/share/mysql/mysql-test/suite/maria -usr/share/mysql/mysql-test/suite/maria/t -usr/share/mysql/mysql-test/suite/maria/r -usr/share/mysql/mysql-test/suite/funcs_2 -usr/share/mysql/mysql-test/suite/funcs_2/lib -usr/share/mysql/mysql-test/suite/funcs_2/t -usr/share/mysql/mysql-test/suite/funcs_2/charset -usr/share/mysql/mysql-test/suite/funcs_2/r -usr/share/mysql/mysql-test/suite/funcs_2/include -usr/share/mysql/mysql-test/suite/funcs_2/data -usr/share/mysql/mysql-test/suite/binlog -usr/share/mysql/mysql-test/suite/binlog/t -usr/share/mysql/mysql-test/suite/binlog/r -usr/share/mysql/mysql-test/suite/binlog/std_data -usr/share/mysql/mysql-test/suite/ndb_team -usr/share/mysql/mysql-test/suite/ndb_team/t -usr/share/mysql/mysql-test/suite/ndb_team/r -usr/share/mysql/mysql-test/suite/federated -usr/share/mysql/mysql-test/suite/pbxt -usr/share/mysql/mysql-test/suite/pbxt/t -usr/share/mysql/mysql-test/suite/pbxt/r -usr/share/mysql/mysql-test/suite/funcs_1 -usr/share/mysql/mysql-test/suite/funcs_1/cursors -usr/share/mysql/mysql-test/suite/funcs_1/bitdata -usr/share/mysql/mysql-test/suite/funcs_1/views -usr/share/mysql/mysql-test/suite/funcs_1/storedproc -usr/share/mysql/mysql-test/suite/funcs_1/triggers -usr/share/mysql/mysql-test/suite/funcs_1/lib -usr/share/mysql/mysql-test/suite/funcs_1/t -usr/share/mysql/mysql-test/suite/funcs_1/r -usr/share/mysql/mysql-test/suite/funcs_1/include -usr/share/mysql/mysql-test/suite/funcs_1/datadict -usr/share/mysql/mysql-test/suite/vcol -usr/share/mysql/mysql-test/suite/vcol/inc -usr/share/mysql/mysql-test/suite/vcol/t -usr/share/mysql/mysql-test/suite/vcol/r -usr/share/mysql/mysql-test/suite/oqgraph -usr/share/mysql/mysql-test/suite/oqgraph/t -usr/share/mysql/mysql-test/suite/oqgraph/r -usr/share/mysql/mysql-test/suite/oqgraph/include -usr/share/mysql/mysql-test/std_data -usr/share/mysql/mysql-test/std_data/ndb_backup50 -usr/share/mysql/mysql-test/std_data/parts -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_le -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_be -usr/share/mysql/mysql-test/std_data/ndb_backup51 -usr/share/mysql/mysql-test/std_data/funcs_1 diff --git a/debian/mariadb-test-5.5.files b/debian/mariadb-test-5.5.files deleted file mode 100644 index ac4fc1c4fca..00000000000 --- a/debian/mariadb-test-5.5.files +++ /dev/null @@ -1,9 +0,0 @@ -usr/bin/mysql_client_test -usr/bin/mysql_client_test_embedded -usr/bin/mysqltest_embedded -usr/share/man/man1/mysql_client_test.1 -usr/share/man/man1/mysql_client_test_embedded.1 -usr/bin/mysqltest -usr/share/man/man1/mysqltest.1 -usr/share/man/man1/mysqltest_embedded.1 -usr/share/mysql/mysql-test diff --git a/debian/mariadb-test-5.5.links b/debian/mariadb-test-5.5.links deleted file mode 100644 index 082680fe5ed..00000000000 --- a/debian/mariadb-test-5.5.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mysql-test-run -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mtr diff --git a/debian/mysql-common.dirs b/debian/mysql-common.dirs deleted file mode 100644 index a5a88ede9c1..00000000000 --- a/debian/mysql-common.dirs +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/ diff --git a/debian/mysql-common.files b/debian/mysql-common.files deleted file mode 100644 index d167569e892..00000000000 --- a/debian/mysql-common.files +++ /dev/null @@ -1,3 +0,0 @@ -etc/mysql/my.cnf -usr/share/mysql-common/internal-use-only -usr/share/lintian/overrides/mysql-common diff --git a/debian/mysql-common.lintian-overrides b/debian/mysql-common.lintian-overrides deleted file mode 100644 index c6c60ccdc71..00000000000 --- a/debian/mysql-common.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_init.d_mysql -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_mysql_debian-start diff --git a/debian/mysql-common.postrm b/debian/mysql-common.postrm deleted file mode 100644 index 0d3f8aed83d..00000000000 --- a/debian/mysql-common.postrm +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# From 30be3f7f1203c45688d51f93ae0a00e4c19276a5 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 27 Nov 2012 16:22:10 +0400 Subject: [PATCH 020/294] MDEV-507 deb/rpm packages for galera builds. If settings are not suitable for the WSREP, just turn it off and keep working. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 45e4f6fe905..cfda1b344dc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3701,7 +3701,7 @@ static int init_common_variables() #ifdef WITH_WSREP /* This is a protection against mutually incompatible option values. */ if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv)) - return 1; + global_system_variables.wsrep_on= 0; #endif /* WITH_WSREP */ if (get_options(&remaining_argc, &remaining_argv)) return 1; From 8ef2eb445431706cbf41849b35b9a40450f08a03 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 27 Nov 2012 16:32:01 +0400 Subject: [PATCH 021/294] MDEV 507 deb/rpm packages for galera builds. lindian-overrides files fixed. --- debian/mariadb-galera-server-5.5.lintian-overrides | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/debian/mariadb-galera-server-5.5.lintian-overrides b/debian/mariadb-galera-server-5.5.lintian-overrides index a5075e2231a..377e6e0dd75 100644 --- a/debian/mariadb-galera-server-5.5.lintian-overrides +++ b/debian/mariadb-galera-server-5.5.lintian-overrides @@ -1,5 +1,5 @@ -mariadb-server-5.5: command-with-path-in-maintainer-script postinst -mariadb-server-5.5: possible-bashism-in-maintainer-script postinst:81 'p{("a".."z","A".."Z",0..9)[int(rand(62))]}' -mariadb-server-5.5: possible-bashism-in-maintainer-script preinst:33 '${cmd/ */}' -mariadb-server-5.5: statically-linked-binary ./usr/bin/mysql_tzinfo_to_sql -mariadb-server-5.5: statically-linked-binary ./usr/sbin/mysqld +mariadb-galera-server-5.5: command-with-path-in-maintainer-script postinst +mariadb-galera-server-5.5: possible-bashism-in-maintainer-script postinst:81 'p{("a".."z","A".."Z",0..9)[int(rand(62))]}' +mariadb-galera-server-5.5: possible-bashism-in-maintainer-script preinst:33 '${cmd/ */}' +mariadb-galera-server-5.5: statically-linked-binary ./usr/bin/mysql_tzinfo_to_sql +mariadb-galera-server-5.5: statically-linked-binary ./usr/sbin/mysqld From fe0188166804de8cfb2ab9598ce58f786ba47eb7 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 28 Nov 2012 17:15:46 +0400 Subject: [PATCH 022/294] MDEV-507 deb/rpm packages for Galera. Ubuntu 'control' file fixed. --- debian/dist/Ubuntu/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 7c1a087b598..8ad7471815c 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -10,7 +10,7 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria -Package: mariadb-server-5.5 +Package: mariadb-galera-server-5.5 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl From fc6cd855e9dd1b89a45f6584b3bd21ddc1f60607 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 28 Nov 2012 17:38:32 +0200 Subject: [PATCH 023/294] References: lp:1066784 - Merged revisions 3810-3827 from lp:codership-mysql --- cmake/wsrep.cmake | 2 +- mysys/default.c | 4 +- scripts/mysqld_safe.sh | 37 +++++++-- scripts/wsrep_sst_rsync.sh | 2 +- scripts/wsrep_sst_xtrabackup.sh | 8 +- sql/lock.cc | 18 ++--- sql/mdl.cc | 30 ++++++++ sql/mdl.h | 3 + sql/mysqld.cc | 104 ++++++++++++++------------ sql/slave.cc | 6 +- sql/sql_parse.cc | 29 ++++--- sql/sys_vars.cc | 8 +- sql/wsrep_mysqld.cc | 60 +++++++++++---- sql/wsrep_mysqld.h | 10 +-- sql/wsrep_sst.cc | 4 +- sql/wsrep_utils.cc | 5 +- sql/wsrep_var.cc | 44 +++++++---- storage/innobase/dict/dict0dict.c | 21 +++++- storage/innobase/handler/ha_innodb.cc | 85 +++++++++++++++++++-- storage/xtradb/dict/dict0dict.c | 21 +++++- storage/xtradb/handler/ha_innodb.cc | 88 +++++++++++++++++++++- 21 files changed, 453 insertions(+), 136 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index bfdf477d421..b0c1dce34dc 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7") +SET(WSREP_PATCH_VERSION "7rc1") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/mysys/default.c b/mysys/default.c index f331668de9f..0ba7ed494af 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -810,7 +810,9 @@ static int search_default_file_with_ext(Process_option_func opt_handler, return 1; /* Ignore wrong files */ #ifdef WITH_WSREP - strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1); + /* make sure we do this only once - for top-level file */ + if ('\0' == wsrep_defaults_file[0]) + strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1); #endif /* WITH_WSREP */ while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 72430cd19f6..8371b8eec46 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -63,7 +63,6 @@ Usage: $0 [OPTIONS] --syslog Log messages to syslog with 'logger' --skip-syslog Log messages to error log (default) --syslog-tag=TAG Pass -t "mysqld-TAG" to 'logger' - --wsrep-urls=WSREP_URLS Comma-separated list of wsrep URLs All other options are passed to the mysqld program. @@ -126,7 +125,7 @@ log_notice () { } eval_log_error () { - cmd="$1" + local cmd="$1" case $logging in file) cmd="$cmd >> "`shell_quote_string "$err_log"`" 2>&1" ;; syslog) @@ -165,6 +164,8 @@ shell_quote_string() { wsrep_pick_url() { [ $# -eq 0 ] && return 0 + log_error "WSREP: 'wsrep_urls' is DEPRECATED! Use wsrep_cluster_address to specify multiple addresses instead." + if ! which nc >/dev/null; then log_error "ERROR: nc tool not found in PATH! Make sure you have it installed." return 1 @@ -193,10 +194,12 @@ wsrep_pick_url() { # Run mysqld with --wsrep-recover and parse recovered position from log. # Position will be stored in wsrep_start_position_opt global. wsrep_recovery() { - cmd="$@" + local mysqld_cmd="$@" wr_logfile=$(mktemp) - log_notice "WSREP: Running position recovery" - $cmd --log_error=$wr_logfile --wsrep-recover + [ "$EUID" = "0" ] && chown $user $wr_logfile + chmod 600 $wr_logfile + log_notice "WSREP: Running position recovery with --log_error=$wr_logfile" + $mysqld_cmd --log_error=$wr_logfile --wsrep-recover rp=$(grep "WSREP: Recovered position:" $wr_logfile) if [ -z "$rp" ]; then skipped=$(grep WSREP $wr_logfile | grep "skipping position recovery") @@ -276,7 +279,12 @@ parse_arguments() { --syslog-tag=*) syslog_tag="$val" ;; --timezone=*) TZ="$val"; export TZ; ;; --wsrep[-_]urls=*) wsrep_urls="$val"; ;; - + --wsrep[-_]provider=*) + if test -n "$val" && test "$val" != "none" + then + wsrep_restart=1 + fi + ;; --help) usage ;; *) @@ -824,6 +832,9 @@ max_fast_restarts=5 # flag whether a usable sleep command exists have_sleep=1 +# maximum number of wsrep restarts +max_wsrep_restarts=0 + while true do rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety @@ -903,6 +914,20 @@ do I=`expr $I + 1` done fi + + if [ -n "$wsrep_restart" ] + then + if [ $wsrep_restart -le $max_wsrep_restarts ] + then + wsrep_restart=`expr $wsrep_restart + 1` + log_notice "WSREP: sleeping 15 seconds before restart" + sleep 15 + else + log_notice "WSREP: not restarting wsrep node automatically" + break + fi + fi + log_notice "mysqld restarted" done diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index d346eb240f2..d510477535c 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -38,7 +38,7 @@ cleanup_joiner() check_pid() { local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + [ -r "$pid_file" ] && ps -p $(cat $pid_file) >/dev/null 2>&1 } check_pid_and_port() diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index dd8532d6485..08552f50a44 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -34,8 +34,8 @@ cleanup_joiner() check_pid() { - local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + local pid_file="$1" + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 } kill_xtrabackup() @@ -133,14 +133,14 @@ then exit 22 fi - if check_pid ${XTRABACKUP_PID} + if check_pid "${XTRABACKUP_PID}" then wsrep_log_error "xtrabackup process is still running. Killing... " kill_xtrabackup exit 22 fi - rm -f ${XTRABACKUP_PID} + rm -f "${XTRABACKUP_PID}" else # BYPASS STATE="${WSREP_SST_OPT_GTID}" diff --git a/sql/lock.cc b/sql/lock.cc index 854e7ddf78d..c8ca26561e6 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1121,6 +1121,15 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) if (m_state != GRL_ACQUIRED) DBUG_RETURN(0); + mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); + + if (thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(TRUE); + + m_mdl_blocks_commits_lock= mdl_request.ticket; + m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; + #ifdef WITH_WSREP long long ret = wsrep->pause(wsrep); if (ret >= 0) @@ -1137,15 +1146,6 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) DBUG_RETURN(TRUE); } #endif /* WITH_WSREP */ - mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); - - if (thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) - DBUG_RETURN(TRUE); - - m_mdl_blocks_commits_lock= mdl_request.ticket; - m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; - DBUG_RETURN(FALSE); } diff --git a/sql/mdl.cc b/sql/mdl.cc index 8527c027937..e2c633b486e 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -3015,3 +3015,33 @@ void MDL_context::set_transaction_duration_for_all_locks() ticket->m_duration= MDL_TRANSACTION; #endif } +#ifdef WITH_WSREP +void MDL_ticket::wsrep_report(bool debug) +{ + if (debug) + { + WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)", + (get_type() == MDL_INTENTION_EXCLUSIVE) ? "intention exclusive" : + ((get_type() == MDL_SHARED) ? "shared" : + ((get_type() == MDL_SHARED_HIGH_PRIO ? "shared high prio" : + ((get_type() == MDL_SHARED_READ) ? "shared read" : + ((get_type() == MDL_SHARED_WRITE) ? "shared write" : + ((get_type() == MDL_SHARED_NO_WRITE) ? "shared no write" : + ((get_type() == MDL_SHARED_NO_READ_WRITE) ? "shared no read write" : + ((get_type() == MDL_EXCLUSIVE) ? "exclusive" : + "UNKNOWN")))))))), + (m_lock->key.mdl_namespace() == MDL_key::GLOBAL) ? "GLOBAL" : + ((m_lock->key.mdl_namespace() == MDL_key::SCHEMA) ? "SCHEMA" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "TABLE" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "FUNCTION" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "PROCEDURE" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "TRIGGER" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "EVENT" : + ((m_lock->key.mdl_namespace() == MDL_key::COMMIT) ? "COMMIT" : + (char *)"UNKNOWN"))))))), + m_lock->key.db_name(), + m_lock->key.name(), + m_lock->key.get_wait_state_name()); + } +} +#endif /* WITH_WSREP */ diff --git a/sql/mdl.h b/sql/mdl.h index af7d75c1297..0f99b759c0e 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -475,6 +475,9 @@ public: MDL_ticket *next_in_lock; MDL_ticket **prev_in_lock; public: +#ifdef WITH_WSREP + void wsrep_report(bool debug); +#endif /* WITH_WSREP */ bool has_pending_conflicting_lock() const; MDL_context *get_ctx() const { return m_ctx; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 45e4f6fe905..b441c31b28d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3639,7 +3639,13 @@ static int init_common_variables() } else opt_log_basename= glob_hostname; - +#ifdef WITH_WSREP + if (0 == wsrep_node_name || 0 == wsrep_node_name[0]) + { + my_free((void *)wsrep_node_name); + wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME)); + } +#endif /* WITH_WSREP */ if (!*pidfile_name) { strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5); @@ -4390,29 +4396,37 @@ will be ignored as the --log-bin option is not defined."); } #endif -/* WSREP BEFORE */ -#ifdef WITH_WSREP - // add basedir/bin to PATH to resolve wsrep script names - char* const tmp_path((char*)alloca(strlen(mysql_home) + strlen("/bin") + 1)); - if (tmp_path) +#ifdef WITH_WSREP /* WSREP BEFORE SE */ + if (!wsrep_recovery) { - strcpy(tmp_path, mysql_home); - strcat(tmp_path, "/bin"); - wsrep_prepend_PATH(tmp_path); - } - else - { - WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); - } + if (opt_bootstrap) // bootsrap option given - disable wsrep functionality + { + wsrep_provider_init(WSREP_NONE); + if (wsrep_init()) unireg_abort(1); + } + else // full wsrep initialization + { + // add basedir/bin to PATH to resolve wsrep script names + char* const tmp_path((char*)alloca(strlen(mysql_home) + + strlen("/bin") + 1)); + if (tmp_path) + { + strcpy(tmp_path, mysql_home); + strcat(tmp_path, "/bin"); + wsrep_prepend_PATH(tmp_path); + } + else + { + WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); + } - if (opt_bootstrap) - { - wsrep_provider_init(WSREP_NONE); - if (wsrep_init()) unireg_abort(1); - } - else if (!wsrep_recovery && wsrep_init_first()) - { - wsrep_init_startup(true); + if (wsrep_before_SE()) + { + set_ports(); // this is also called in network_init() later but we need + // to know mysqld_port now - lp:1071882 + wsrep_init_startup(true); + } + } } #endif /* WITH_WSREP */ if (opt_bin_log) @@ -5622,32 +5636,37 @@ int mysqld_main(int argc, char **argv) if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); -/* WSREP AFTER */ -#ifdef WITH_WSREP - wsrep_SE_initialized(); - if (opt_bootstrap) - { - /*! bootstrap wsrep init was taken care of above */ - } - else if (wsrep_recovery) +#ifdef WITH_WSREP /* WSREP AFTER SE */ + if (wsrep_recovery) { select_thread_in_use= 0; wsrep_recover(); unireg_abort(0); } - else if (wsrep_init_first()) + + if (opt_bootstrap) { - /*! 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 */ - wsrep_sst_continue(); + /*! bootstrap wsrep init was taken care of above */ } else { - wsrep_init_startup (false); + 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 */ + wsrep_sst_continue(); + } + else + { + wsrep_init_startup (false); + } + + wsrep_create_appliers(wsrep_slave_threads - 1); } - wsrep_create_appliers(wsrep_slave_threads - 1); #endif /* WITH_WSREP */ if (opt_bootstrap) { @@ -8451,15 +8470,6 @@ mysqld_get_one_option(int optid, lower_case_table_names_used= 1; break; #ifdef WITH_WSREP - case OPT_WSREP_PROVIDER: - wsrep_provider_init (argument); - break; - case OPT_WSREP_PROVIDER_OPTIONS: - wsrep_provider_options_init (argument); - break; - case OPT_WSREP_CLUSTER_ADDRESS: - wsrep_cluster_address_init (argument); - break; case OPT_WSREP_START_POSITION: wsrep_start_position_init (argument); break; diff --git a/sql/slave.cc b/sql/slave.cc index b928b658f51..7e082971d6c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2601,10 +2601,10 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) int reason= ev->shall_skip(rli); #ifdef WITH_WSREP - if (ev->get_type_code() == XID_EVENT || + if (WSREP_ON && (ev->get_type_code() == XID_EVENT || (ev->get_type_code() == QUERY_EVENT && thd->wsrep_mysql_replicated > 0 && (!strncasecmp(((Query_log_event*)ev)->query , "BEGIN", 5) || - !strncasecmp(((Query_log_event*)ev)->query , "COMMIT", 6) ))) + !strncasecmp(((Query_log_event*)ev)->query , "COMMIT", 6) )))) { if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) { @@ -3568,7 +3568,7 @@ pthread_handler_t handle_slave_sql(void *arg) #ifdef WITH_WSREP thd->wsrep_exec_mode= LOCAL_STATE; /* synchronize with wsrep replication */ - wsrep_ready_wait (); + if (WSREP_ON) wsrep_ready_wait(); #endif DBUG_PRINT("master_info",("log_file_name: %s position: %s", rli->group_master_log_name, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1e9561e895b..03398987818 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1059,7 +1059,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->mysys_var->abort = 0; thd->wsrep_conflict_state = NO_CONFLICT; thd->wsrep_retry_counter = 0; - + /* + Increment threads running to compensate dec_thread_running() called + after dispatch_end label. + */ + inc_thread_running(); goto dispatch_end; } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -4883,7 +4887,6 @@ finish: thd_proc_info(thd, "closing tables"); close_thread_tables(thd); #ifdef WITH_WSREP - WSREP_TO_ISOLATION_END thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; #endif /* WITH_WSREP */ thd_proc_info(thd, 0); @@ -4922,6 +4925,7 @@ finish: { thd->mdl_context.release_statement_locks(); } + WSREP_TO_ISOLATION_END DBUG_RETURN(res || thd->is_error()); } @@ -6127,14 +6131,14 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, { mysql_reset_thd_for_next_command(thd, opt_userstat_running); thd->killed= NOT_KILLED; - if (is_autocommit && - (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) + if (is_autocommit && + thd->lex->sql_command != SQLCOM_SELECT && + (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) { WSREP_DEBUG("wsrep retrying AC query: %s", (thd->query()) ? thd->query() : "void"); - - close_thread_tables(thd); + close_thread_tables(thd); thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; thd->wsrep_retry_counter++; // grow @@ -6166,7 +6170,12 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, if (thd->wsrep_retry_query) { - WSREP_DEBUG("releasing retry_query: %s", thd->wsrep_retry_query); + WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s", + thd->wsrep_conflict_state, + thd->stmt_da->is_sent, + thd->killed, + thd->stmt_da->is_error() ? thd->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; @@ -8316,8 +8325,6 @@ void wsrep_replication_process(THD *thd) struct wsrep_thd_shadow shadow; wsrep_prepare_bf_thd(thd, &shadow); - wsrep_format_desc= new Format_description_log_event(4); - rcode = wsrep->recv(wsrep, (void *)thd); DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode)); @@ -8428,8 +8435,8 @@ void wsrep_rollback_process(THD *thd) mysql_mutex_lock(&aborting->LOCK_wsrep_thd); wsrep_client_rollback(aborting); - WSREP_DEBUG("WSREP rollbacker aborted thd: %llu", - (long long)aborting->real_id); + WSREP_DEBUG("WSREP rollbacker aborted thd: (%lu %llu)", + aborting->thread_id, (long long)aborting->real_id); mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); mysql_mutex_lock(&LOCK_wsrep_rollback); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 49be8e79e3b..1efe724e6f9 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3620,7 +3620,7 @@ static Sys_var_tz Sys_time_zone( static Sys_var_charptr Sys_wsrep_provider( "wsrep_provider", "Path to replication provider library", - GLOBAL_VAR(wsrep_provider), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER), + PREALLOCATED GLOBAL_VAR(wsrep_provider), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER), IN_FS_CHARSET, DEFAULT(wsrep_provider), // IN_FS_CHARSET, DEFAULT(wsrep_provider_default), NO_MUTEX_GUARD, NOT_IN_BINLOG, @@ -3628,7 +3628,7 @@ static Sys_var_charptr Sys_wsrep_provider( static Sys_var_charptr Sys_wsrep_provider_options( "wsrep_provider_options", "provider specific options", - GLOBAL_VAR(wsrep_provider_options), + PREALLOCATED GLOBAL_VAR(wsrep_provider_options), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER_OPTIONS), IN_FS_CHARSET, DEFAULT(wsrep_provider_options), NO_MUTEX_GUARD, NOT_IN_BINLOG, @@ -3652,7 +3652,7 @@ static Sys_var_charptr Sys_wsrep_cluster_name( static PolyLock_mutex PLock_wsrep_slave_threads(&LOCK_wsrep_slave_threads); static Sys_var_charptr Sys_wsrep_cluster_address ( "wsrep_cluster_address", "Address to initially connect to cluster", - GLOBAL_VAR(wsrep_cluster_address), + PREALLOCATED GLOBAL_VAR(wsrep_cluster_address), CMD_LINE(REQUIRED_ARG, OPT_WSREP_CLUSTER_ADDRESS), IN_FS_CHARSET, DEFAULT(wsrep_cluster_address), &PLock_wsrep_slave_threads, NOT_IN_BINLOG, @@ -3741,7 +3741,7 @@ static Sys_var_charptr Sys_wsrep_sst_receive_address( static Sys_var_charptr Sys_wsrep_sst_auth( "wsrep_sst_auth", "Authentication for SST connection", - GLOBAL_VAR(wsrep_sst_auth), CMD_LINE(REQUIRED_ARG, OPT_WSREP_SST_AUTH), + PREALLOCATED GLOBAL_VAR(wsrep_sst_auth), CMD_LINE(REQUIRED_ARG, OPT_WSREP_SST_AUTH), IN_FS_CHARSET, DEFAULT(wsrep_sst_auth), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_sst_auth_check), diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c31c02e6d33..62397c58a6e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -21,6 +21,7 @@ #include #include "log_event.h" +extern Format_description_log_event *wsrep_format_desc; wsrep_t *wsrep = NULL; my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface @@ -94,6 +95,11 @@ wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; long wsrep_protocol_version = 2; +// 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; + // action execute callback extern wsrep_status_t wsrep_apply_cb(void *ctx, const void* buf, size_t buf_len, @@ -283,13 +289,12 @@ static void wsrep_view_handler_cb (void* app_ctx, * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized * before - OR - it was reinitilized on startup (lp:992840) */ - if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) || - 0 == wsrep_cluster_conf_id) + if (wsrep_startup) { - if (wsrep_init_first()) + if (wsrep_before_SE()) { wsrep_SE_init_grab(); - // Signal init thread to continue + // Signal mysqld init thread to continue wsrep_sst_complete (&cluster_uuid, view->seqno, false); // and wait for SE initialization wsrep_SE_init_wait(); @@ -305,15 +310,14 @@ static void wsrep_view_handler_cb (void* app_ctx, wsrep_set_SE_checkpoint(&xid); new_status= WSREP_MEMBER_JOINED; } - else // just some sanity check + + // just some sanity check + if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t))) { - 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->seqno, - &local_uuid, -1); - abort(); - } + WSREP_ERROR("Undetected state gap. Can't continue."); + wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->seqno, + &local_uuid, -1); + unireg_abort(1); } } @@ -324,7 +328,7 @@ static void wsrep_view_handler_cb (void* app_ctx, } out: - + wsrep_startup= FALSE; local_status.set(new_status, view); } @@ -415,7 +419,7 @@ int wsrep_init() wsrep_ready_set(FALSE); assert(wsrep_provider); - + wsrep_format_desc= new Format_description_log_event(4); wsrep_init_position(); if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) @@ -476,8 +480,10 @@ int wsrep_init() } static char inc_addr[512]= { 0, }; + if ((!wsrep_node_incoming_address || - !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) + { size_t const node_addr_len= strlen(node_addr); if (node_addr_len > 0) { @@ -579,6 +585,9 @@ void wsrep_deinit() provider_name[0]= '\0'; provider_version[0]= '\0'; provider_vendor[0]= '\0'; + + delete wsrep_format_desc; + wsrep_format_desc= NULL; } void wsrep_recover() @@ -1181,6 +1190,21 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list) { int ret= 0; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) + { + WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", + thd->thread_id, thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + return WSREP_TRX_FAIL; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (wsrep_debug && thd->mdl_context.has_locks()) + { + WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", + thd->query(), thd->thread_id); + } if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { @@ -1236,24 +1260,28 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, { mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); WSREP_MDL_LOG(DEBUG, "MDL conflict ", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || granted_thd->wsrep_exec_mode == REPL_RECV) { WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); + ticket->wsrep_report(true); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) { WSREP_DEBUG("mdl granted over FLUSH BF"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) { WSREP_DEBUG("DROP caused BF abort"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1261,6 +1289,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) { WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1268,6 +1297,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else { WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index d1c72e6001f..6b9640cea70 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -167,7 +167,7 @@ extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_slave_threads_check CHECK_ARGS; extern bool wsrep_slave_threads_update UPDATE_ARGS; -extern bool wsrep_init_first(); // initialize wsrep before storage +extern bool wsrep_before_SE(); // initialize wsrep before storage // engines (true) or after (false) extern int wsrep_init(); extern void wsrep_deinit(); @@ -206,8 +206,8 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); /* wsrep initialization sequence at startup - * @param first wsrep_init_first() value */ -extern void wsrep_init_startup(bool first); + * @param first wsrep_before_SE() value */ +extern void wsrep_init_startup(bool before); extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); @@ -258,11 +258,11 @@ extern wsrep_seqno_t wsrep_locked_seqno; #define WSREP_LOG_CONFLICT_THD(thd, role) \ WSREP_LOG(sql_print_information, \ "%s: \n " \ - " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %ld\n " \ + " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ " SQL: %s", \ role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ wsrep_thd_query_state_str(thd), \ - wsrep_thd_conflict_state_str(thd), wsrep_thd_trx_seqno(thd), \ + wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \ wsrep_thd_query(thd) \ ); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 53e3bbcfc79..597d0ea087d 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -164,10 +164,10 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; -bool wsrep_init_first() +bool wsrep_before_SE() { return (wsrep_provider != NULL - && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_provider, WSREP_NONE) && strcmp (wsrep_sst_method, WSREP_SST_SKIP) && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index b1bd6de07cf..daba0e4cab2 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -354,8 +354,9 @@ size_t guess_ip (char* buf, size_t buf_len) // try to find the address of the first one #if (TARGET_OS_LINUX == 1) const char cmd[] = "/sbin/ifconfig | " - "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +// "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "grep -E '^[[:space:]]+inet addr:' | grep -m1 -v 'inet addr:127' | " + "sed 's/:/ /' | awk '{ print $3 }'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3136f905109..01f91b0a5ae 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -24,21 +24,28 @@ #include #define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" +#define WSREP_CLUSTER_NAME "my_wsrep_cluster" -// trx history position to start with -const char* wsrep_start_position = WSREP_START_POSITION_ZERO; -const char* wsrep_provider = WSREP_NONE; -const char* wsrep_provider_options = (const char*)my_memdup("", 1, MYF(MY_WME)); -const char* wsrep_cluster_address = NULL; -const char* wsrep_cluster_name = "my_wsrep_cluster"; -const char* wsrep_node_name = glob_hostname; -static char node_address[256] = { 0, }; -const char* wsrep_node_address = node_address; +const char* wsrep_provider = 0; +const char* wsrep_provider_options = 0; +const char* wsrep_cluster_address = 0; +const char* wsrep_cluster_name = 0; +const char* wsrep_node_name = 0; +static char node_address[256] = { 0, }; +const char* wsrep_node_address = node_address; // ??? +const char* wsrep_start_position = 0; ulong wsrep_OSU_method_options; static int wsrep_thread_change = 0; int wsrep_init_vars() { + wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME)); + wsrep_provider_options= my_strdup("", MYF(MY_WME)); + wsrep_cluster_address = my_strdup("", MYF(MY_WME)); + wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME)); + wsrep_node_name = my_strdup("", MYF(MY_WME)); + wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME)); + global_system_variables.binlog_format=BINLOG_FORMAT_ROW; return 0; } @@ -152,13 +159,13 @@ void wsrep_start_position_init (const char* val) return; } - wsrep_start_position = my_strdup(val, MYF(0)); - wsrep_set_local_position (val); } static bool refresh_provider_options() { + WSREP_DEBUG("refresh_provider_options: %s", + (wsrep_provider_options) ? wsrep_provider_options : "null"); char* opts= wsrep->options_get(wsrep); if (opts) { @@ -225,6 +232,8 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_on_saved= thd->variables.wsrep_on; thd->variables.wsrep_on= false; + WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider); + wsrep_stop_replication(thd); wsrep_deinit(); @@ -250,12 +259,17 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_provider_init (const char* value) { + WSREP_DEBUG("wsrep_provider_init: %s -> %s", + (wsrep_provider) ? wsrep_provider : "null", + (value) ? value : "null"); if (NULL == value || wsrep_provider_verify (value)) { WSREP_ERROR("Bad initial value for wsrep_provider: %s", (value ? value : "")); return; } + + if (wsrep_provider) my_free((void *)wsrep_provider); wsrep_provider = my_strdup(value, MYF(0)); } @@ -327,9 +341,11 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_cluster_address_init (const char* value) { - if (wsrep_cluster_address && wsrep_cluster_address != value) - my_free ((void*)wsrep_cluster_address); - + WSREP_DEBUG("wsrep_cluster_address_init: %s -> %s", + (wsrep_cluster_address) ? wsrep_cluster_address : "null", + (value) ? value : "null"); + + if (wsrep_cluster_address) my_free ((void*)wsrep_cluster_address); wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; } diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 6f2c2caffaf..d338330585a 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -2489,7 +2489,26 @@ next_rec: return(NULL); } - +#ifdef WITH_WSREP +dict_index_t* +wsrep_dict_foreign_find_index( +/*====================*/ + dict_table_t* table, /*!< in: table */ + const char** columns,/*!< in: array of column names */ + ulint n_cols, /*!< in: number of columns */ + dict_index_t* types_idx, /*!< in: NULL or an index to whose types the + column types must match */ + ibool check_charsets, + /*!< in: whether to check charsets. + only has an effect if types_idx != NULL */ + ulint check_null) + /*!< in: nonzero if none of the columns must + be declared NOT NULL */ +{ + return dict_foreign_find_index( + table, columns, n_cols, types_idx, check_charsets, check_null); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Find an index that is equivalent to the one passed in and is not marked for deletion. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2e1732d7d25..ebcb5fdff6e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6980,6 +6980,15 @@ ha_innobase::rnd_pos( } #ifdef WITH_WSREP extern "C" { +dict_index_t* +wsrep_dict_foreign_find_index( + dict_table_t* table, + const char** columns, + ulint n_cols, + dict_index_t* types_idx, + ibool check_charsets, + ulint check_null); + ulint wsrep_append_foreign_key( /*===========================*/ @@ -6990,15 +6999,75 @@ wsrep_append_foreign_key( ibool referenced, /*!mysql_thd; ulint rcode = DB_SUCCESS; - char cache_key[512] = {'\0'}; + char cache_key[513] = {'\0'}; int cache_key_len; if (!wsrep_on(trx->mysql_thd) || wsrep_thd_exec_mode(thd) != LOCAL_STATE) return DB_SUCCESS; + if (!thd || !foreign || + (!foreign->referenced_table && !foreign->foreign_table)) + { + WSREP_INFO("FK: %s missing in: %s", + (!thd) ? "thread" : + ((!foreign) ? "constraint" : + ((!foreign->referenced_table) ? + "referenced table" : "foreign table")), + (thd && wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_DEBUG("pulling %s table into cache", + (referenced) ? "referenced" : "foreign"); + mutex_enter(&(dict_sys->mutex)); + if (referenced) + { + foreign->referenced_table = + dict_table_check_if_in_cache_low( + foreign->referenced_table_name_lookup); + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } + else + { + foreign->foreign_table = + dict_table_check_if_in_cache_low( + foreign->foreign_table_name_lookup); + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + + } + mutex_exit(&(dict_sys->mutex)); + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_WARN("FK: %s missing in query: %s", + (!foreign->referenced_table) ? + "referenced table" : "foreign table", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; @@ -7022,8 +7091,10 @@ wsrep_append_foreign_key( WSREP_ERROR( "FK key set failed: %lu (%lu %lu), index: %s %s, %s", rcode, referenced, shared, - (index->name) ? index->name : "void index", - (index->table_name) ? index->table_name : "void table", + (index && index->name) ? index->name : + "void index", + (index && index->table_name) ? index->table_name : + "void table", wsrep_thd_query(thd)); return rcode; } @@ -7032,7 +7103,7 @@ wsrep_append_foreign_key( ((referenced) ? foreign->referenced_table->name : foreign->foreign_table->name) : - foreign->foreign_table->name, 512); + foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); #ifdef WSREP_DEBUG_PRINT ulint j; @@ -7048,7 +7119,8 @@ wsrep_append_foreign_key( *p = '\0'; } else { WSREP_WARN("unexpected foreign key table %s %s", - foreign->referenced_table->name, foreign->foreign_table->name); + foreign->referenced_table->name, + foreign->foreign_table->name); } wsrep_key_part_t wkey_part[3]; @@ -12260,6 +12332,9 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, case QUERY_COMMITTING: enum wsrep_status rcode; + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(thd, signal); WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", victim_trx->id); diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 516b6e927e0..0d484dc44cd 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -2560,7 +2560,26 @@ next_rec: return(NULL); } - +#ifdef WITH_WSREP +dict_index_t* +wsrep_dict_foreign_find_index( +/*====================*/ + dict_table_t* table, /*!< in: table */ + const char** columns,/*!< in: array of column names */ + ulint n_cols, /*!< in: number of columns */ + dict_index_t* types_idx, /*!< in: NULL or an index to whose types the + column types must match */ + ibool check_charsets, + /*!< in: whether to check charsets. + only has an effect if types_idx != NULL */ + ulint check_null) + /*!< in: nonzero if none of the columns must + be declared NOT NULL */ +{ + return dict_foreign_find_index( + table, columns, n_cols, types_idx, check_charsets, check_null); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Find an index that is equivalent to the one passed in and is not marked for deletion. diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4258299c486..b84de8f5787 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -7810,6 +7810,15 @@ ha_innobase::rnd_pos( } #ifdef WITH_WSREP extern "C" { +dict_index_t* +wsrep_dict_foreign_find_index( + dict_table_t* table, + const char** columns, + ulint n_cols, + dict_index_t* types_idx, + ibool check_charsets, + ulint check_null); + ulint wsrep_append_foreign_key( /*===========================*/ @@ -7820,15 +7829,75 @@ wsrep_append_foreign_key( ibool referenced, /*!mysql_thd; ulint rcode = DB_SUCCESS; - char cache_key[512] = {'\0'}; + char cache_key[513] = {'\0'}; int cache_key_len; if (!wsrep_on(trx->mysql_thd) || wsrep_thd_exec_mode(thd) != LOCAL_STATE) return DB_SUCCESS; + if (!thd || !foreign || + (!foreign->referenced_table && !foreign->foreign_table)) + { + WSREP_INFO("FK: %s missing in: %s", + (!thd) ? "thread" : + ((!foreign) ? "constraint" : + ((!foreign->referenced_table) ? + "referenced table" : "foreign table")), + (thd && wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_DEBUG("pulling %s table into cache", + (referenced) ? "referenced" : "foreign"); + mutex_enter(&(dict_sys->mutex)); + if (referenced) + { + foreign->referenced_table = + dict_table_check_if_in_cache_low( + foreign->referenced_table_name_lookup); + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } + else + { + foreign->foreign_table = + dict_table_check_if_in_cache_low( + foreign->foreign_table_name_lookup); + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + + } + mutex_exit(&(dict_sys->mutex)); + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_WARN("FK: %s missing in query: %s", + (!foreign->referenced_table) ? + "referenced table" : "foreign table", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; @@ -7849,7 +7918,14 @@ wsrep_append_foreign_key( &key[1], &len, rec, index, wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { - WSREP_ERROR("FK key set failed: %lu", rcode); + WSREP_ERROR( + "FK key set failed: %lu (%lu %lu), index: %s %s, %s", + rcode, referenced, shared, + (index && index->name) ? index->name : + "void index", + (index && index->table_name) ? index->table_name : + "void table", + wsrep_thd_query(thd)); return rcode; } strncpy(cache_key, @@ -7857,7 +7933,7 @@ wsrep_append_foreign_key( ((referenced) ? foreign->referenced_table->name : foreign->foreign_table->name) : - foreign->foreign_table->name, 512); + foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); #ifdef WSREP_DEBUG_PRINT ulint j; @@ -7873,7 +7949,8 @@ wsrep_append_foreign_key( *p = '\0'; } else { WSREP_WARN("unexpected foreign key table %s %s", - foreign->referenced_table->name, foreign->foreign_table->name); + foreign->referenced_table->name, + foreign->foreign_table->name); } wsrep_key_part_t wkey_part[3]; @@ -13259,6 +13336,9 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) case QUERY_COMMITTING: enum wsrep_status rcode; + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(thd, signal); WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", victim_trx->id); From 28d9d0c7a8bc141daa4f881b5b2a4c474b550c58 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 29 Nov 2012 14:50:52 +0400 Subject: [PATCH 024/294] MDEV-3893 mariadb-galera-server deb package cannot be installed on a mysql-free machine. Fixed templates for messages. --- ...es => mariadb-galera-server-5.5.templates} | 0 debian/po/POTFILES.in | 2 +- debian/po/ar.po | 48 +++++++++---------- debian/po/ca.po | 48 +++++++++---------- debian/po/cs.po | 48 +++++++++---------- debian/po/da.po | 48 +++++++++---------- debian/po/de.po | 48 +++++++++---------- debian/po/es.po | 48 +++++++++---------- debian/po/eu.po | 48 +++++++++---------- debian/po/fr.po | 48 +++++++++---------- debian/po/gl.po | 48 +++++++++---------- debian/po/it.po | 48 +++++++++---------- debian/po/ja.po | 48 +++++++++---------- debian/po/nb.po | 48 +++++++++---------- debian/po/nl.po | 48 +++++++++---------- debian/po/pt.po | 48 +++++++++---------- debian/po/pt_BR.po | 48 +++++++++---------- debian/po/ro.po | 48 +++++++++---------- debian/po/ru.po | 48 +++++++++---------- debian/po/sv.po | 48 +++++++++---------- debian/po/templates.pot | 48 +++++++++---------- debian/po/tr.po | 48 +++++++++---------- 22 files changed, 481 insertions(+), 481 deletions(-) rename debian/{mariadb-server-5.5.templates => mariadb-galera-server-5.5.templates} (100%) diff --git a/debian/mariadb-server-5.5.templates b/debian/mariadb-galera-server-5.5.templates similarity index 100% rename from debian/mariadb-server-5.5.templates rename to debian/mariadb-galera-server-5.5.templates diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in index 8ca17f69cc1..347ab715d2f 100644 --- a/debian/po/POTFILES.in +++ b/debian/po/POTFILES.in @@ -1 +1 @@ -[type: gettext/rfc822deb] mariadb-server-5.5.templates +[type: gettext/rfc822deb] mariadb-galera-server-5.5.templates diff --git a/debian/po/ar.po b/debian/po/ar.po index 7791fbebf2e..a076d4757e7 100644 --- a/debian/po/ar.po +++ b/debian/po/ar.po @@ -27,19 +27,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "هل ÙØ¹Ù„اً تريد التثبيط؟" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "هناك مل٠مسمى /var/lib/mysql/debian-*.flag موجود على هذا النظام." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -52,7 +52,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -62,13 +62,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "ملاحظة هامة لمستخدمي NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -76,7 +76,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -88,13 +88,13 @@ msgstr "عليك أيضاً أن تقوم بالتأكد من صلاحيات Ù… #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "إزالة جميع قواعد بيانات MariaDBØŸ" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -102,7 +102,7 @@ msgstr "الدليل /var/lib/mysql الذي يحتوي قواعد بيانات #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "تشغيل خادم MariaDB عند الإقلاع؟" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -129,13 +129,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص بـMariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -145,7 +145,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -153,7 +153,7 @@ msgstr "إن ترك الحقل ÙØ§Ø±ØºØ§Ù‹ØŒ Ùلن يتم تغيير كلمة #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MariaDB \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -161,13 +161,13 @@ msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص ب #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "تعذر تعيين كلمة مرور للمستخدم \"root\" الخاص بـMariaDB." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -188,7 +188,7 @@ msgstr "يجب عليك التحقق من كلمة مرور الحساب عقب #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -202,25 +202,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ca.po b/debian/po/ca.po index 612ed584c96..20c7da86f6c 100644 --- a/debian/po/ca.po +++ b/debian/po/ca.po @@ -17,19 +17,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -37,7 +37,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -45,7 +45,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -53,7 +53,7 @@ msgstr "Nota important pels usuaris de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -61,7 +61,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -69,13 +69,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -83,7 +83,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -92,7 +92,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -100,7 +100,7 @@ msgstr "Voleu que el MariaDB s'inici #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy msgid "" "The MariaDB server can be launched automatically at boot time or manually " @@ -112,13 +112,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -126,25 +126,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -153,13 +153,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -167,25 +167,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/cs.po b/debian/po/cs.po index 87d9645a4c5..7db6cce1ad8 100644 --- a/debian/po/cs.po +++ b/debian/po/cs.po @@ -26,19 +26,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Opravdu pokraÄovat v degradaci?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "V systému existuje soubor /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -51,7 +51,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -61,13 +61,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Důležitá poznámka pro uživatele NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -75,7 +75,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -88,13 +88,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Odstranit vÅ¡echny MariaDB databáze?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -104,7 +104,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -116,13 +116,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Spustit MariaDB server pÅ™i startu systému?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -132,13 +132,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -148,7 +148,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -156,7 +156,7 @@ msgstr "Ponecháte-li pole prázdné, heslo se nezmÄ›ní." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -164,13 +164,13 @@ msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Nelze nastavit heslo MariaDB uživatele \"root\"" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -182,7 +182,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -191,7 +191,7 @@ msgstr "Po instalaci balíku byste mÄ›li heslo ověřit." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -204,25 +204,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/da.po b/debian/po/da.po index a42e3bd67d7..934065e71fb 100644 --- a/debian/po/da.po +++ b/debian/po/da.po @@ -27,20 +27,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Ønsker du virkelig at fortsætte nedgraderingen?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Der er en fil med navnet /var/lib/mysql/debian-*.flag på dette system." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -54,7 +54,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -64,13 +64,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Vigtig oplysning til NIS/YP-brugere" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -78,7 +78,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -91,13 +91,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Fjern alle MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -107,7 +107,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -119,13 +119,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Start MariaDB-serveren under systemopstart?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -135,13 +135,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -151,7 +151,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -159,7 +159,7 @@ msgstr "Hvis du lader dette felt st #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -167,13 +167,13 @@ msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Kunne ikke sætte adgangskoden for MariaDB's \"root\"-bruger" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -186,13 +186,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Du bør tjekke kontoens adgangskode efter pakkeinstallationen." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -206,25 +206,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/de.po b/debian/po/de.po index bbefb910646..5238f43e9fc 100644 --- a/debian/po/de.po +++ b/debian/po/de.po @@ -29,13 +29,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Möchten Sie wirklich eine ältere Version einspielen?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Auf diesem System existiert eine Datei mit dem Namen /var/lib/mysql/debian-*." @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -53,7 +53,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -63,13 +63,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Wichtige Anmerkung für NIS/YP-Benutzer!" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -79,7 +79,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -89,13 +89,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Alle MariaDB-Datenbanken entfernen?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -105,7 +105,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -117,13 +117,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Soll der MariaDB-Server automatisch beim Booten starten?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -133,13 +133,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Neues Passwort für den MariaDB »root«-Benutzer:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -149,25 +149,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Wenn dieses Feld freigelassen wird, wird das Passwort nicht geändert." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Wiederholen Sie das Passwort für den MariaDB-»root«-Benutzer:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Konnte für den MariaDB-»root«-Benutzer kein Passwort setzen" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -180,7 +180,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Sie sollten das Passwort des administrativen Benutzers nach der " @@ -188,7 +188,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.1/README.Debian file for " @@ -202,13 +202,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Passwort-Eingabefehler" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Die beiden von Ihnen eingegebenen Passwörter sind nicht identisch. Bitte " @@ -216,13 +216,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB-Cluster scheint gerade benutzt zu werden" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/es.po b/debian/po/es.po index cb77ed5a50e..eae3a157e98 100644 --- a/debian/po/es.po +++ b/debian/po/es.po @@ -52,20 +52,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "¿Desea realmente continuar con la desactualización?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Existe un archivo con el nombre /var/lib/mysql/debian-*.flag en este sistema." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -79,7 +79,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -89,13 +89,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para los usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -103,7 +103,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -117,13 +117,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Desea eliminar todas las bases de datos MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -133,7 +133,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -145,13 +145,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "¿Debería ejecutarse el servidor MariaDB al iniciarse el sistema?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -161,13 +161,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -177,7 +177,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -185,7 +185,7 @@ msgstr "No se modificará la contraseña si deja el espacio en blanco." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -193,13 +193,13 @@ msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "No se pudo fijar la contraseña para el usuario «root» de MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -212,7 +212,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Debería comprobar la contraseña de la cuenta después de la instalación del " @@ -220,7 +220,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -234,25 +234,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/eu.po b/debian/po/eu.po index ef195532d2a..972239ae97f 100644 --- a/debian/po/eu.po +++ b/debian/po/eu.po @@ -20,19 +20,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Benetan bertsio zaharragora itzuli nahi duzu?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Sisteman badago /var/lib/mysql/debian-*.flag izeneko fitxategi bat." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -46,7 +46,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -56,13 +56,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP erabiltzaileentzat ohar garrantzitsua" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -70,7 +70,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -84,13 +84,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ezabatu MariaDB datubase guztiak?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -99,7 +99,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -111,13 +111,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Abioan MariaDB zerbitzaria abiarazi?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -127,13 +127,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB \"root\" erabiltzailearen pasahitz berria:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -143,7 +143,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -151,19 +151,19 @@ msgstr "Eremua hau zurian utziaz gero ez da pasahitza aldatuko." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Errepikatu MariaDB \"root\" erabiltzailearen pasahitza:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ezin da MariaDB \"root\" erabiltzailearen pasahitza ezarri" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,14 +175,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Kontuaren pasahitza egiaztatu beharko zenuke paketea instalatu aurretik." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -196,25 +196,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Pasahitz sarrera errorea" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Idatzi dituzun bi pasahitzak ez dira berdina. Mesedez saiatu berriz." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "Dirudienez NDB Cluster-a erabilia dago" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 #, fuzzy #| msgid "" #| "MySQL-5.1 has orphaned NDB Cluster support. Please migrate to the new " diff --git a/debian/po/fr.po b/debian/po/fr.po index d9f59de8e3e..66ab77e101d 100644 --- a/debian/po/fr.po +++ b/debian/po/fr.po @@ -22,19 +22,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Faut-il vraiment revenir à la version précédente ?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Un fichier /var/lib/mysql/debian-*.flag est présent sur ce système." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -44,7 +44,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -52,13 +52,13 @@ msgstr "Il n'est pas garanti que cette version puisse en utiliser les données." #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Note importante pour les utilisateurs NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -68,7 +68,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -78,13 +78,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Faut-il supprimer toutes les bases de données MariaDB ?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -94,7 +94,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Faut-il lancer MariaDB au démarrage ?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -121,13 +121,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nouveau mot de passe du superutilisateur de MariaDB :" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -137,26 +137,26 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Si ce champ est laissé vide, le mot de passe ne sera pas changé." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Confirmation du mot de passe du superutilisateur de MariaDB :" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Impossible de changer le mot de passe de l'utilisateur « root » de MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -168,7 +168,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Vous devriez vérifier le mot de passe de ce compte après l'installation du " @@ -176,7 +176,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -190,13 +190,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Erreur de saisie du mot de passe" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Le mot de passe et sa confirmation ne sont pas identiques. Veuillez " @@ -204,13 +204,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "Abandon de la gestion de NDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/gl.po b/debian/po/gl.po index 0f05f62ba6d..87e102069d2 100644 --- a/debian/po/gl.po +++ b/debian/po/gl.po @@ -17,19 +17,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "¿Quere pasar a unha versión anterior?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Neste sistema hai un ficheiro chamado /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -53,13 +53,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para os usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -81,13 +81,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Eliminar tódalas bases de datos de MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -109,13 +109,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "¿Iniciar o servidor MariaDB co ordenador?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -125,13 +125,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -141,7 +141,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -149,7 +149,7 @@ msgstr "Se deixa o campo en branco, non se ha cambiar o contrasinal." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -157,13 +157,13 @@ msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Non se puido establecer o contrasinal do usuario \"root\" de MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,7 +175,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -184,7 +184,7 @@ msgstr "Debería comprobar o contrasinal da conta trala instalación do paquete. #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -198,25 +198,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/it.po b/debian/po/it.po index b377d9f9fb3..3cb92f9bc3e 100644 --- a/debian/po/it.po +++ b/debian/po/it.po @@ -18,20 +18,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Procedere realmente con l'abbassamento di versione?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Su questo sistema esiste un file con nome /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -41,7 +41,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -51,13 +51,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante per gli utenti NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -77,13 +77,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Eliminare tutti i database MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Lanciare il server MariaDB all'avvio?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -121,13 +121,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nuova password per l'utente «root» di MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -137,25 +137,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Se questo campo è lasciato vuoto, la password non viene cambiata." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Ripetere la password per l'utente «root» di MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Impossibile impostare la password per l'utente «root» di MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -168,14 +168,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Al termine dell'installazione si deve verificare la password dell'account." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -189,25 +189,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Errore di inserimento della password" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Le due password inserite sono diverse. Riprovare." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "È in uso un cluster NDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ja.po b/debian/po/ja.po index f63f21fdb8d..1f756492263 100644 --- a/debian/po/ja.po +++ b/debian/po/ja.po @@ -27,13 +27,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "本当ã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã‚’実行ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ /var/lib/mysql/debian-*.flag ã¨ã„ã†åå‰ã®ãƒ•ァイルãŒå­˜åœ¨ã—ã¦" @@ -41,7 +41,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -51,7 +51,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -61,13 +61,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP ユーザã¸ã®é‡è¦ãªæ³¨æ„" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -77,7 +77,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -85,13 +85,13 @@ msgstr "/var/lib/mysql ã®æ‰€æœ‰è€…権é™ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹å¿…è¦ã‚‚ã‚り㾠#. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "ã™ã¹ã¦ã® MariaDB データベースを削除ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -101,7 +101,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "MariaDB をシステム起動時ã«é–‹å§‹ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -129,13 +129,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -145,25 +145,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "ã“ã®å€¤ã‚’空ã®ã¾ã¾ã«ã—ã¦ãŠã„ãŸå ´åˆã¯ã€ãƒ‘スワードã¯å¤‰æ›´ã•れã¾ã›ã‚“。" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "MariaDB ã® \"root\" ユーザã®ãƒ‘スワードを設定ã§ãã¾ã›ã‚“" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,14 +175,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å¾Œã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを確èªã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -195,25 +195,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "パスワード入力エラー" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "入力ã•れãŸäºŒã¤ã®ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“。å†å…¥åŠ›ã—ã¦ãã ã•ã„。" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB クラスタãŒåˆ©ç”¨ã•れã¦ã„るよã†ã§ã™" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/nb.po b/debian/po/nb.po index 3dd6ec7ae5c..d6e136afc6e 100644 --- a/debian/po/nb.po +++ b/debian/po/nb.po @@ -19,7 +19,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -27,13 +27,13 @@ msgstr "Er du sikker pÃ¥ at du vil nedgradere?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Viktig merknad for NIS/YP-brukere!" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -113,7 +113,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -121,7 +121,7 @@ msgstr "Skal MariaDB startes ved maskinoppstart?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -135,7 +135,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -143,7 +143,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -157,13 +157,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -171,7 +171,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -179,7 +179,7 @@ msgstr "Klarer ikke angi passord for MariaDBs «root»-bruker" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -198,13 +198,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -212,25 +212,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/nl.po b/debian/po/nl.po index 09cf06c7c47..8fc82aebd66 100644 --- a/debian/po/nl.po +++ b/debian/po/nl.po @@ -18,7 +18,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -26,13 +26,13 @@ msgstr "Wilt u echt een oude versie herstellen?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Belangrijke opmerking voor gebruikers van NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -114,7 +114,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -122,7 +122,7 @@ msgstr "Moet MariaDB starten als de computer start?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -136,7 +136,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -144,7 +144,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -158,13 +158,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -172,7 +172,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -180,7 +180,7 @@ msgstr "Kan het wachtwoord voor de MariaDB \"root\"-gebruiker niet instellen" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -199,13 +199,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -213,25 +213,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/pt.po b/debian/po/pt.po index e1a3cad5c24..73fbae3248c 100644 --- a/debian/po/pt.po +++ b/debian/po/pt.po @@ -18,19 +18,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Deseja mesmo fazer downgrade?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Existe um ficheiro chamado /var/lib/mysql/debian-*.flag neste sistema." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -44,7 +44,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -54,13 +54,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para utilizadores de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -68,7 +68,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -81,13 +81,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -109,13 +109,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Iniciar o servidor MariaDB no arranque?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -125,13 +125,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -141,7 +141,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -150,7 +150,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -158,7 +158,7 @@ msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Não foi possível definir a palavra-passe para o utilizador \"root\" do " @@ -166,7 +166,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -189,7 +189,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -203,25 +203,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po index 26a5ac3d6fa..50979feeee2 100644 --- a/debian/po/pt_BR.po +++ b/debian/po/pt_BR.po @@ -21,19 +21,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Realmente proceder com o rebaixamento de versão?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Um arquivo de nome /var/lib/mysql/debian-*.flag existe no sistema." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -47,7 +47,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -57,13 +57,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Aviso importante para usuários NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -71,7 +71,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -84,13 +84,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados do MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -100,7 +100,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -112,13 +112,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Iniciar o servidor MariaDB junto a inicialização da máquina?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -128,13 +128,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -144,7 +144,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -152,7 +152,7 @@ msgstr "Caso este campo seja deixado em branco, a senha não sera mudada." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -160,13 +160,13 @@ msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Impossível definir senha para o usuário \"root\" do MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -188,7 +188,7 @@ msgstr "Você deverá checar a senha dessa conta após a instalação deste paco #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -202,25 +202,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ro.po b/debian/po/ro.po index 81d64f37658..7c38a8e8ba7 100644 --- a/debian/po/ro.po +++ b/debian/po/ro.po @@ -19,7 +19,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -27,13 +27,13 @@ msgstr "SunteÅ£i sigur că doriÅ£i să instalaÅ£i o versiune mai veche?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Notă importantă pentru utilizatorii NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -113,7 +113,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -121,7 +121,7 @@ msgstr "DoriÅ£i ca MariaDB să pornească la initializarea sistemului?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -135,7 +135,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -143,7 +143,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -157,13 +157,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -171,7 +171,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -179,7 +179,7 @@ msgstr "Nu s-a putut stabili parola pentru utilizatorul „root†al MariaDB" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -198,13 +198,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -212,25 +212,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ru.po b/debian/po/ru.po index 8ce5690ffe1..3e0bbe884ed 100644 --- a/debian/po/ru.po +++ b/debian/po/ru.po @@ -32,19 +32,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "ДейÑтвительно уÑтановить более Ñтарую верÑию?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Ð’ ÑиÑтеме найден файл /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -54,7 +54,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -64,13 +64,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Важное замечание Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ NIS/YP" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -80,7 +80,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -88,13 +88,13 @@ msgstr "Также проверьте права доÑтупа и владел #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Удалить вÑе базы данных MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -103,7 +103,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -115,13 +115,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "ЗапуÑкать MariaDB при загрузке ÑиÑтемы?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -131,13 +131,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ðовый пароль Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -147,25 +147,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "ЕÑли оÑтавить поле пуÑтым, то пароль изменён не будет." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Повторите ввод Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ðевозможно задать пароль MariaDB пользователю \"root\"" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -177,13 +177,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Проверьте пароль учётной запиÑи поÑле уÑтановки пакета." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -196,25 +196,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Ошибка ввода паролÑ" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Два введённых Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ одинаковы. Повторите ввод." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB Cluster уже иÑпользуетÑÑ" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/sv.po b/debian/po/sv.po index 297a2fb6d68..374601a97c2 100644 --- a/debian/po/sv.po +++ b/debian/po/sv.po @@ -21,19 +21,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "Vill du verkligen genomföra nedgraderingen?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "En fil med namnet /var/lib/mysql/debian-*.flag hittades i systemet." #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -53,13 +53,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "Viktig information för NIS/YP-användare" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -69,7 +69,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -79,13 +79,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ta bort alla MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -95,7 +95,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -107,13 +107,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Ska MariaDB startas vid systemets uppstart?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -123,13 +123,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nytt lösenord för MariaDBs \"root\"-användare:" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -139,25 +139,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Om detta fält lämnas tom kommer lösenordet inte att ändras." #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Repetera lösenordet för MariaDBs \"root\"-användare:" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Kunde inte sätta lösenord för MariaDBs \"root\"-användare" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -170,13 +170,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Du bör kontrollera kontots lösenord efter installationen av paketet." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " @@ -190,25 +190,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "Fel vid inmatning av lösenord" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "De tvÃ¥ lösenorden du angav stämde inte överrens. Prova igen." #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB-kluster används inte" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/templates.pot b/debian/po/templates.pot index 742ea566a84..94174d24233 100644 --- a/debian/po/templates.pot +++ b/debian/po/templates.pot @@ -19,19 +19,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -39,7 +39,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -47,13 +47,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "Important note for NIS/YP users" msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -61,7 +61,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -69,13 +69,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -83,7 +83,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -92,13 +92,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -106,13 +106,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -120,25 +120,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -147,13 +147,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -161,25 +161,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/tr.po b/debian/po/tr.po index 046c346e85c..9a91efbf61a 100644 --- a/debian/po/tr.po +++ b/debian/po/tr.po @@ -18,19 +18,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -38,7 +38,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:2001 +#: ../mariadb-galera-server-5.5.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -46,7 +46,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -54,7 +54,7 @@ msgstr "NIS/YP kullanıcıları için önemli not!" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -62,7 +62,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-5.5.templates:3001 +#: ../mariadb-galera-server-5.5.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -70,13 +70,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -84,7 +84,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:4001 +#: ../mariadb-galera-server-5.5.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -101,7 +101,7 @@ msgstr "MariaDB açılış sırasında baÅŸlatılsın mı?" #. Type: boolean #. Description -#: ../mariadb-server-5.5.templates:5001 +#: ../mariadb-galera-server-5.5.templates:5001 #, fuzzy msgid "" "The MariaDB server can be launched automatically at boot time or manually " @@ -113,13 +113,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -127,25 +127,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:6001 +#: ../mariadb-galera-server-5.5.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-5.5.templates:7001 +#: ../mariadb-galera-server-5.5.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -154,13 +154,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:8001 +#: ../mariadb-galera-server-5.5.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-5.5/README.Debian file for " "more information." @@ -168,25 +168,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:9001 +#: ../mariadb-galera-server-5.5.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-5.5.templates:10001 +#: ../mariadb-galera-server-5.5.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " From c194027f2271aad12624761d770551d837167a4b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 13 Dec 2012 17:48:46 +0400 Subject: [PATCH 025/294] MDEV-507 Galera Deb/RPM packages. Add new wsrep-related files to the DEB packages. --- debian/dist/Debian/mariadb-galera-server-5.5.dirs | 1 + debian/dist/Debian/mariadb-galera-server-5.5.files | 7 +++++++ debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs | 1 + debian/dist/Ubuntu/mariadb-galera-server-5.5.files | 6 ++++++ 4 files changed, 15 insertions(+) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.dirs b/debian/dist/Debian/mariadb-galera-server-5.5.dirs index 6afd2a1854c..4f82cf4c4f2 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Debian/mariadb-galera-server-5.5.dirs @@ -6,5 +6,6 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-server-5.5 +usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files index e68be4f9b86..f6ee6b7febd 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files @@ -1,3 +1,4 @@ +usr/README-wsrep usr/sbin/mysqld usr/lib/mysql/plugin/ usr/lib/libhsclient.so.* @@ -30,6 +31,10 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip +usr/bin/wsrep_sst_common +usr/bin/wsrep_sst_mysqldump +usr/bin/wsrep_sst_rsync +usr/bin/wsrep_sst_xtrabackup usr/share/doc/mariadb-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-server-5.5/INFO_SRC usr/share/doc/mariadb-server-5.5/INFO_BIN @@ -88,3 +93,5 @@ usr/share/mysql/fill_help_tables.sql usr/share/mysql/mysql_system_tables_data.sql usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_test_data_timezone.sql +usr/support-files/wsrep.cnf +usr/support-files/wsrep_notify diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs index 6afd2a1854c..4f82cf4c4f2 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs @@ -6,5 +6,6 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-server-5.5 +usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files index d20f8a0af91..f35844dcfff 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files @@ -1,3 +1,4 @@ +usr/README-wsrep usr/sbin/mysqld usr/lib/mysql/plugin/ usr/lib/libhsclient.so.* @@ -32,6 +33,10 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip +usr/bin/wsrep_sst_common +usr/bin/wsrep_sst_mysqldump +usr/bin/wsrep_sst_rsync +usr/bin/wsrep_sst_xtrabackup usr/share/doc/mariadb-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-server-5.5/INFO_SRC usr/share/doc/mariadb-server-5.5/INFO_BIN @@ -90,3 +95,4 @@ usr/share/mysql/fill_help_tables.sql usr/share/mysql/mysql_system_tables_data.sql usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_test_data_timezone.sql +usr/support-files/wsrep.cnf From ffc82ab60665ae910950022811370d7db49b41ea Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 20 Dec 2012 12:34:37 +0100 Subject: [PATCH 026/294] update test cases and results --- mysql-test/r/information_schema.result | 48 +-------- mysql-test/r/mysqld--help.result | 102 ++++++++++++++++++ mysql-test/r/show_check.result | 6 +- .../suite/funcs_1/r/is_columns_is.result | 16 +-- .../suite/innodb/r/innodb-autoinc.result | 21 ++++ .../suite/perfschema/r/all_instances.result | 13 +++ .../perfschema/r/dml_setup_instruments.result | 6 +- mysql-test/suite/sys_vars/r/all_vars.result | 34 ++++++ mysql-test/t/information_schema.test | 24 +---- mysql-test/t/mysqld--help.test | 2 +- 10 files changed, 191 insertions(+), 81 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 9d993e723c2..83f2fabcf26 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1564,50 +1564,10 @@ id select_type table type possible_keys key key_len ref rows Extra explain select count(*) from information_schema.views; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE views ALL NULL NULL NULL NULL NULL Open_frm_only; Scanned all databases -set global init_connect="drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;"; -select * from information_schema.global_variables where variable_name='init_connect'; -VARIABLE_NAME VARIABLE_VALUE -INIT_CONNECT drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists +set global init_connect=repeat("drop table if exists t1;", 100); +select length(@@global.init_connect), length(variable_value) from information_schema.global_variables where variable_name='init_connect'; +length(@@global.init_connect) length(variable_value) +2400 2048 Warnings: Warning 1265 Data truncated for column 'VARIABLE_VALUE' at row 1 set global init_connect=""; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index c36cc96bb1a..6a8b7e059fb 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -851,6 +851,75 @@ The following options may be given as the first argument: -V, --version Output version information and exit. --wait-timeout=# The number of seconds the server waits for activity on a connection before closing it + --wsrep-OSU-method[=name] + Method for Online Schema Upgrade + --wsrep-auto-increment-control + To automatically control the assignment of autoincrement + variables + (Defaults to on; use --skip-wsrep-auto-increment-control to disable.) + --wsrep-causal-reads + Enable "strictly synchronous" semantics for read + operations + --wsrep-certify-nonPK + Certify tables with no primary key + (Defaults to on; use --skip-wsrep-certify-nonPK to disable.) + --wsrep-cluster-address=name + Address to initially connect to cluster + --wsrep-cluster-name=name + Name for the cluster + --wsrep-convert-LOCK-to-trx + To convert locking sessions into transactions + --wsrep-data-home-dir=name + home directory for wsrep provider + --wsrep-dbug-option=name + DBUG options to provider library + --wsrep-debug To enable debug level logging + --wsrep-drupal-282555-workaround + To use a workaround forbad autoincrement value + --wsrep-forced-binlog-format=name + binlog format to take effect over user's choice + --wsrep-log-conflicts + To log multi-master conflicts + --wsrep-max-ws-rows=# + Max number of rows in write set + --wsrep-max-ws-size=# + Max write set size (bytes) + --wsrep-mysql-replication-bundle=# + mysql replication group commit + --wsrep-node-address=name + Node address + --wsrep-node-incoming-address=name + Client connection address + --wsrep-node-name=name + Node name + --wsrep-notify-cmd=name + --wsrep-on To enable wsrep replication + (Defaults to on; use --skip-wsrep-on to disable.) + --wsrep-provider=name + Path to replication provider library + --wsrep-provider-options=name + provider specific options + --wsrep-recover Recover database state after crash and exit + --wsrep-replicate-myisam + To enable myisam replication + --wsrep-retry-autocommit=# + Max number of times to retry a failed autocommit + statement + --wsrep-slave-threads=# + Number of slave appliers to launch + --wsrep-sst-auth=name + Authentication for SST connection + --wsrep-sst-donor=name + preferred donor node for the SST + --wsrep-sst-donor-rejects-queries + Reject client queries when donating state snapshot + transfer + --wsrep-sst-method=name + State snapshot transfer method + --wsrep-sst-receive-address=name + Address where node is waiting for SST contact + --wsrep-start-position=name + global transaction position to start from Variables (--variable-name=value) allow-suspicious-udfs FALSE @@ -1099,6 +1168,39 @@ updatable-views-with-limit YES userstat FALSE verbose TRUE wait-timeout 28800 +wsrep-OSU-method TOI +wsrep-auto-increment-control TRUE +wsrep-causal-reads FALSE +wsrep-certify-nonPK TRUE +wsrep-cluster-address +wsrep-cluster-name my_wsrep_cluster +wsrep-convert-LOCK-to-trx FALSE +wsrep-data-home-dir +wsrep-dbug-option +wsrep-debug FALSE +wsrep-drupal-282555-workaround FALSE +wsrep-forced-binlog-format NONE +wsrep-log-conflicts FALSE +wsrep-max-ws-rows 131072 +wsrep-max-ws-size 1073741824 +wsrep-mysql-replication-bundle 0 +wsrep-node-address +wsrep-node-incoming-address AUTO +wsrep-node-name meddwl +wsrep-notify-cmd +wsrep-on FALSE +wsrep-provider none +wsrep-provider-options +wsrep-recover FALSE +wsrep-replicate-myisam FALSE +wsrep-retry-autocommit 1 +wsrep-slave-threads 1 +wsrep-sst-auth (No default value) +wsrep-sst-donor +wsrep-sst-donor-rejects-queries FALSE +wsrep-sst-method mysqldump +wsrep-sst-receive-address AUTO +wsrep-start-position 00000000-0000-0000-0000-000000000000:-1 To see what values a running MySQL server is using, type 'mysqladmin variables' instead of 'mysqld --verbose --help'. diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index b0a812c7b18..86c48253179 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -101,19 +101,19 @@ drop table t1; show variables like "wait_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 5 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 5 Y 0 0 8 Variable_name Value wait_timeout 28800 show variables like "WAIT_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 5 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 5 Y 0 0 8 Variable_name Value wait_timeout 28800 show variables like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 0 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 0 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 0 Y 0 0 8 Variable_name Value show table status from test like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index 4da7eeb2ada..526d69fe4c9 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -134,9 +134,9 @@ def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select def information_schema GLOBAL_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema INDEX_STATISTICS INDEX_NAME 3 NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema INDEX_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select @@ -284,9 +284,9 @@ def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 NO varchar 64 192 NUL def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select def information_schema SESSION_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema SESSION_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) select def information_schema STATISTICS COLUMN_NAME 8 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select @@ -602,9 +602,9 @@ NULL information_schema FILES CHECKSUM bigint NULL NULL NULL NULL bigint(21) uns 3.0000 information_schema FILES STATUS varchar 20 60 utf8 utf8_general_ci varchar(20) 3.0000 information_schema FILES EXTRA varchar 255 765 utf8 utf8_general_ci varchar(255) 3.0000 information_schema GLOBAL_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) @@ -752,9 +752,9 @@ NULL information_schema ROUTINES LAST_ALTERED datetime NULL NULL NULL NULL datet 3.0000 information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema SCHEMA_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema SESSION_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema SESSION_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema STATISTICS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) 3.0000 information_schema STATISTICS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema STATISTICS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index 8c4c1c20590..746401e732f 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -201,6 +201,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -234,6 +235,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -273,6 +275,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -286,6 +289,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL); INSERT INTO t1 VALUES (250),(NULL); SELECT * FROM t1; @@ -319,6 +323,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -334,6 +339,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2); Warnings: Warning 1264 Out of range value for column 'c1' at row 1 @@ -374,6 +380,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -389,6 +396,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL); Warnings: Warning 1264 Out of range value for column 'c1' at row 1 @@ -423,6 +431,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -438,6 +447,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 2 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); SELECT * FROM t1; c1 @@ -456,6 +466,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -471,6 +482,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 2 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL); ERROR HY000: Failed to read auto-increment value from storage engine SELECT * FROM t1; @@ -484,6 +496,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -499,6 +512,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 5 auto_increment_offset 7 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL), (NULL); ERROR HY000: Failed to read auto-increment value from storage engine SELECT * FROM t1; @@ -512,6 +526,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -531,6 +546,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 3 auto_increment_offset 3 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL), (NULL); SELECT * FROM t1; c1 @@ -548,6 +564,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -566,6 +583,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 65535 auto_increment_offset 65535 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL); ERROR 22003: Out of range value for column 'c1' at row 1 SELECT * FROM t1; @@ -579,6 +597,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 DOUBLE NOT NULL AUTO_INCREMENT, c2 INT, PRIMARY KEY (c1)) ENGINE=InnoDB; INSERT INTO t1 VALUES(NULL, 1); INSERT INTO t1 VALUES(NULL, 2); @@ -866,6 +885,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (-1, 'innodb'); @@ -1256,6 +1276,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 256 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, NULL); SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/perfschema/r/all_instances.result b/mysql-test/suite/perfschema/r/all_instances.result index caf4f49034f..34144dfecb1 100644 --- a/mysql-test/suite/perfschema/r/all_instances.result +++ b/mysql-test/suite/perfschema/r/all_instances.result @@ -68,6 +68,12 @@ wait/synch/mutex/sql/LOCK_thread_count wait/synch/mutex/sql/LOCK_user_conn wait/synch/mutex/sql/LOCK_user_locks wait/synch/mutex/sql/LOCK_uuid_short_generator +wait/synch/mutex/sql/LOCK_wsrep_ready +wait/synch/mutex/sql/LOCK_wsrep_replaying +wait/synch/mutex/sql/LOCK_wsrep_rollback +wait/synch/mutex/sql/LOCK_wsrep_slave_threads +wait/synch/mutex/sql/LOCK_wsrep_sst +wait/synch/mutex/sql/LOCK_wsrep_sst_init wait/synch/mutex/sql/LOCK_xid_cache wait/synch/mutex/sql/LOG::LOCK_log wait/synch/mutex/sql/LOG_INFO::lock @@ -87,6 +93,7 @@ wait/synch/mutex/sql/Slave_reporting_capability::err_lock wait/synch/mutex/sql/TABLE_SHARE::LOCK_ha_data wait/synch/mutex/sql/THD::LOCK_thd_data wait/synch/mutex/sql/THD::LOCK_wakeup_ready +wait/synch/mutex/sql/THD::LOCK_wsrep_thd wait/synch/mutex/sql/tz_LOCK select name from rwlock_instances where name not in ("wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock") @@ -122,6 +129,11 @@ wait/synch/cond/sql/COND_rpl_status wait/synch/cond/sql/COND_server_started wait/synch/cond/sql/COND_thread_cache wait/synch/cond/sql/COND_thread_count +wait/synch/cond/sql/COND_wsrep_ready +wait/synch/cond/sql/COND_wsrep_replaying +wait/synch/cond/sql/COND_wsrep_rollback +wait/synch/cond/sql/COND_wsrep_sst +wait/synch/cond/sql/COND_wsrep_sst_init wait/synch/cond/sql/Event_scheduler::COND_state wait/synch/cond/sql/Master_info::data_cond wait/synch/cond/sql/Master_info::sleep_cond @@ -139,6 +151,7 @@ wait/synch/cond/sql/Relay_log_info::sleep_cond wait/synch/cond/sql/Relay_log_info::start_cond wait/synch/cond/sql/Relay_log_info::stop_cond wait/synch/cond/sql/THD::COND_wakeup_ready +wait/synch/cond/sql/THD::COND_wsrep_thd select event_name from file_instances group by event_name; event_name wait/io/file/aria/control diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result index 9f48a085eca..807cc3e079e 100644 --- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result +++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result @@ -43,9 +43,9 @@ wait/synch/cond/sql/COND_rpl_status YES YES wait/synch/cond/sql/COND_server_started YES YES wait/synch/cond/sql/COND_thread_cache YES YES wait/synch/cond/sql/COND_thread_count YES YES -wait/synch/cond/sql/Delayed_insert::cond YES YES -wait/synch/cond/sql/Delayed_insert::cond_client YES YES -wait/synch/cond/sql/Event_scheduler::COND_state YES YES +wait/synch/cond/sql/COND_wsrep_ready YES YES +wait/synch/cond/sql/COND_wsrep_replaying YES YES +wait/synch/cond/sql/COND_wsrep_rollback YES YES select * from performance_schema.setup_instruments where name='Wait'; select * from performance_schema.setup_instruments diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 1bd4e394f6a..b61a8aabf08 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -10,5 +10,39 @@ there should be *no* long test name listed below: select distinct variable_name as `there should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; there should be *no* variables listed below: +innodb_disallow_writes +wsrep_auto_increment_control +wsrep_causal_reads +wsrep_certify_nonpk +wsrep_cluster_address +wsrep_cluster_name +wsrep_convert_lock_to_trx +wsrep_data_home_dir +wsrep_dbug_option +wsrep_debug +wsrep_drupal_282555_workaround +wsrep_forced_binlog_format +wsrep_log_conflicts +wsrep_max_ws_rows +wsrep_max_ws_size +wsrep_mysql_replication_bundle +wsrep_node_address +wsrep_node_incoming_address +wsrep_node_name +wsrep_notify_cmd +wsrep_on +wsrep_osu_method +wsrep_provider +wsrep_provider_options +wsrep_recover +wsrep_replicate_myisam +wsrep_retry_autocommit +wsrep_slave_threads +wsrep_sst_auth +wsrep_sst_donor +wsrep_sst_donor_rejects_queries +wsrep_sst_method +wsrep_sst_receive_address +wsrep_start_position drop table t1; drop table t2; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index e95f41f6c8d..952915c6eb0 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1336,28 +1336,8 @@ explain select count(*) from information_schema.views; # # Bug#39955 SELECT on INFORMATION_SCHEMA.GLOBAL_VARIABLES takes too long # -set global init_connect="drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;"; -select * from information_schema.global_variables where variable_name='init_connect'; +set global init_connect=repeat("drop table if exists t1;", 100); +select length(@@global.init_connect), length(variable_value) from information_schema.global_variables where variable_name='init_connect'; set global init_connect=""; # diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 806e6f7f8d1..24dc9e0d1e9 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -10,7 +10,7 @@ # force symbolic-links=0 (valgrind build has a different default) # -exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt 2>&1; +exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt; # The inline perl code below will copy $MYSQL_TMP_DIR/mysqld--help.txt # to output, but filter away some variable stuff (e.g. paths). From c40abe9df0b759e2f8ba44b342eba4cfe2ca6388 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 3 Feb 2013 04:03:08 +0400 Subject: [PATCH 027/294] MDEV-508 (Wrong MTR result files in MariaDB-Galera) --- mysql-test/r/mysqld--help.result | 1 - mysql-test/suite/percona/innodb_sys_index.result | 2 +- mysql-test/suite/percona/innodb_sys_index.test | 2 ++ mysql-test/t/mysqld--help.test | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 6a8b7e059fb..46fffb1c6df 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1186,7 +1186,6 @@ wsrep-max-ws-size 1073741824 wsrep-mysql-replication-bundle 0 wsrep-node-address wsrep-node-incoming-address AUTO -wsrep-node-name meddwl wsrep-notify-cmd wsrep-on FALSE wsrep-provider none diff --git a/mysql-test/suite/percona/innodb_sys_index.result b/mysql-test/suite/percona/innodb_sys_index.result index 8bf4fa745ba..3dc1dcfebc8 100644 --- a/mysql-test/suite/percona/innodb_sys_index.result +++ b/mysql-test/suite/percona/innodb_sys_index.result @@ -3,7 +3,7 @@ Warnings: Note 1051 Unknown table 't1' select @@version_comment limit 1 ; @@version_comment -Source distribution +Source distribution, wsrep_X.Y.rZ SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; CREATE TABLE test.t1 ( `a` SERIAL NOT NULL , `b` VARCHAR( 255 ) NOT NULL , INDEX ( `b` ) ) ENGINE = InnoDB ; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; diff --git a/mysql-test/suite/percona/innodb_sys_index.test b/mysql-test/suite/percona/innodb_sys_index.test index 212baeda663..3c8f889f117 100644 --- a/mysql-test/suite/percona/innodb_sys_index.test +++ b/mysql-test/suite/percona/innodb_sys_index.test @@ -5,6 +5,7 @@ drop table if exists t1; # # test for bug LP#875797 "Using 'innodb_sys_indexes' causes core dump" # +--replace_regex /wsrep_[0-9]+\.[a-zA-Z0-9]+\.r[0-9]+/wsrep_X.Y.rZ/ select @@version_comment limit 1 ; --disable_result_log SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; @@ -19,3 +20,4 @@ SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; drop table test.t1; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; --enable_result_log + diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 24dc9e0d1e9..95f3b346ecd 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -20,7 +20,7 @@ perl; # their paths may vary: @skipvars=qw/basedir open-files-limit general-log-file log plugin-dir log-slow-queries pid-file slow-query-log-file log-basename - datadir slave-load-tmpdir tmpdir socket/; + datadir slave-load-tmpdir tmpdir socket wsrep-node-name/; # Plugins which may or may not be there: @plugins=qw/innodb ndb archive blackhole federated partition ndbcluster feedback debug temp-pool ssl des-key-file From db7495822940b5c95f10ff5b1e6273701e868436 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 4 Feb 2013 00:30:15 +0400 Subject: [PATCH 028/294] MDEV-508 - wsrep revno can be either a number or XXXX, test should be able to handle both --- mysql-test/suite/percona/innodb_sys_index.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/percona/innodb_sys_index.test b/mysql-test/suite/percona/innodb_sys_index.test index 3c8f889f117..9c6c83e029a 100644 --- a/mysql-test/suite/percona/innodb_sys_index.test +++ b/mysql-test/suite/percona/innodb_sys_index.test @@ -5,7 +5,7 @@ drop table if exists t1; # # test for bug LP#875797 "Using 'innodb_sys_indexes' causes core dump" # ---replace_regex /wsrep_[0-9]+\.[a-zA-Z0-9]+\.r[0-9]+/wsrep_X.Y.rZ/ +--replace_regex /wsrep_[0-9]+\.[a-zA-Z0-9]+\.r[0-9X]+/wsrep_X.Y.rZ/ select @@version_comment limit 1 ; --disable_result_log SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; From e0c6a87b997509f9eb282988cfb097e30b4c9749 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 15:48:54 +0200 Subject: [PATCH 029/294] re-merging wsrep files from lp:codership-mysql --- BUILD/compile-amd64-debug-wsrep | 11 - BUILD/compile-amd64-wsrep | 9 - BUILD/compile-pentium-debug-wsrep | 12 - BUILD/compile-pentium-wsrep | 11 - BUILD/compile-pentium64-wsrep | 28 - Docs/README-wsrep | 487 ----------- cmake/wsrep.cmake | 59 -- scripts/wsrep_sst_common.sh | 106 --- scripts/wsrep_sst_mysqldump.sh | 121 --- scripts/wsrep_sst_rsync.sh | 210 ----- scripts/wsrep_sst_xtrabackup.sh | 222 ----- sql/wsrep_check_opts.cc | 392 --------- sql/wsrep_hton.cc | 449 ---------- sql/wsrep_mysqld.cc | 1311 ----------------------------- sql/wsrep_mysqld.h | 383 --------- sql/wsrep_notify.cc | 107 --- sql/wsrep_priv.h | 233 ----- sql/wsrep_sst.cc | 1001 ---------------------- sql/wsrep_utils.cc | 468 ---------- sql/wsrep_var.cc | 548 ------------ support-files/wsrep.cnf.sh | 129 --- support-files/wsrep_notify.sh | 102 --- 22 files changed, 6399 deletions(-) delete mode 100755 BUILD/compile-amd64-debug-wsrep delete mode 100755 BUILD/compile-amd64-wsrep delete mode 100755 BUILD/compile-pentium-debug-wsrep delete mode 100755 BUILD/compile-pentium-wsrep delete mode 100755 BUILD/compile-pentium64-wsrep delete mode 100644 Docs/README-wsrep delete mode 100644 cmake/wsrep.cmake delete mode 100644 scripts/wsrep_sst_common.sh delete mode 100644 scripts/wsrep_sst_mysqldump.sh delete mode 100644 scripts/wsrep_sst_rsync.sh delete mode 100644 scripts/wsrep_sst_xtrabackup.sh delete mode 100644 sql/wsrep_check_opts.cc delete mode 100644 sql/wsrep_hton.cc delete mode 100644 sql/wsrep_mysqld.cc delete mode 100644 sql/wsrep_mysqld.h delete mode 100644 sql/wsrep_notify.cc delete mode 100644 sql/wsrep_priv.h delete mode 100644 sql/wsrep_sst.cc delete mode 100644 sql/wsrep_utils.cc delete mode 100644 sql/wsrep_var.cc delete mode 100644 support-files/wsrep.cnf.sh delete mode 100644 support-files/wsrep_notify.sh diff --git a/BUILD/compile-amd64-debug-wsrep b/BUILD/compile-amd64-debug-wsrep deleted file mode 100755 index 995a8afcca9..00000000000 --- a/BUILD/compile-amd64-debug-wsrep +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/sh - -path=`dirname $0` -. "$path/SETUP.sh" - -extra_flags="$amd64_cflags $debug_cflags -g -O0 $wsrep_cflags" -c_warnings="$c_warnings $debug_extra_warnings" -cxx_warnings="$cxx_warnings $debug_extra_warnings" -extra_configs="$amd64_configs $debug_configs $wsrep_configs --with-wsrep" - -. "$path/FINISH.sh" diff --git a/BUILD/compile-amd64-wsrep b/BUILD/compile-amd64-wsrep deleted file mode 100755 index 57dfbdd6da2..00000000000 --- a/BUILD/compile-amd64-wsrep +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -path=`dirname $0` -. "$path/SETUP.sh" - -extra_flags="$amd64_cflags $fast_cflags -g $wsrep_cflags" -extra_configs="$amd64_configs $wsrep_configs --with-wsrep" - -. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-debug-wsrep b/BUILD/compile-pentium-debug-wsrep deleted file mode 100755 index ee68e3fd0c1..00000000000 --- a/BUILD/compile-pentium-debug-wsrep +++ /dev/null @@ -1,12 +0,0 @@ -#! /bin/sh -x - -path=`dirname $0` -set -- "$@" --with-debug=full -. "$path/SETUP.sh" - -extra_flags="$pentium_cflags $debug_cflags -g -O0 $wsrep_cflags" -c_warnings="$c_warnings $debug_extra_warnings" -cxx_warnings="$cxx_warnings $debug_extra_warnings" -extra_configs="$pentium_configs $debug_configs $wsrep_configs --with-wsrep" - -. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-wsrep b/BUILD/compile-pentium-wsrep deleted file mode 100755 index eeb14310e4e..00000000000 --- a/BUILD/compile-pentium-wsrep +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/sh - -path=`dirname $0` -. "$path/SETUP.sh" - -extra_flags="$pentium_cflags $fast_cflags $wsrep_cflags" -extra_configs="$pentium_configs $wsrep_configs --with-wsrep" - -#strip=yes - -. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-wsrep b/BUILD/compile-pentium64-wsrep deleted file mode 100755 index 0bccb34e753..00000000000 --- a/BUILD/compile-pentium64-wsrep +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/sh - -# Copyright (C) 2006, 2007 MySQL AB -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public -# License along with this library; if not, write to the Free -# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -# MA 02111-1307, USA - -path=`dirname $0` -. "$path/SETUP.sh" - -extra_flags="$pentium64_cflags $fast_cflags -g $wsrep_cflags" -extra_configs="$pentium_configs $static_link $wsrep_configs --with-wsrep" -CC="$CC --pipe" -strip=yes - -. "$path/FINISH.sh" diff --git a/Docs/README-wsrep b/Docs/README-wsrep deleted file mode 100644 index 025379764b2..00000000000 --- a/Docs/README-wsrep +++ /dev/null @@ -1,487 +0,0 @@ -Codership Oy -http://www.codership.com - - -DISCLAIMER - -THIS SOFTWARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -IN NO EVENT SHALL CODERSHIP OY BE HELD LIABLE TO ANY PARTY FOR ANY DAMAGES -RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE. - -Trademark Information. - -MySQL is a trademark or registered trademark of Oracle and/or its affiliates. -Other trademarks are the property of their respective owners. - -Licensing Information. - -Please see file COPYING that came with this distribution - -Source code can be found at -wsrep API: https://launchpad.net/wsrep -MySQL patch: https://launchpad.net/codership-mysql - - -ABOUT THIS DOCUMENT - -This document covers installation and configuration issues specific to this -wsrep-patched MySQL distribution by Codership. It does not cover the use or -administration of MySQL server per se. The reader is assumed to know how to -install, configure, administer and use standard MySQL server version 5.1.xx. - - - MYSQL-5.5.x/wsrep-23.x - -CONTENTS: -========= -1. WHAT IS WSREP PATCH FOR MYSQL -2. INSTALLATION -3. FIRST TIME SETUP - 3.1 CONFIGURATION FILES - 3.2 DATABASE PRIVILEGES - 3.3 CHECK AND CORRECT FIREWALL SETTINGS - 3.4 SELINUX - 3.5 APPARMOR - 3.6 CONNECT TO CLUSTER -4. UPGRADING FROM MySQL 5.1.x -5. CONFIGURATION OPTIONS - 5.1 MANDATORY MYSQL OPTIONS - 5.2 WSREP OPTIONS -6. ONLINE SCHEMA UPGRADE - 6.1 TOTAL ORDER ISOLATION (TOI) - 6.2 ROLLING SCHEMA UPGRADE (RSU) -7. LIMITATIONS - - -1. WHAT IS WSREP PATCH FOR MYSQL/INNODB - -Wsrep API developed by Codership Oy is a modern generic (database-agnostic) -replication API for transactional databases with a goal to make database -replication/logging subsystem completely modular and pluggable. It is developed -with flexibility and completeness in mind to satisfy broad range of modern -replication scenarios. It is equally suitable for synchronous and asynchronous, -master-slave and multi-master replication. - -wsrep stands for Write Set REPlication. - -Wsrep patch for MySQL/InnoDB allows MySQL server to load and use various wsrep -API implementations ("wsrep providers") with different qualities of service. -Without wsrep provider MySQL-wsrep server will function like a regular -standalone server. - - -2. INSTALLATION - -In the examples below mysql authentication options are omitted for brevity. - -2.1 Download and install mysql-wsrep package. - -Download binary package for your Linux distribution from -https://launchpad.net/codership-mysql/ - -2.1.1 On Debian and Debian-derived distributions. - -Upgrade from mysql-server-5.0 to mysql-wsrep is not supported yet, please -upgrade to mysql-server-5.1 first. - -If you're installing over an existing mysql installation, mysql-server-wsrep -will conflict with mysql-server-5.1 package, so remove it first: - -$ sudo apt-get remove mysql-server-5.1 mysql-server-core-5.1 - -mysql-server-wsrep requires psmisc and mysql-client-5.1.47 (or later). -MySQL 5.1 packages can be found from backports repositories. -For further information about configuring and using Debian or Ubuntu -backports, see: - -* http://backports.debian.org - -* https://help.ubuntu.com/community/UbuntuBackports - -For example, installation of required packages on Debian Lenny: - -$ sudo apt-get install psmisc -$ sudo apt-get -t lenny-backports install mysql-client-5.1 - -Now you should be able to install mysql-wsrep package: - -$ sudo dpkg -i - -2.1.2 On CentOS and similar RPM-based distributions. - -If you're migrating from existing MySQL installation, there are two variants: - - a) If you're already using official MySQL-server-community 5.1.x RPM from - Oracle: - - # rpm -e mysql-server - - b) If you're upgrading from the stock mysql-5.0.77 on CentOS: - - 1) Make sure that the following packages are not installed: - # rpm --nodeps --allmatches -e mysql-server mysql-test mysql-bench - - 2) Install *official* MySQL-shared-compat-5.1.x from - http://dev.mysql.com/downloads/mysql/5.1.html - -Actual installation: - - # rpm -Uvh - - If this fails due to unsatisfied dependencies, install missing packages - (e.g. yum install perl-DBI) and retry. - -Additional packages to consider (if not yet installed): - * galera (multi-master replication provider, https://launchpad.net/galera) - * MySQL-client-community (for connecting to server and mysqldump-based SST) - * rsync (for rsync-based SST) - * xtrabackup and nc (for xtrabackup-based SST) - -2.2 Upgrade system tables. - -If you're upgrading a previous MySQL installation, it might be advisable to -upgrade system tables. To do that start mysqld and run mysql_upgrade command. -Consult MySQL documentation in case of errors. Normally they are not critical -and can be ignored unless specific functionality is needed. - - -3. FIRST TIME SETUP - -Unless you're upgrading an already installed mysql-wsrep package, you will need -to set up a few things to prepare server for operation. - -3.1 CONFIGURATION FILES - -* Make sure system-wide my.cnf does not bind mysqld to 127.0.0.1. That is, if - you have the following line in [mysqld] section, comment it out: - - #bind-address = 127.0.0.1 - -* Make sure system-wide my.cnf contains "!includedir /etc/mysql/conf.d/" line. - -* Edit /etc/mysql/conf.d/wsrep.cnf and set wsrep_provider option by specifying - a path to provider library. If you don't have a provider, leave it as it is. - -* When a new node joins the cluster it'll have to receive a state snapshot from - one of the peers. This requires a privileged MySQL account with access from - the rest of the cluster. Edit /etc/mysql/conf.d/wsrep.cnf and set mysql - login/password pair for SST, for example: - - wsrep_sst_auth=wsrep_sst:wspass - -* See CONFIGURATION section below about other configuration parameters that you - might want to change at this point. - -3.2 DATABASE PRIVILEGES - -Restart MySQL server and connect to it as root to grant privileges to SST -account (empty users confuse MySQL authentication matching rules, we need to -delete them too): - -$ mysql -e "SET wsrep_on=OFF; DELETE FROM mysql.user WHERE user='';" -$ mysql -e "SET wsrep_on=OFF; GRANT ALL ON *.* TO wsrep_sst@'%' IDENTIFIED BY 'wspass'"; - -3.3 CHECK AND CORRECT FIREWALL SETTINGS. - -MySQL-wsrep server needs to be accessible from other cluster members through -its client listening socket and through wsrep provider socket. See your -distribution and wsrep provider documentation for details. For example on -CentOS you might need to do something along these lines: - -# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 3306 -j ACCEPT -# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 4567 -j ACCEPT - -If there is a NAT firewall between the nodes, it must be configured to allow -direct connections between the nodes (e.g. via port forwarding). - -3.4 SELINUX - -If you have SELinux enabled, it may block mysqld from doing required operations. -You'll need to either disable it or configure to allow mysqld to run external -programs and open listen sockets at unprivileged ports (i.e. things that -an unprivileged user can do). See SELinux documentation about it. - -To quickly disable SELinux: -1) run 'setenforce 0' as root. -2) set 'SELINUX=permissive' in /etc/selinux/config - -3.5 APPARMOR - -AppArmor automatically comes with Ubuntu and may also prevent mysqld to from -opening additional ports or run scripts. See AppArmor documentation about its -configuration. To disable AppArmor for mysqld: - -$ cd /etc/apparmor.d/disable/ -$ sudo ln -s /etc/apparmor.d/usr.sbin.mysqld -$ sudo service apparmor restart - - -3.6 CONNECT TO CLUSTER - -Now you're ready to connect to cluster by setting wsrep_cluster_address variable -and monitor status of wsrep provider: - -mysql> SET GLOBAL wsrep_cluster_address=''; -mysql> SHOW STATUS LIKE 'wsrep%'; - - -4 UPGRADING FROM MySQL 5.1.x - -!!! THESE INSTRUCTIONS ARE PRELIMINARY AND INCOMPLETE !!! - -1) BEFORE UPGRADE (while running 5.1.x): - - comment out 'wsrep_provider' setting from configuration files - (my.cnf and/or wsrep.cnf) - - If performing a rolling upgrade on a running cluster, set - wsrep_sst_method=mysqldump. - You might also need to configure wsrep_sst_receive_address and - wsrep_sst_auth appropriately. mysqldump is the only way to transfer data - from 5.1.x to 5.5.x reliably. - - remove innodb_plugin settings from configuration files. - -2) Perform upgrade as usual: - http://dev.mysql.com/doc/refman/5.5/en/upgrading-from-previous-series.html - Don't forget to run 'mysql_upgrade' command. - -3) AFTER UPGRADING individual node: - - uncomment 'wsrep_provider' line in configuration file. - - restart the server and join the cluster. - -4) AFTER UPGRADING the whole cluster: - - revert to usual wsrep SST settings if not 'mysqldump'. - - -5. CONFIGURATION OPTIONS - -5.1 MANDATORY MYSQL OPTIONS - -binlog_format=ROW - This option is required to use row-level replication as opposed to - statement-level. For performance and consistency considerations don't change - that. As a side effect, binlog, if turned on, can be ROW only. In future this - option won't have special meaning. - -innodb_autoinc_lock_mode=2 - This is a required parameter. Without it INSERTs into tables with - AUTO_INCREMENT column may fail. - autoinc lock modes 0 and 1 can cause unresolved deadlock, and make - system unresponsive. - -innodb_locks_unsafe_for_binlog=1 - This option is required for parallel applying. - -5.2 WSREP OPTIONS - -All options are optional except for wsrep_provider, wsrep_cluster_address, and -wsrep_sst_auth. - -wsrep_provider=none - A full path to the library that implements WSREP interface. If none is - specified, the server behaves like a regular mysqld. - -wsrep_provider_options= - Provider-specific option string. Check wsrep provider documentation or - http://www.codership.com/wiki - -wsrep_cluster_address= - Provider-specific cluster address string. This is used to connect a node to - the desired cluster. This option can be given either on mysqld startup or set - during runtime. See wsrep provider documentation for possible values. - -wsrep_cluster_name="my_wsrep_cluster" - Logical cluster name, must be the same for all nodes of the cluster. - -wsrep_node_address= - An option to explicitly specify the network address of the node in the form -
[:port] if autoguessing for some reason does not produce desirable - results (multiple network interfaces, NAT, etc.) - If not explicitly overridden by wsrep_sst_receive_address, the
part - will be used to listen for SST (see below). And the whole
[:port] - will be passed to wsrep provider to be used as a base address in its - communications. - -wsrep_node_name= - Human readable node name (for easier log reading only). Defaults to hostname. - -wsrep_slave_threads=1 - Number of threads dedicated to processing of writesets from other nodes. - For best performance should be few per CPU core. - -wsrep_dbug_option - Options for the built-in DBUG library (independent from what MySQL uses). - Empty by default. Not currently in use. - -wsrep_debug=0 - Enable debug-level logging. - -wsrep_convert_LOCK_to_trx=0 - Implicitly convert locking sessions into transactions inside mysqld. By - itself it does not mean support for locking sessions, but it prevents the - database from going into logically inconsistent state. Note however, that - loading large database dump with LOCK statements might result in abnormally - large transactions and cause an out-of-memory condition - -wsrep_retry_autocommit=1 - Retry autocommit queries and single statement transactions should they fail - certification test. This is analogous to rescheduling an autocommit query - should it go into deadlock with other transactions in the database lock - manager. - -wsrep_auto_increment_control=1 - Automatically adjust auto_increment_increment and auto_increment_offset - variables based on the number of nodes in the cluster. Significantly reduces - certification conflict rate for INSERTS. - -wsrep_drupal_282555_workaround=1 - MySQL seems to have an obscure bug when INSERT into table with - AUTO_INCREMENT column with NULL value for that column can fail with a - duplicate key error. When this option is on, it retries such INSERTs. - Required for stable Drupal operation. Documented at: - http://bugs.mysql.com/bug.php?id=41984 - http://drupal.org/node/282555 - -wsrep_causal_reads=0 - Enforce strict READ COMMITTED semantics on reads and transactions. May - result in additional latencies. It is a session variable. - -wsrep_OSU_method=TOI - Online Schema Upgrade (OSU) can be performed with two alternative methods: - Total Order Isolation (TOI) runs DDL statement in all cluster nodes in - same total order sequence locking the affected table for the duration of the - operation. This may result in the whole cluster being blocked for the - duration of the operation. - Rolling Schema Upgrade (RSU) executes the DDL statement only locally, thus - blocking only one cluster node. During the DDL processing, the node - is not replicating and may be unable to process replication events (due to - table lock). Once DDL operation is complete, the node will catch up and sync - with the cluster to become fully operational again. The DDL statement or - its effects are not replicated, so it is user's responsibility to manually - perform this operation on each of the nodes. - -wsrep_forced_binlog_format=none - Force every transaction to use given binlog format. When this variable is - set to something else than NONE, all transactions will use the given forced - format, regardless of what the client session has specified in binlog_format. - Valid choices for wsrep_forced_binlog_format are: ROW, STATEMENT, MIXED and - special value NONE, meaning that there is no forced binlog format in effect. - This variable was intruduced to support STATEMENT format replication during - rolling schema upgrade processing. However, in most cases ROW replication - is valid for asymmetrict schema replication. - -State snapshot transfer options. - -When a new node joins the cluster it has to synchronize its initial state with -the other cluster members by transferring state snapshot from one of them. -The options below govern how this happens and should be set up before attempting -to join or start a cluster. - -wsrep_sst_method=mysqldump - What method to use to copy database state to a newly joined node. Supported - methods: - - mysqldump: slow (except for small datasets) but most tested. - - rsync: much faster on large datasets. - - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. - - xtrabackup: very fast and practically non-blocking SST method based on - Percona's xtrabackup tool. - - (for xtrabackup to work the following settings must be present in my.cnf - on all nodes: - [mysqld] - wsrep_sst_auth=root: - datadir= - [client] - socket= - ) - -wsrep_sst_receive_address= - Address (hostname:port) at which this node wants to receive state snapshot. - Defaults to mysqld bind address, and if that is not specified (0.0.0.0) - - to the first IP of eth0 + mysqld bind port. - NOTE: check that your firewall allows connections to this address from other - cluster nodes. - -wsrep_sst_auth= - Authentication information needed for state transfer. Depends on the state - transfer method. For mysqldump-based SST it is - : - and should be the same on all nodes - it is used to authenticate with both - state snapshot receiver and state snapshot donor. - -wsrep_sst_donor= - A name of the node which should serve as state snapshot donor. This allows - to control which node will serve state snapshot request. By default the - most suitable node is chosen by wsrep provider. This is the same as given in - wsrep_node_name. - - -6. ONLINE SCHEMA UPGRADE - - Schema upgrades mean any data definition statements (DDL statemnents) run - for the database. They change the database structure and are non- - transactional. - - Release 22.3 brings a new method for performing schema upgrades. User can - now choose whether to use the traditional total order isolation or new - rolling schema upgrade method. The OSU method choice is done by global - parameter: 'wsrep_OSU_method'. - -6.1 Total Order Isolation (TOI) - - With earlier releases, DDL processing happened always by Total Order - Isolation (TOI) method. With TOI, the DDL was scheduled to be processed in - same transaction seqeuncing 'slot' in each cluster node. - The processing is secured by locking the affected table from any other use. - With TOI method, the whole cluster has part of the database locked for the - duration of the DDL processing. - -6.2 Rolling Schema Upgrade (RSU) - - Rolling schema upgrade is new DDL processing method, where DDL will be - processed locally for the node. The node is disconnected of the replication - for the duration of the DDL processing, so that there is only DDL statement - processing in the node and it does not block the rest of the cluster. When - the DDL processing is complete, the node applies delayed replication events - and synchronizes back with the cluster. - The DDL can then be executed cluster-wide by running the same DDL statement - for each node in turn. When this rolling schema upgrade proceeds, part of - the cluster will have old schema structure and part of the cluster will have - new schema structure. - - -7. LIMITATIONS - -1) Currently replication works only with InnoDB storage engine. Any writes to - tables of other types, including system (mysql.*) tables are not replicated. - However, DDL statements are replicated in statement level, and changes - to mysql.* tables will get replicated that way. - So, you can safely issue: CREATE USER..., - but issuing: INSERT INTO mysql.user..., will not be replicated. - -2) DELETE operation is unsupported on tables without primary key. Also rows in - tables without primary key may appear in different order on different nodes. - As a result SELECT...LIMIT... may return slightly different sets. - -3) Unsupported queries: - * LOCK/UNLOCK TABLES cannot be supported in multi-master setups. - * lock functions (GET_LOCK(), RELEASE_LOCK()... ) - -4) Query log cannot be directed to table. If you enable query logging, - you must forward the log to a file: - log_output = FILE - Use general_log and general_log_file to choose query logging and the - log file name - -5) Maximum allowed transaction size is defined by wsrep_max_ws_rows and - wsrep_max_ws_size. Anything bigger (e.g. huge LOAD DATA) will be rejected. - -6) Due to cluster level optimistic concurrency control, transaction issuing - COMMIT may still be aborted at that stage. There can be two transactions. - writing to same rows and committing in separate cluster nodes, and only one - of the them can successfully commit. The failing one will be aborted. - For cluster level aborts, MySQL/galera cluster gives back deadlock error. - code (Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK)). - -7) XA transactions can not be supported due to possible rollback on commit. - diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake deleted file mode 100644 index b0c1dce34dc..00000000000 --- a/cmake/wsrep.cmake +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2011, Codership Oy . -# -# 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 - -# We need to generate a proper spec file even without --with-wsrep flag, -# so WSREP_VERSION is produced regardless - -# Set the patch version -SET(WSREP_PATCH_VERSION "7rc1") - -# Obtain patch revision number -SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) -IF(NOT WSREP_PATCH_REVNO) - EXECUTE_PROCESS( - COMMAND bzr revno - OUTPUT_VARIABLE WSREP_PATCH_REVNO - RESULT_VARIABLE RESULT - ) -STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_PATCH_REVNO "${WSREP_PATCH_REVNO}") -#FILE(WRITE "wsrep_config" "Debug: WSREP_PATCH_REVNO result: ${RESULT}\n") -ENDIF() -IF(NOT WSREP_PATCH_REVNO) - SET(WSREP_PATCH_REVNO "XXXX") -ENDIF() - -# Obtain wsrep API version -EXECUTE_PROCESS( - COMMAND sh -c "grep WSREP_INTERFACE_VERSION ${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h | cut -d '\"' -f 2" - OUTPUT_VARIABLE WSREP_API_VERSION - RESULT_VARIABLE RESULT -) -#FILE(WRITE "wsrep_config" "Debug: WSREP_API_VERSION result: ${RESULT}\n") -STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_API_VERSION "${WSREP_API_VERSION}") - -SET(WSREP_VERSION - "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" -) - -OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ON) -IF (WITH_WSREP) - SET(WSREP_C_FLAGS "-DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WSREP_C_FLAGS}") - SET(COMPILATION_COMMENT "${COMPILATION_COMMENT}, wsrep_${WSREP_VERSION}") - SET(WITH_EMBEDDED_SERVER OFF CACHE INTERNAL "" FORCE) -ENDIF() - -# diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh deleted file mode 100644 index 5c292465ecc..00000000000 --- a/scripts/wsrep_sst_common.sh +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (C) 2010 Codership Oy -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# This is a common command line parser to be sourced by other SST scripts - -set -u - -WSREP_SST_OPT_BYPASS=0 - -while [ $# -gt 0 ]; do -case "$1" in - '--address') - readonly WSREP_SST_OPT_ADDR="$2" - shift - ;; - '--auth') - readonly WSREP_SST_OPT_AUTH="$2" - shift - ;; - '--bypass') - WSREP_SST_OPT_BYPASS=1 - ;; - '--datadir') - readonly WSREP_SST_OPT_DATA="$2" - shift - ;; - '--defaults-file') - readonly WSREP_SST_OPT_CONF="$2" - shift - ;; - '--host') - readonly WSREP_SST_OPT_HOST="$2" - shift - ;; - '--local-port') - readonly WSREP_SST_OPT_LPORT="$2" - shift - ;; - '--parent') - readonly WSREP_SST_OPT_PARENT="$2" - shift - ;; - '--password') - readonly WSREP_SST_OPT_PSWD="$2" - shift - ;; - '--port') - readonly WSREP_SST_OPT_PORT="$2" - shift - ;; - '--role') - readonly WSREP_SST_OPT_ROLE="$2" - shift - ;; - '--socket') - readonly WSREP_SST_OPT_SOCKET="$2" - shift - ;; - '--user') - readonly WSREP_SST_OPT_USER="$2" - shift - ;; - '--gtid') - readonly WSREP_SST_OPT_GTID="$2" - shift - ;; - *) # must be command - # usage - # exit 1 - ;; -esac -shift -done -readonly WSREP_SST_OPT_BYPASS - -wsrep_log() -{ - # echo everything to stderr so that it gets into common error log - # deliberately made to look different from the rest of the log - local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" - echo "WSREP_SST: $* ($tst)" >>/dev/stderr -} - -wsrep_log_error() -{ - wsrep_log "[ERROR] $*" -} - -wsrep_log_info() -{ - wsrep_log "[INFO] $*" -} - diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh deleted file mode 100644 index 120533edc4e..00000000000 --- a/scripts/wsrep_sst_mysqldump.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh -e -# Copyright (C) 2009 Codership Oy -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# This is a reference script for mysqldump-based state snapshot tansfer - -. $(dirname $0)/wsrep_sst_common - -EINVAL=22 - -local_ip() -{ - PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - - [ "$1" = "127.0.0.1" ] && return 0 - [ "$1" = "localhost" ] && return 0 - [ "$1" = "$(hostname -s)" ] && return 0 - [ "$1" = "$(hostname -f)" ] && return 0 - [ "$1" = "$(hostname -d)" ] && return 0 - - # Now if ip program is not found in the path, we can't return 0 since - # it would block any address. Thankfully grep should fail in this case - ip route get "$1" | grep local >/dev/null && return 0 - - return 1 -} - -if test -z "$WSREP_SST_OPT_USER"; then err "USER cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_LPORT"; then err "LPORT cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_SOCKET";then err "SOCKET cannot be nil";exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_GTID"; then err "GTID cannot be nil"; exit $EINVAL; fi - -if local_ip $WSREP_SST_OPT_HOST && \ - [ "$WSREP_SST_OPT_PORT" = "$WSREP_SST_OPT_LPORT" ] -then - wsrep_log_error \ - "destination address '$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT' matches source address." - exit $EINVAL -fi - -# Check client version -if ! mysql --version | grep 'Distrib 5.5' >/dev/null -then - mysql --version >&2 - err "this operation requires MySQL client version 5.5.x" - exit $EINVAL -fi - -AUTH="-u$WSREP_SST_OPT_USER" -if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi - -STOP_WSREP="SET wsrep_on=OFF;" - -# NOTE: we don't use --routines here because we're dumping mysql.proc table -MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ ---add-drop-database --add-drop-table --skip-add-locks --create-options \ ---disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ ---skip-comments --flush-privileges --all-databases" - -# mysqldump cannot restore CSV tables, fix this issue -CSV_TABLES_FIX=" -set sql_mode=''; - -USE mysql; - -SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, thread_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, command_type VARCHAR(64) NOT NULL,argument MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"General log\"', 'SET @dummy = 0'); - -PREPARE stmt FROM @str; -EXECUTE stmt; -DROP PREPARE stmt; - -SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"Slow log\"', 'SET @dummy = 0'); - -PREPARE stmt FROM @str; -EXECUTE stmt; -DROP PREPARE stmt;" - -SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" - -MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ -"--disable-reconnect --connect_timeout=10" - -# need to disable logging when loading the dump -# reason is that dump contains ALTER TABLE for log tables, and -# this causes an error if logging is enabled -GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@GENERAL_LOG"` -SLOW_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@SLOW_QUERY_LOG"` -$MYSQL -e"$STOP_WSREP SET GLOBAL GENERAL_LOG=OFF" -$MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF" - -# commands to restore log settings -RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" -RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" - -if [ $WSREP_SST_OPT_BYPASS -eq 0 ] -then - (echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX \ - && echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG \ - && echo $SET_START_POSITION \ - || echo "SST failed to complete;") | $MYSQL -else - wsrep_log_info "Bypassing state dump." - echo $SET_START_POSITION | $MYSQL -fi - -# diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh deleted file mode 100644 index d510477535c..00000000000 --- a/scripts/wsrep_sst_rsync.sh +++ /dev/null @@ -1,210 +0,0 @@ -#!/bin/bash -ue - -# Copyright (C) 2010 Codership Oy -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# This is a reference script for rsync-based state snapshot tansfer - -RSYNC_PID= -RSYNC_CONF= - -. $(dirname $0)/wsrep_sst_common - -cleanup_joiner() -{ - wsrep_log_info "Joiner cleanup." - local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) - [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \ - || : - rm -rf "$RSYNC_CONF" - rm -rf "$MAGIC_FILE" - rm -rf "$RSYNC_PID" - echo " done." >&2 -} - -check_pid() -{ - local pid_file=$1 - [ -r "$pid_file" ] && ps -p $(cat $pid_file) >/dev/null 2>&1 -} - -check_pid_and_port() -{ - local pid_file=$1 - local rsync_pid=$(cat $pid_file) - local rsync_port=$2 - - check_pid $pid_file && \ - netstat -anpt 2>/dev/null | \ - grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null -} - -MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" -rm -rf "$MAGIC_FILE" - -if [ "$WSREP_SST_OPT_ROLE" = "donor" ] -then - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - - FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" - rm -rf "$FLUSHED" - - # Use deltaxfer only for WAN - inv=$(basename $0) - [ "$inv" = "wsrep_sst_rsync_wan" ] && WHOLE_FILE_OPT="" \ - || WHOLE_FILE_OPT="--whole-file" - - echo "flush tables" - - # wait for tables flushed and state ID written to the file - while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1 - do - sleep 0.2 - done - - STATE="$(cat $FLUSHED)" - rm -rf "$FLUSHED" - - sync - - # Old filter - include everything except selected - # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ - # --exclude '*.conf' --exclude core --exclude 'galera.*' \ - # --exclude grastate.txt --exclude '*.pem' \ - # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') - - # New filter - exclude everything except dirs (schemas) and innodb files - FILTER=(-f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') - - RC=0 - rsync --archive --no-times --ignore-times --inplace --delete --quiet \ - $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA" \ - rsync://$WSREP_SST_OPT_ADDR || RC=$? - - [ $RC -ne 0 ] && echo "rsync returned code $RC:" >> /dev/stderr - - case $RC in - 0) RC=0 # Success - ;; - 12) RC=71 # EPROTO - wsrep_log_error \ - "rsync server on the other end has incompatible protocol. " \ - "Make sure you have the same version of rsync on all nodes." - ;; - 22) RC=12 # ENOMEM - ;; - *) RC=255 # unknown error - ;; - esac - - [ $RC -ne 0 ] && exit $RC - - else # BYPASS - wsrep_log_info "Bypassing state dump." - STATE="$WSREP_SST_OPT_GTID" - fi - - echo "continue" # now server can resume updating data - - echo "$STATE" > "$MAGIC_FILE" - rsync -aqc "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR - - echo "done $STATE" - -elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ] -then - MYSQLD_PID=$WSREP_SST_OPT_PARENT - - MODULE="rsync_sst" - - RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" - - if check_pid $RSYNC_PID - then - echo "rsync daemon already running." - exit 114 # EALREADY - fi - rm -rf "$RSYNC_PID" - - ADDR=$WSREP_SST_OPT_ADDR - RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }') - if [ -z "$RSYNC_PORT" ] - then - RSYNC_PORT=4444 - ADDR="$(echo $ADDR | awk -F ':' '{ print $1 }'):$RSYNC_PORT" - fi - - trap "exit 32" HUP PIPE - trap "exit 3" INT TERM - trap cleanup_joiner EXIT - - MYUID=$(id -u) - MYGID=$(id -g) - RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" - -cat << EOF > "$RSYNC_CONF" -pid file = $RSYNC_PID -use chroot = no -[$MODULE] - path = $WSREP_SST_OPT_DATA - read only = no - timeout = 300 - uid = $MYUID - gid = $MYGID -EOF - -# rm -rf "$DATA"/ib_logfile* # we don't want old logs around - - # listen at all interfaces (for firewalled setups) - rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF" - - until check_pid_and_port $RSYNC_PID $RSYNC_PORT - do - sleep 0.2 - done - - echo "ready $ADDR/$MODULE" - - # wait for SST to complete by monitoring magic file - while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \ - ps -p $MYSQLD_PID >/dev/null - do - sleep 1 - done - - if ! ps -p $MYSQLD_PID >/dev/null - then - echo "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." >&2 - exit 32 - fi - - if [ -r "$MAGIC_FILE" ] - then - cat "$MAGIC_FILE" # output UUID:seqno - else - # this message should cause joiner to abort - echo "rsync process ended without creating '$MAGIC_FILE'" - fi - -# cleanup_joiner -else - echo "Unrecognized role: '$WSREP_SST_OPT_ROLE'" - exit 22 # EINVAL -fi - -exit 0 diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh deleted file mode 100644 index 08552f50a44..00000000000 --- a/scripts/wsrep_sst_xtrabackup.sh +++ /dev/null @@ -1,222 +0,0 @@ -#!/bin/bash -ue - -# Copyright (C) 2011 Percona Inc -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# This is a reference script for Percona XtraBackup-based state snapshot tansfer - -TMPDIR="/tmp" - -. $(dirname $0)/wsrep_sst_common - -cleanup_joiner() -{ -#set -x - local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') - wsrep_log_info "Killing nc pid $PID" - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$MAGIC_FILE" -#set +x -} - -check_pid() -{ - local pid_file="$1" - [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 -} - -kill_xtrabackup() -{ -#set -x - local PID=$(cat $XTRABACKUP_PID) - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$XTRABACKUP_PID" -#set +x -} - -# waits ~10 seconds for nc to open the port and then reports ready -# (regardless of timeout) -wait_for_nc() -{ - local PORT=$1 - local ADDR=$2 - local MODULE=$3 - for i in $(seq 1 50) - do - netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \ - sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break - sleep 0.2 - done - echo "ready ${ADDR}/${MODULE}" -} - -INNOBACKUPEX_BIN=innobackupex -INNOBACKUPEX_ARGS="" -NC_BIN=nc - -for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do - if ! which ${!TOOL_BIN} > /dev/null 2>&1 - then - echo "Can't find ${!TOOL_BIN} in the path" - exit 22 # EINVAL - fi -done - -#ROLE=$1 -#ADDR=$2 -readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) -readonly DATA="${WSREP_SST_OPT_DATA}" -#CONF=$5 - -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" - -MAGIC_FILE="${DATA}/${INFO_FILE}" -rm -f "${MAGIC_FILE}" - -if [ "$WSREP_SST_OPT_ROLE" = "donor" ] -then - -# UUID=$6 -# SEQNO=$7 -# BYPASS=$8 - - NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') - REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - - INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar - --defaults-file=${WSREP_SST_OPT_CONF} - --socket=${WSREP_SST_OPT_SOCKET}" - - if [ "${AUTH[0]}" != "(null)" ]; then - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}" - fi - - if [ ${#AUTH[*]} -eq 2 ]; then - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" - fi - - set +e - - # This file and variable seems to have no effect and probably should be deleted - XTRABACKUP_PID=$(mktemp --tmpdir wsrep_sst_xtrabackupXXXX.pid) - - ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ - 2> ${DATA}/innobackup.backup.log | \ - ${NC_BIN} ${REMOTEIP} ${NC_PORT} - - RC=( "${PIPESTATUS[@]}" ) - set -e - - if [ ${RC[0]} -ne 0 ]; then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ - "Check ${DATA}/innobackup.backup.log" - exit 22 - elif [ ${RC[1]} -ne 0 ]; then - wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}" - exit 22 - fi - - if check_pid "${XTRABACKUP_PID}" - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - exit 22 - fi - - rm -f "${XTRABACKUP_PID}" - - else # BYPASS - STATE="${WSREP_SST_OPT_GTID}" - echo "continue" # now server can resume updating data - echo "${STATE}" > "${MAGIC_FILE}" - echo "1" > "${DATA}/${IST_FILE}" - (cd ${DATA}; tar cf - ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} - rm -f ${DATA}/${IST_FILE} - fi - - echo "done ${WSREP_SST_OPT_GTID}" - -elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] -then - MODULE="xtrabackup_sst" - - rm -f ${DATA}/xtrabackup_* - - ADDR=${WSREP_SST_OPT_ADDR} - NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }') - if [ -z "${NC_PORT}" ] - then - NC_PORT=4444 - ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}" - fi - - wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & - -# trap "exit 32" HUP PIPE -# trap "exit 3" INT TERM - trap cleanup_joiner HUP PIPE INT TERM - - set +e - ${NC_BIN} -dl ${NC_PORT} | tar xfi - -C ${DATA} 1>&2 - RC=( "${PIPESTATUS[@]}" ) - set -e - - wait %% # join wait_for_nc thread - - if [ ${RC[0]} -ne 0 -o ${RC[1]} -ne 0 ]; - then - wsrep_log_error "Error while getting st data from donor node: " \ - "${RC[0]}, ${RC[1]}" - exit 32 - fi - - if [ ! -r "${MAGIC_FILE}" ] - then - # this message should cause joiner to abort - wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" - exit 32 - fi - - if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null - then - wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." >&2 - exit 32 - fi - - if [ ! -r "${IST_FILE}" ] - then - rm -f ${DATA}/ib_logfile* - ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \ - --ibbackup=xtrabackup ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log - if [ $? -ne 0 ]; - then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" >&2 - exit 22 - fi - fi - - cat "${MAGIC_FILE}" # output UUID:seqno - -else - wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}" - exit 22 # EINVAL -fi - -exit 0 diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc deleted file mode 100644 index 5764be39093..00000000000 --- a/sql/wsrep_check_opts.cc +++ /dev/null @@ -1,392 +0,0 @@ -/* Copyright 2011 Codership Oy - - 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 -#include -//#include -//#include - -#include "wsrep_mysqld.h" - -#include -#include -#include -#include - -/* This file is about checking for correctness of mysql configuration options */ - -struct opt -{ - const char* const name; - const char* value; -}; - -/* A list of options to check. - * At first we assume default values and then see if they are changed on CLI or - * in my.cnf */ -static struct opt opts[] = -{ - { "wsrep_slave_threads", "1" }, // mysqld.cc - { "bind_address", "0.0.0.0" }, // mysqld.cc - { "wsrep_sst_method","mysqldump" }, // mysqld.cc - { "wsrep_sst_receive_address","AUTO"}, // mysqld.cc - { "binlog_format", "ROW" }, // mysqld.cc - { "wsrep_provider", "none" }, // mysqld.cc - { "query_cache_type", "0" }, // mysqld.cc - { "query_cache_size", "0" }, // mysqld.cc - { "locked_in_memory", "0" }, // mysqld.cc - { "wsrep_cluster_address", "0" }, // mysqld.cc - { "locks_unsafe_for_binlog", "0" }, // ha_innodb.cc - { "autoinc_lock_mode", "1" }, // ha_innodb.cc - { 0, 0 } -}; - -enum -{ - WSREP_SLAVE_THREADS, - BIND_ADDRESS, - WSREP_SST_METHOD, - WSREP_SST_RECEIVE_ADDRESS, - BINLOG_FORMAT, - WSREP_PROVIDER, - QUERY_CACHE_TYPE, - QUERY_CACHE_SIZE, - LOCKED_IN_MEMORY, - WSREP_CLUSTER_ADDRESS, - LOCKS_UNSAFE_FOR_BINLOG, - AUTOINC_LOCK_MODE -}; - - -/* A class to make a copy of argv[] vector */ -struct argv_copy -{ - int const argc_; - char** argv_; - - argv_copy (int const argc, const char* const argv[]) : - argc_ (argc), - argv_ (reinterpret_cast(calloc(argc_, sizeof(char*)))) - { - if (argv_) - { - for (int i = 0; i < argc_; ++i) - { - argv_[i] = strdup(argv[i]); - - if (!argv_[i]) - { - argv_free (); // free whatever bee allocated - return; - } - } - } - } - - ~argv_copy () { argv_free (); } - -private: - argv_copy (const argv_copy&); - argv_copy& operator= (const argv_copy&); - - void argv_free() - { - if (argv_) - { - for (int i = 0; (i < argc_) && argv_[i] ; ++i) free (argv_[i]); - free (argv_); - argv_ = 0; - } - } -}; - -/* a short corresponding to '--' byte sequence */ -static short const long_opt_prefix ('-' + ('-' << 8)); - -/* Normalizes long options to have '_' instead of '-' */ -static int -normalize_opts (argv_copy& a) -{ - if (a.argv_) - { - for (int i = 0; i < a.argc_; ++i) - { - char* ptr = a.argv_[i]; - if (long_opt_prefix == *(short*)ptr) // long option - { - ptr += 2; - const char* end = strchr(ptr, '='); - - if (!end) end = ptr + strlen(ptr); - - for (; ptr != end; ++ptr) if ('-' == *ptr) *ptr = '_'; - } - } - - return 0; - } - - return EINVAL; -} - -/* Find required options in the argument list and change their values */ -static int -find_opts (argv_copy& a, struct opt* const opts) -{ - for (int i = 0; i < a.argc_; ++i) - { - char* ptr = a.argv_[i] + 2; // we're interested only in long options - - struct opt* opt = opts; - for (; 0 != opt->name; ++opt) - { - if (!strstr(ptr, opt->name)) continue; // try next option - - /* 1. try to find value after the '=' */ - opt->value = strchr(ptr, '=') + 1; - - /* 2. if no '=', try next element in the argument vector */ - if (reinterpret_cast(1) == opt->value) - { - /* also check that the next element is not an option itself */ - if (i + 1 < a.argc_ && *(a.argv_[i + 1]) != '-') - { - ++i; - opt->value = a.argv_[i]; - } - else opt->value = ""; // no value supplied (like boolean opt) - } - - break; // option found, break inner loop - } - } - - return 0; -} - -/* Parses string for an integer. Returns 0 on success. */ -int get_long_long (const struct opt& opt, long long* const val, int const base) -{ - const char* const str = opt.value; - - if ('\0' != *str) - { - char* endptr; - - *val = strtoll (str, &endptr, base); - - if ('k' == *endptr || 'K' == *endptr) - { - *val *= 1024L; - endptr++; - } - else if ('m' == *endptr || 'M' == *endptr) - { - *val *= 1024L * 1024L; - endptr++; - } - else if ('g' == *endptr || 'G' == *endptr) - { - *val *= 1024L * 1024L * 1024L; - endptr++; - } - - if ('\0' == *endptr) return 0; // the whole string was a valid integer - } - - WSREP_ERROR ("Bad value for *%s: '%s'. Should be integer.", - opt.name, opt.value); - - return EINVAL; -} - -/* This is flimzy coz hell knows how mysql interprets boolean strings... - * and, no, I'm not going to become versed in how mysql handles options - - * I'd rather sing. - - Aha, http://dev.mysql.com/doc/refman/5.1/en/dynamic-system-variables.html: - Variables that have a type of “boolean†can be set to 0, 1, ON or OFF. (If you - set them on the command line or in an option file, use the numeric values.) - - So it is '0' for FALSE, '1' or empty string for TRUE - - */ -int get_bool (const struct opt& opt, bool* const val) -{ - const char* str = opt.value; - - while (isspace(*str)) ++str; // skip initial whitespaces - - ssize_t str_len = strlen(str); - switch (str_len) - { - case 0: - *val = true; - return 0; - case 1: - if ('0' == *str || '1' == *str) - { - *val = ('1' == *str); - return 0; - } - } - - WSREP_ERROR ("Bad value for *%s: '%s'. Should be '0', '1' or empty string.", - opt.name, opt.value); - - return EINVAL; -} - -static int -check_opts (int const argc, const char* const argv[], struct opt opts[]) -{ - /* First, make a copy of argv to be able to manipulate it */ - argv_copy a(argc, argv); - - if (!a.argv_) - { - WSREP_ERROR ("Could not copy argv vector: not enough memory."); - return ENOMEM; - } - - int err = normalize_opts (a); - if (err) - { - WSREP_ERROR ("Failed to normalize options."); - return err; - } - - err = find_opts (a, opts); - if (err) - { - WSREP_ERROR ("Failed to parse options."); - return err; - } - - /* At this point we have updated default values in our option list to - what has been specified on the command line / my.cnf */ - - long long slave_threads; - err = get_long_long (opts[WSREP_SLAVE_THREADS], &slave_threads, 10); - if (err) return err; - - int rcode = 0; - - if (slave_threads > 1) - /* Need to check AUTOINC_LOCK_MODE and LOCKS_UNSAFE_FOR_BINLOG */ - { - long long autoinc_lock_mode; - err = get_long_long (opts[AUTOINC_LOCK_MODE], &autoinc_lock_mode, 10); - if (err) return err; - - bool locks_unsafe_for_binlog; - err = get_bool (opts[LOCKS_UNSAFE_FOR_BINLOG],&locks_unsafe_for_binlog); - if (err) return err; - - if (autoinc_lock_mode != 2) - { - WSREP_ERROR ("Parallel applying (wsrep_slave_threads > 1) requires" - " innodb_autoinc_lock_mode = 2."); - rcode = EINVAL; - } - } - - long long query_cache_size, query_cache_type; - if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10))) - return err; - if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10))) - return err; - - if (0 != query_cache_size && 0 != query_cache_type) - { - WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)", - query_cache_size, query_cache_type); - rcode = EINVAL; - } - - bool locked_in_memory; - err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory); - if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; } - if (locked_in_memory) - { - WSREP_ERROR ("Memory locking is not supported (locked_in_memory=%s)", - locked_in_memory ? "ON" : "OFF"); - rcode = EINVAL; - } - - if (!strcasecmp(opts[WSREP_SST_METHOD].value,"mysqldump")) - { - if (!strcasecmp(opts[BIND_ADDRESS].value, "127.0.0.1") || - !strcasecmp(opts[BIND_ADDRESS].value, "localhost")) - { - WSREP_ERROR ("wsrep_sst_method is set to 'mysqldump' yet " - "mysqld bind_address is set to '%s', which makes it " - "impossible to receive state transfer from another " - "node, since mysqld won't accept such connections. " - "If you wish to use mysqldump state transfer method, " - "set bind_address to allow mysql client connections " - "from other cluster members (e.g. 0.0.0.0).", - opts[BIND_ADDRESS].value); - rcode = EINVAL; - } - } - else - { - // non-mysqldump SST requires wsrep_cluster_address on startup - if (strlen(opts[WSREP_CLUSTER_ADDRESS].value) == 0) - { - WSREP_ERROR ("%s SST method requires wsrep_cluster_address to be " - "configured on startup.",opts[WSREP_SST_METHOD].value); - rcode = EINVAL; - } - } - - if (strcasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, "AUTO")) - { - if (!strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, - "127.0.0.1", strlen("127.0.0.1")) || - !strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, - "localhost", strlen("localhost"))) - { - WSREP_WARN ("wsrep_sst_receive_address is set to '%s' which " - "makes it impossible for another host to reach this " - "one. Please set it to the address which this node " - "can be connected at by other cluster members.", - opts[WSREP_SST_RECEIVE_ADDRESS].value); -// rcode = EINVAL; - } - } - - if (strcasecmp(opts[WSREP_PROVIDER].value, "none")) - { - if (strcasecmp(opts[BINLOG_FORMAT].value, "ROW")) - { - WSREP_ERROR ("Only binlog_format = 'ROW' is currently supported. " - "Configured value: '%s'. Please adjust your " - "configuration.", opts[BINLOG_FORMAT].value); - - rcode = EINVAL; - } - } - - return rcode; -} - -int -wsrep_check_opts (int const argc, char* const* const argv) -{ - return check_opts (argc, argv, opts); -} - diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc deleted file mode 100644 index 1fc2372a57c..00000000000 --- a/sql/wsrep_hton.cc +++ /dev/null @@ -1,449 +0,0 @@ -/* Copyright 2008 Codership Oy - - 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 -#include "sql_base.h" -#include "rpl_filter.h" -#include -#include "wsrep_mysqld.h" -#include "wsrep_priv.h" -#include -#include - -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 - -enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); - -/* - a post-commit cleanup on behalf of wsrep. Can't be a part of hton struct. - Is called by THD::transactions.cleanup() -*/ -void wsrep_cleanup_transaction(THD *thd) -{ - if (thd->thread_id == 0) return; - if (thd->wsrep_exec_mode == LOCAL_COMMIT) - { - if (thd->variables.wsrep_on && - thd->wsrep_conflict_state != MUST_REPLAY) - { - if (thd->wsrep_seqno_changed) - { - if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) - { - DBUG_PRINT("wsrep", ("set committed fail")); - WSREP_WARN("set committed fail: %llu %d", - (long long)thd->real_id, thd->stmt_da->status()); - } - } - //else - //WSREP_DEBUG("no trx handle for %s", thd->query()); - thd_binlog_trx_reset(thd); - thd->wsrep_seqno_changed = false; - } - thd->wsrep_exec_mode= LOCAL_STATE; - } -} - -/* - wsrep hton -*/ -handlerton *wsrep_hton; - -void wsrep_register_hton(THD* thd, bool all) -{ - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; - for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) - { - if (i->ht()->db_type == DB_TYPE_INNODB) - { - trans_register_ha(thd, all, wsrep_hton); - thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); - 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_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_ROLLBACK, 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) -{ -#ifndef DBUG_OFF - //wsrep_seqno_t old = thd->wsrep_trx_seqno; -#endif - DBUG_ENTER("wsrep_prepare"); - if ((all || - !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) - { - switch (wsrep_run_wsrep_commit(thd, hton, all)) - { - case WSREP_TRX_OK: - // DBUG_ASSERT(thd->wsrep_trx_seqno > old || - // thd->wsrep_exec_mode == REPL_RECV || - // thd->wsrep_exec_mode == TOTAL_ORDER); - break; - case WSREP_TRX_ROLLBACK: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); - } - } - DBUG_RETURN(0); -} - -static int wsrep_savepoint_set(handlerton *hton, THD *thd, void *sv) -{ - if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); - return rcode; -} -static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) -{ - if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); - return rcode; -} - -static int wsrep_rollback(handlerton *hton, THD *thd, bool all) -{ - DBUG_ENTER("wsrep_rollback"); - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) - { - if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) - { - DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", - (long long)thd->real_id, thd->query()); - } - } - - int rcode = 0; - if (!wsrep_emulate_bin_log) - { - if (all) thd_binlog_trx_reset(thd); - } - - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - DBUG_RETURN(rcode); -} - -int wsrep_commit(handlerton *hton, THD *thd, bool all) -{ - DBUG_ENTER("wsrep_commit"); - - 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, handlerton *hton, bool all) -{ - int rcode = -1; - uint data_len = 0; - uchar *rbr_data = NULL; - IO_CACHE *cache; - int replay_round= 0; - - if (thd->stmt_da->is_error()) { - WSREP_ERROR("commit issue, error: %d %s", - thd->stmt_da->sql_errno(), thd->stmt_da->message()); - } - - DBUG_ENTER("wsrep_run_wsrep_commit"); - 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_wsrep_thd); - 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_wsrep_thd); - // - // 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_wsrep_thd); - } - 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_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) { - DBUG_PRINT("wsrep", ("replicate commit fail")); - thd->wsrep_conflict_state = ABORTED; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - if (wsrep_debug) { - WSREP_INFO("innobase_commit, abort %s", - (thd->query()) ? thd->query() : "void"); - } - DBUG_RETURN(WSREP_TRX_ROLLBACK); - } - - mysql_mutex_lock(&LOCK_wsrep_replaying); - - while (wsrep_replaying > 0 && - thd->wsrep_conflict_state == NO_CONFLICT && - thd->killed == NOT_KILLED && - !shutdown_in_progress) - { - - mysql_mutex_unlock(&LOCK_wsrep_replaying); - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - mysql_mutex_lock(&thd->mysys_var->mutex); - thd_proc_info(thd, "wsrep waiting on replaying"); - thd->mysys_var->current_mutex= &LOCK_wsrep_replaying; - thd->mysys_var->current_cond= &COND_wsrep_replaying; - mysql_mutex_unlock(&thd->mysys_var->mutex); - - mysql_mutex_lock(&LOCK_wsrep_replaying); - // Using timedwait is a hack to avoid deadlock in case if BF victim - // misses the signal. - struct timespec wtime = {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: (%lu) conflict: %d (round: %d)", - wsrep_replaying, 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_wsrep_thd); - 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_wsrep_thd); - WSREP_DEBUG("innobase_commit abort after replaying wait %s", - (thd->query()) ? thd->query() : "void"); - DBUG_RETURN(WSREP_TRX_ROLLBACK); - } - thd->wsrep_query_state = QUERY_COMMITTING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - cache = get_trans_log(thd); - rcode = 0; - if (cache) { - thd->binlog_flush_pending_rows_event(true); - rcode = wsrep_write_cache(cache, &rbr_data, &data_len); - if (rcode) { - WSREP_ERROR("rbr write fail, data_len: %d, %d", data_len, rcode); - if (data_len) my_free(rbr_data); - DBUG_RETURN(WSREP_TRX_ROLLBACK); - } - } - if (data_len == 0) - { - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_exec_mode = LOCAL_COMMIT; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - if (thd->stmt_da->is_ok() && - thd->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->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()); - } - DBUG_RETURN(WSREP_TRX_OK); - } - if (!rcode) { - rcode = wsrep->pre_commit( - wsrep, - (wsrep_conn_id_t)thd->thread_id, - &thd->wsrep_trx_handle, - rbr_data, - data_len, - (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, - &thd->wsrep_trx_seqno); - if (rcode == WSREP_TRX_MISSING) { - rcode = WSREP_OK; - } else if (rcode == WSREP_BF_ABORT) { - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state = MUST_REPLAY; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying++; - WSREP_DEBUG("replaying increased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - thd->wsrep_seqno_changed = true; - } else { - WSREP_ERROR("I/O error reading from thd's binlog iocache: " - "errno=%d, io cache code=%d", my_errno, cache->error); - if (data_len) my_free(rbr_data); - DBUG_ASSERT(0); // failure like this can not normally happen - DBUG_RETURN(WSREP_TRX_ERROR); - } - - if (data_len) { - my_free(rbr_data); - } - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - switch(rcode) { - case 0: - thd->wsrep_exec_mode = LOCAL_COMMIT; - /* 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, - wsrep_cluster_uuid(), - thd->wsrep_trx_seqno); - } - DBUG_PRINT("wsrep", ("replicating commit success")); - - break; - case WSREP_TRX_FAIL: - case WSREP_BF_ABORT: - 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_wsrep_thd); - - DBUG_RETURN(WSREP_TRX_ROLLBACK); - - case WSREP_CONN_FAIL: - WSREP_ERROR("connection failure"); - DBUG_RETURN(WSREP_TRX_ERROR); - default: - WSREP_ERROR("unknown connection failure"); - DBUG_RETURN(WSREP_TRX_ERROR); - } - - thd->wsrep_query_state= QUERY_EXEC; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - 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=DB_TYPE_WSREP; - 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 - wsrep_hton->slot= 0; - return 0; -} - - -struct st_mysql_storage_engine wsrep_storage_engine= -{ MYSQL_HANDLERTON_INTERFACE_VERSION }; - - -mysql_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 */ - NULL, /* config options */ - 0, /* flags */ -} -mysql_declare_plugin_end; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc deleted file mode 100644 index 62397c58a6e..00000000000 --- a/sql/wsrep_mysqld.cc +++ /dev/null @@ -1,1311 +0,0 @@ -/* Copyright 2008 Codership Oy - - 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 -#include -#include -#include "wsrep_priv.h" -#include -#include -#include "log_event.h" - -extern Format_description_log_event *wsrep_format_desc; -wsrep_t *wsrep = NULL; -my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface - -/* - * Begin configuration options and their default values - */ - -const char* wsrep_data_home_dir = NULL; - -#define WSREP_NODE_INCOMING_AUTO "AUTO" -const char* wsrep_node_incoming_address = WSREP_NODE_INCOMING_AUTO; -const char* wsrep_dbug_option = ""; - -long wsrep_slave_threads = 1; // # of slave action appliers wanted -my_bool wsrep_debug = 0; // enable debug level logging -my_bool wsrep_convert_LOCK_to_trx = 1; // convert locking sessions to trx -ulong wsrep_retry_autocommit = 5; // retry aborted autocommit trx -my_bool wsrep_auto_increment_control = 1; // control auto increment variables -my_bool wsrep_drupal_282555_workaround = 1; // retry autoinc insert after dupkey -my_bool wsrep_incremental_data_collection = 0; // incremental data collection -long long wsrep_max_ws_size = 1073741824LL; //max ws (RBR buffer) size -long wsrep_max_ws_rows = 65536; // max number of rows in ws -int wsrep_to_isolation = 0; // # of active TO isolation threads -my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key -long wsrep_max_protocol_version = 2; // maximum protocol version to use -ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; -my_bool wsrep_recovery = 0; // recovery -my_bool wsrep_replicate_myisam = 0; // enable myisam replication -my_bool wsrep_log_conflicts = 0; // -ulong wsrep_mysql_replication_bundle = 0; - -/* - * End configuration options - */ - -static const wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; -const wsrep_uuid_t* wsrep_cluster_uuid() -{ - return &cluster_uuid; -} -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 - */ -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; -const char* wsrep_provider_name = provider_name; -const char* wsrep_provider_version = provider_version; -const char* wsrep_provider_vendor = provider_vendor; -/* End wsrep status variables */ - - -wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; -wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; -wsp::node_status local_status; -long wsrep_protocol_version = 2; - -// 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; - -// action execute callback -extern wsrep_status_t wsrep_apply_cb(void *ctx, - const void* buf, size_t buf_len, - wsrep_seqno_t global_seqno); - -extern wsrep_status_t wsrep_commit_cb (void *ctx, - wsrep_seqno_t global_seqno, - bool commit); - -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: - sql_print_error("WSREP: %s", msg); - break; - case WSREP_LOG_DEBUG: - if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); - default: - break; - } -} - -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); -} - -static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) -{ - XID* xid= reinterpret_cast(arg); - handlerton* hton= plugin_data(plugin, handlerton *); - if (hton->db_type == DB_TYPE_INNODB) - { - const wsrep_uuid_t* uuid(wsrep_xid_uuid(xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); - WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(xid)); - hton->wsrep_set_checkpoint(hton, xid); - } - return FALSE; -} - -void wsrep_set_SE_checkpoint(XID* xid) -{ - plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); -} - -static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) -{ - XID* xid= reinterpret_cast(arg); - handlerton* hton= plugin_data(plugin, handlerton *); - if (hton->db_type == DB_TYPE_INNODB) - { - hton->wsrep_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_DEBUG("Read WSREPXid from InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(xid)); - - } - return FALSE; -} - -void wsrep_get_SE_checkpoint(XID* xid) -{ - plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); -} - -static void 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, - ssize_t* sst_req_len) -{ - wsrep_member_status_t new_status= local_status.get(); - - if (memcmp(&cluster_uuid, &view->uuid, sizeof(wsrep_uuid_t))) - { - memcpy((wsrep_uuid_t*)&cluster_uuid, &view->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->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) { - wsrep_ready_set(FALSE); - new_status= WSREP_MEMBER_UNDEFINED; - /* Always record local_uuid and local_seqno in non-prim since this - * may lead to re-initializing provider and start position is - * determined according to these variables */ - // 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; - } - - switch (view->proto_ver) - { - case 0: - case 1: - case 2: - // version change - if (view->proto_ver != wsrep_protocol_version) - { - my_bool wsrep_ready_saved= wsrep_ready; - 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 */ - WSREP_DEBUG("[debug]: closing client connections for PRIM"); - wsrep_close_client_connections(TRUE); - - *sst_req_len= wsrep_sst_prepare (sst_req); - - if (*sst_req_len < 0) - { - int err = *sst_req_len; - WSREP_ERROR("SST preparation failed: %d (%s)", -err, strerror(-err)); - new_status= WSREP_MEMBER_UNDEFINED; - } - else - { - new_status= WSREP_MEMBER_JOINER; - } - } - 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) - { - if (wsrep_before_SE()) - { - wsrep_SE_init_grab(); - // Signal mysqld init thread to continue - wsrep_sst_complete (&cluster_uuid, view->seqno, false); - // and wait for SE initialization - wsrep_SE_init_wait(); - } - else - { - local_uuid= cluster_uuid; - local_seqno= view->seqno; - } - /* Init storage engine XIDs from first view */ - XID xid; - wsrep_xid_init(&xid, &local_uuid, local_seqno); - wsrep_set_SE_checkpoint(&xid); - new_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->seqno, - &local_uuid, -1); - unireg_abort(1); - } - } - - if (wsrep_auto_increment_control) - { - global_system_variables.auto_increment_offset= view->my_idx + 1; - global_system_variables.auto_increment_increment= view->memb_num; - } - -out: - wsrep_startup= FALSE; - local_status.set(new_status, view); -} - -void wsrep_ready_set (my_bool x) -{ - WSREP_DEBUG("Setting wsrep_ready to %d", x); - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - if (wsrep_ready != x) - { - wsrep_ready= x; - mysql_cond_signal (&COND_wsrep_ready); - } - mysql_mutex_unlock (&LOCK_wsrep_ready); -} - -// Wait until wsrep has reached ready state -void wsrep_ready_wait () -{ - 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); -} - -static void wsrep_synced_cb(void* app_ctx) -{ - WSREP_INFO("Synchronized with group, ready for connections"); - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - if (!wsrep_ready) - { - wsrep_ready= TRUE; - mysql_cond_signal (&COND_wsrep_ready); - } - local_status.set(WSREP_MEMBER_SYNCED); - mysql_mutex_unlock (&LOCK_wsrep_ready); -} - -static void wsrep_init_position() -{ - /* read XIDs from storage engines */ - XID xid; - memset(&xid, 0, sizeof(xid)); - xid.formatID= -1; - wsrep_get_SE_checkpoint(&xid); - - if (xid.formatID == -1) - { - WSREP_INFO("Read nil XID from storage engines, skipping position init"); - return; - } - else if (!wsrep_is_wsrep_xid(&xid)) - { - WSREP_WARN("Read non-wsrep XID from storage engines, skipping position init"); - return; - } - - const wsrep_uuid_t* uuid= wsrep_xid_uuid(&xid); - const wsrep_seqno_t seqno= wsrep_xid_seqno(&xid); - - 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"); - } -} - - -int wsrep_init() -{ - int rcode= -1; - - wsrep_ready_set(FALSE); - assert(wsrep_provider); - wsrep_format_desc= new Format_description_log_event(4); - 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 - (void) wsrep_init(); - return rcode; - } - 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); - } - } - - if (strlen(wsrep_provider)== 0 || - !strcmp(wsrep_provider, WSREP_NONE)) - { - // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); - global_system_variables.wsrep_on = 0; - return 0; - } - 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); - } - - if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) - wsrep_data_home_dir = mysql_real_data_home; - - char node_addr[512]= { 0, }; - if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) - { - size_t const node_addr_max= sizeof(node_addr); - size_t const ret= guess_ip(node_addr, node_addr_max); - if (!(ret > 0 && ret < node_addr_max)) - { - WSREP_WARN("Failed to guess base node address. Set it explicitly via " - "wsrep_node_address."); - node_addr[0]= '\0'; - } - } - else - { - strncpy(node_addr, wsrep_node_address, sizeof(node_addr) - 1); - } - - static char inc_addr[512]= { 0, }; - - if ((!wsrep_node_incoming_address || - !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) - { - size_t const node_addr_len= strlen(node_addr); - if (node_addr_len > 0) - { - const char* const colon= strrchr(node_addr, ':'); - if (strchr(node_addr, ':') == colon) // 1 or 0 ':' - { - size_t const inc_addr_max= sizeof (inc_addr); - size_t const ip_len= colon ? colon - node_addr : node_addr_len; - if (ip_len + 7 /* :55555\0 */ < inc_addr_max) - { - memcpy (inc_addr, node_addr, ip_len); - snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",mysqld_port); - } - else - { - WSREP_WARN("Guessing address for incoming client connections: " - "address too long."); - inc_addr[0]= '\0'; - } - } - else - { - WSREP_WARN("Guessing address for incoming client connections: " - "too many colons :) ."); - inc_addr[0]= '\0'; - } - } - - // this is to display detected address on SHOW VARIABLES... - wsrep_node_incoming_address = inc_addr; - - if (!strlen(wsrep_node_incoming_address)) - { - WSREP_WARN("Guessing address for incoming client connections failed. " - "Try setting wsrep_node_incoming_address explicitly."); - } - } - - struct wsrep_init_args wsrep_args; - - 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 = wsrep_node_incoming_address; - wsrep_args.options = (wsrep_provider_options) ? - wsrep_provider_options : ""; - wsrep_args.proto_ver = wsrep_max_protocol_version; - - wsrep_args.state_uuid = &local_uuid; - wsrep_args.state_seqno = local_seqno; - - 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.sst_donate_cb = wsrep_sst_donate_cb; - wsrep_args.synced_cb = wsrep_synced_cb; - - rcode = wsrep->init(wsrep, &wsrep_args); - - if (rcode) - { - DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); - WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); - free(wsrep); - wsrep = NULL; - } - - return rcode; -} - -extern "C" int wsrep_on(void *); - -void wsrep_init_startup (bool first) -{ - if (wsrep_init()) unireg_abort(1); - - wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd, - wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); - - /* Skip replication start if no cluster address */ - if (!wsrep_cluster_address || strlen(wsrep_cluster_address) == 0) return; - - if (first) wsrep_sst_grab(); // do it so we can wait for SST below - - 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 -} - - -void wsrep_deinit() -{ - wsrep_unload(wsrep); - wsrep= 0; - provider_name[0]= '\0'; - provider_version[0]= '\0'; - provider_vendor[0]= '\0'; - - delete wsrep_format_desc; - wsrep_format_desc= NULL; -} - -void wsrep_recover() -{ - if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) && - local_seqno == -2) - { - char uuid_str[40]; - wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str)); - WSREP_INFO("Position %s:%lld given at startup, skipping position recovery", - uuid_str, (long long)local_seqno); - return; - } - XID xid; - memset(&xid, 0, sizeof(xid)); - xid.formatID= -1; - wsrep_get_SE_checkpoint(&xid); - char uuid_str[40]; - wsrep_uuid_print(wsrep_xid_uuid(&xid), uuid_str, sizeof(uuid_str)); - WSREP_INFO("Recovered position: %s:%lld", uuid_str, - (long long)wsrep_xid_seqno(&xid)); -} - - -void wsrep_stop_replication(THD *thd) -{ - WSREP_INFO("Stop replication"); - if (!wsrep) - { - WSREP_INFO("Provider was not loaded, in stop replication"); - return; - } - - /* disconnect from group first to get wsrep_ready == FALSE */ - WSREP_DEBUG("Provider disconnect"); - wsrep->disconnect(wsrep); - - wsrep_connected= FALSE; - - wsrep_close_client_connections(TRUE); - - /* wait until appliers have stopped */ - wsrep_wait_appliers_close(thd); - - return; -} - - -bool wsrep_start_replication() -{ - wsrep_status_t rcode; - - /* - if provider is trivial, don't even try to connect, - but resume local node operation - */ - if (strlen(wsrep_provider)== 0 || - !strcmp(wsrep_provider, WSREP_NONE)) - { - // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); - return true; - } - - if (!wsrep_cluster_address || strlen(wsrep_cluster_address)== 0) - { - // if provider is non-trivial, but no address is specified, wait for address - wsrep_ready_set(FALSE); - return true; - } - - WSREP_INFO("Start replication"); - - if ((rcode = wsrep->connect(wsrep, - wsrep_cluster_name, - wsrep_cluster_address, - wsrep_sst_donor))) - { - if (-ESOCKTNOSUPPORT == rcode) - { - DBUG_PRINT("wsrep",("unrecognized cluster address: '%s', rcode: %d", - wsrep_cluster_address, rcode)); - WSREP_ERROR("unrecognized cluster address: '%s', rcode: %d", - wsrep_cluster_address, rcode); - } - else - { - DBUG_PRINT("wsrep",("wsrep->connect() failed: %d", rcode)); - WSREP_ERROR("wsrep::connect() failed: %d", rcode); - } - - return false; - } - else - { - wsrep_connected= TRUE; - - uint64_t caps = wsrep->capabilities (wsrep); - - wsrep_incremental_data_collection = - (caps & WSREP_CAP_WRITE_SET_INCREMENTS); - - char* opts= wsrep->options_get(wsrep); - if (opts) - { - wsrep_provider_options_init(opts); - free(opts); - } - else - { - WSREP_WARN("Failed to get wsrep options"); - } - } - - return true; -} - -bool -wsrep_causal_wait (THD* thd) -{ - if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on && - !thd->in_active_multi_stmt_transaction() && - thd->wsrep_conflict_state != REPLAYING) - { - // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 - // TODO: modify to check if thd has locked any rows. - wsrep_seqno_t seqno; - wsrep_status_t ret= wsrep->causal_read (wsrep, &seqno); - - if (unlikely(WSREP_OK != ret)) - { - 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 - - switch (ret) - { - case WSREP_NOT_IMPLEMENTED: - msg= "consistent reads by wsrep backend. " - "Please unset wsrep_causal_reads variable."; - err= ER_NOT_SUPPORTED_YET; - break; - default: - msg= "Causal wait failed."; - err= ER_LOCK_WAIT_TIMEOUT; // NOTE: the above msg won't be displayed - // with ER_LOCK_WAIT_TIMEOUT - } - - my_error(err, MYF(0), msg); - - return true; - } - } - - return false; -} - -/* - * Helpers to deal with TOI key arrays - */ -typedef struct wsrep_key_arr -{ - wsrep_key_t* keys; - size_t keys_len; -} wsrep_key_arr_t; - - -static void wsrep_keys_free(wsrep_key_arr_t* key_arr) -{ - for (size_t i= 0; i < key_arr->keys_len; ++i) - { - my_free((wsrep_key_part_t*)key_arr->keys[i].key_parts); - } - my_free(key_arr->keys); - key_arr->keys= 0; - key_arr->keys_len= 0; -} - - -/*! - * @param db Database string - * @param table Table string - * @param key Array of wsrep_key_t - * @param key_len In: number of elements in key array, Out: number of - * elements populated - * - * @return true if preparation was successful, otherwise false. - */ - -static bool wsrep_prepare_key_for_isolation(const char* db, - const char* table, - wsrep_key_part_t* key, - size_t* key_len) -{ - if (*key_len < 2) return false; - - switch (wsrep_protocol_version) - { - case 0: - *key_len= 0; - break; - case 1: - case 2: - { - *key_len= 0; - if (db) - { - // sql_print_information("%s.%s", db, table); - if (db) - { - key[*key_len].buf= db; - key[*key_len].buf_len= strlen(db); - ++(*key_len); - if (table) - { - key[*key_len].buf= table; - key[*key_len].buf_len= strlen(table); - ++(*key_len); - } - } - } - break; - } - default: - return false; - } - - return true; -} - -/* Prepare key list from db/table and table_list */ -static bool wsrep_prepare_keys_for_isolation(THD* thd, - const char* db, - const char* table, - const TABLE_LIST* table_list, - wsrep_key_arr_t* ka) -{ - ka->keys= 0; - ka->keys_len= 0; - - extern TABLE* find_temporary_table(THD*, const TABLE_LIST*); - - if (db || table) - { - TABLE_LIST tmp_table; - bzero((char*) &tmp_table,sizeof(tmp_table)); - tmp_table.table_name= (char*)db; - tmp_table.db= (char*)table; - if (!table || !find_temporary_table(thd, &tmp_table)) - { - if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0)))) - { - sql_print_error("Can't allocate memory for key_array"); - goto err; - } - ka->keys_len= 1; - if (!(ka->keys[0].key_parts= (wsrep_key_part_t*) - my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) - { - sql_print_error("Can't allocate memory for key_parts"); - goto err; - } - ka->keys[0].key_parts_len= 2; - if (!wsrep_prepare_key_for_isolation( - db, table, - (wsrep_key_part_t*)ka->keys[0].key_parts, - &ka->keys[0].key_parts_len)) - { - sql_print_error("Preparing keys for isolation failed"); - goto err; - } - } - } - - for (const TABLE_LIST* table= table_list; table; table= table->next_global) - { - if (!find_temporary_table(thd, table)) - { - wsrep_key_t* tmp; - tmp= (wsrep_key_t*)my_realloc( - ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); - if (!tmp) - { - sql_print_error("Can't allocate memory for key_array"); - goto err; - } - ka->keys= tmp; - if (!(ka->keys[ka->keys_len].key_parts= (wsrep_key_part_t*) - my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) - { - sql_print_error("Can't allocate memory for key_parts"); - goto err; - } - ka->keys[ka->keys_len].key_parts_len= 2; - ++ka->keys_len; - if (!wsrep_prepare_key_for_isolation( - table->db, table->table_name, - (wsrep_key_part_t*)ka->keys[ka->keys_len - 1].key_parts, - &ka->keys[ka->keys_len - 1].key_parts_len)) - { - sql_print_error("Preparing keys for isolation failed"); - goto err; - } - } - } - return true; -err: - wsrep_keys_free(ka); - return false; -} - - - -bool wsrep_prepare_key_for_innodb(const uchar* cache_key, - size_t cache_key_len, - const uchar* row_id, - size_t row_id_len, - wsrep_key_part_t* key, - size_t* key_len) -{ - if (*key_len < 3) return false; - - *key_len= 0; - switch (wsrep_protocol_version) - { - case 0: - { - key[*key_len].buf = cache_key; - key[*key_len].buf_len = cache_key_len; - ++(*key_len); - break; - } - case 1: - case 2: - { - key[*key_len].buf = cache_key; - key[*key_len].buf_len = strlen( (char*)cache_key ); - ++(*key_len); - key[*key_len].buf = cache_key + strlen( (char*)cache_key ) + 1; - key[*key_len].buf_len = strlen( (char*)(key[*key_len].buf) ); - ++(*key_len); - break; - } - default: - return false; - } - - key[*key_len].buf = row_id; - key[*key_len].buf_len = row_id_len; - ++(*key_len); - - return true; -} - -/* - * Construct Query_log_Event from thd query and serialize it - * into buffer. - * - * Return 0 in case of success, 1 in case of error. - */ -int wsrep_to_buf_helper( - THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len) -{ - IO_CACHE tmp_io_cache; - if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, - 65536, MYF(MY_WME))) - return 1; - Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); - int ret(0); - if (ev.write(&tmp_io_cache)) ret= 1; - if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; - close_cached_file(&tmp_io_cache); - return ret; -} - -#include "sql_show.h" -static int -create_view_query(THD *thd, uchar** buf, uint* buf_len) -{ - LEX *lex= thd->lex; - SELECT_LEX *select_lex= &lex->select_lex; - TABLE_LIST *first_table= select_lex->table_list.first; - TABLE_LIST *views = first_table; - - String buff; - const LEX_STRING command[3]= - {{ C_STRING_WITH_LEN("CREATE ") }, - { C_STRING_WITH_LEN("ALTER ") }, - { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; - - buff.append(command[thd->lex->create_view_mode].str, - command[thd->lex->create_view_mode].length); - - if (!lex->definer) - { - /* - DEFINER-clause is missing; we have to create default definer in - persistent arena to be PS/SP friendly. - If this is an ALTER VIEW then the current user should be set as - the definer. - */ - - if (!(lex->definer= create_default_definer(thd))) - { - WSREP_WARN("view default definer issue"); - } - } - - views->algorithm = lex->create_view_algorithm; - views->definer.user = lex->definer->user; - views->definer.host = lex->definer->host; - 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 ")); - /* Test if user supplied a db (ie: we did not use thd->db) */ - if (views->db && views->db[0] && - (thd->db == NULL || strcmp(views->db, thd->db))) - { - append_identifier(thd, &buff, views->db, - views->db_length); - buff.append('.'); - } - append_identifier(thd, &buff, views->table_name, - views->table_name_length); - if (lex->view_list.elements) - { - List_iterator_fast names(lex->view_list); - LEX_STRING *name; - int i; - - for (i= 0; (name= names++); i++) - { - buff.append(i ? ", " : "("); - append_identifier(thd, &buff, name->str, name->length); - } - 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); -} - -static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, - const TABLE_LIST* table_list) -{ - wsrep_status_t ret(WSREP_WARNING); - uchar* buf(0); - uint buf_len(0); - int buf_err; - - WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, thd->query() ); - switch (thd->lex->sql_command) - { - case SQLCOM_CREATE_VIEW: - buf_err= create_view_query(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_PROCEDURE: - case SQLCOM_CREATE_SPFUNCTION: - buf_err= wsrep_create_sp(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_TRIGGER: - buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_EVENT: - buf_err= wsrep_create_event_query(thd, &buf, &buf_len); - break; - default: - buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, - &buf_len); - break; - } - - wsrep_key_arr_t key_arr= {0, 0}; - if (!buf_err && - wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&& - WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, - key_arr.keys, key_arr.keys_len, - buf, buf_len, - &thd->wsrep_trx_seqno))) - { - thd->wsrep_exec_mode= TOTAL_ORDER; - wsrep_to_isolation++; - if (buf) my_free(buf); - wsrep_keys_free(&key_arr); - WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode); - } - else { - /* jump to error handler in mysql_execute_command() */ - WSREP_WARN("TO isolation failed for: %d, sql: %s. Check wsrep " - "connection state and retry the query.", - ret, (thd->query()) ? thd->query() : "void"); - my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " - "your wsrep connection state and retry the query."); - if (buf) my_free(buf); - wsrep_keys_free(&key_arr); - return -1; - } - return 0; -} - -static void wsrep_TOI_end(THD *thd) { - wsrep_status_t ret; - wsrep_to_isolation--; - WSREP_DEBUG("TO END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void") - if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { - WSREP_DEBUG("TO END: %lld", (long long)thd->wsrep_trx_seqno); - } - else { - WSREP_WARN("TO isolation end failed for: %d, sql: %s", - ret, (thd->query()) ? thd->query() : "void"); - } -} - -static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) -{ - wsrep_status_t ret(WSREP_WARNING); - WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, thd->query() ); - - ret = wsrep->desync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("RSU desync failed %d for %s", ret, thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(ret); - } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying++; - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - if (wsrep_wait_committing_connections_close(5000)) - { - /* no can do, bail out from DDL */ - WSREP_WARN("RSU failed due to pending transactions, %s", thd->query()); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resync failed %d for %s", ret, thd->query()); - } - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(1); - } - - wsrep_seqno_t seqno = wsrep->pause(wsrep); - if (seqno == WSREP_SEQNO_UNDEFINED) - { - WSREP_WARN("pause failed %lld for %s", (long long)seqno, thd->query()); - return(1); - } - 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)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, thd->query() ); - - - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - ret = wsrep->resume(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resume failed %d for %s", ret, thd->query()); - } - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resync failed %d for %s", ret, thd->query()); - return; - } - thd->variables.wsrep_on = 1; - return; -} - -int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, - const TABLE_LIST* table_list) -{ - int ret= 0; - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) - { - WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", - thd->thread_id, thd->query()); - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - return WSREP_TRX_FAIL; - } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - if (wsrep_debug && thd->mdl_context.has_locks()) - { - WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", - thd->query(), thd->thread_id); - } - if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) - { - switch (wsrep_OSU_method_options) { - case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_, - table_list); break; - case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; - } - if (!ret) - { - thd->wsrep_exec_mode= TOTAL_ORDER; - } - } - return ret; -} - -void wsrep_to_isolation_end(THD *thd) { - if (thd->wsrep_exec_mode==TOTAL_ORDER) - { - switch(wsrep_OSU_method_options) - { - case WSREP_OSU_TOI: return wsrep_TOI_end(thd); - case WSREP_OSU_RSU: return wsrep_RSU_end(thd); - } - } -} - -#define WSREP_MDL_LOG(severity, msg, req, gra) \ - WSREP_##severity( \ - "%s\n" \ - "request: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ - "granted: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ - msg, \ - req->thread_id, (long long)req->wsrep_trx_seqno, \ - req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \ - req->command, req->lex->sql_command, req->query(), \ - gra->thread_id, (long long)gra->wsrep_trx_seqno, \ - gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ - gra->command, gra->lex->sql_command, gra->query()); - -bool -wsrep_grant_mdl_exception(MDL_context *requestor_ctx, - MDL_ticket *ticket -) { - if (!WSREP_ON) return FALSE; - - THD *request_thd = requestor_ctx->get_thd(); - THD *granted_thd = ticket->get_ctx()->get_thd(); - bool ret = FALSE; - - mysql_mutex_lock(&request_thd->LOCK_wsrep_thd); - if (request_thd->wsrep_exec_mode == TOTAL_ORDER || - request_thd->wsrep_exec_mode == REPL_RECV) - { - mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); - WSREP_MDL_LOG(DEBUG, "MDL conflict ", request_thd, granted_thd); - ticket->wsrep_report(wsrep_debug); - - mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); - if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || - granted_thd->wsrep_exec_mode == REPL_RECV) - { - WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); - ticket->wsrep_report(true); - mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - ret = TRUE; - } - else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) - { - WSREP_DEBUG("mdl granted over FLUSH BF"); - ticket->wsrep_report(wsrep_debug); - mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - ret = TRUE; - } - else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) - { - WSREP_DEBUG("DROP caused BF abort"); - ticket->wsrep_report(wsrep_debug); - mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - ret = FALSE; - } - else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) - { - WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); - ticket->wsrep_report(wsrep_debug); - mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - ret = FALSE; - } - else - { - WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); - ticket->wsrep_report(wsrep_debug); - mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); - wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); - ret = FALSE; - } - } - else - { - mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); - } - return ret; -} diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h deleted file mode 100644 index 6b9640cea70..00000000000 --- a/sql/wsrep_mysqld.h +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright 2008-2012 Codership Oy - - 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_MYSQLD_H -#define WSREP_MYSQLD_H - -#include "mysqld.h" -typedef struct st_mysql_show_var SHOW_VAR; -#include -#include "../wsrep/wsrep_api.h" - -class set_var; -class THD; - -#ifdef WITH_WSREP -#include "../wsrep/wsrep_api.h" -//#include "wsrep_mysqld.h" - enum wsrep_exec_mode { - LOCAL_STATE, - REPL_RECV, - TOTAL_ORDER, - LOCAL_COMMIT, - }; - enum wsrep_query_state { - QUERY_IDLE, - QUERY_EXEC, - QUERY_COMMITTING, - QUERY_EXITING, - QUERY_ROLLINGBACK, - }; - enum wsrep_conflict_state { - NO_CONFLICT, - MUST_ABORT, - ABORTING, - ABORTED, - MUST_REPLAY, - REPLAYING, - RETRY_AUTOCOMMIT, - CERT_FAILURE, - }; - enum wsrep_consistency_check_mode { - NO_CONSISTENCY_CHECK, - CONSISTENCY_CHECK_DECLARED, - CONSISTENCY_CHECK_RUNNING, - }; -#endif - -// Global wsrep parameters -extern wsrep_t* wsrep; - -// MySQL wsrep options -extern const char* wsrep_provider; -extern const char* wsrep_provider_options; -extern const char* wsrep_cluster_name; -extern const char* wsrep_cluster_address; -extern const char* wsrep_node_name; -extern const char* wsrep_node_address; -extern const char* wsrep_node_incoming_address; -extern const char* wsrep_data_home_dir; -extern const char* wsrep_dbug_option; -extern long wsrep_slave_threads; -extern 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_sst_method; -extern const char* wsrep_sst_receive_address; -extern char* wsrep_sst_auth; -extern const char* wsrep_sst_donor; -extern my_bool wsrep_sst_donor_rejects_queries; -extern const char* wsrep_start_position; -extern long long wsrep_max_ws_size; -extern long wsrep_max_ws_rows; -extern const char* wsrep_notify_cmd; -extern my_bool wsrep_certify_nonPK; -extern long wsrep_max_protocol_version; -extern long wsrep_protocol_version; -extern ulong wsrep_forced_binlog_format; -extern ulong wsrep_OSU_method_options; -extern my_bool wsrep_recovery; -extern my_bool wsrep_replicate_myisam; -extern my_bool wsrep_log_conflicts; -extern ulong wsrep_mysql_replication_bundle; - -enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; - -// MySQL status variables -extern my_bool wsrep_connected; -extern my_bool wsrep_ready; -extern const char* wsrep_cluster_state_uuid; -extern long long wsrep_cluster_conf_id; -extern const char* wsrep_cluster_status; -extern long wsrep_cluster_size; -extern long wsrep_local_index; -extern const char* wsrep_provider_name; -extern const char* wsrep_provider_version; -extern const char* wsrep_provider_vendor; -extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); -extern void wsrep_free_status(THD *thd); - -#define WSREP_SST_ADDRESS_AUTO "AUTO" -// MySQL variables funcs - -#define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) -#define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) -#define DEFAULT_ARGS (THD* thd, enum_var_type var_type) -#define INIT_ARGS (const char* opt) - -extern int wsrep_init_vars(); - -extern bool wsrep_on_update UPDATE_ARGS; -extern void wsrep_causal_reads_update UPDATE_ARGS; -extern bool wsrep_start_position_check CHECK_ARGS; -extern bool wsrep_start_position_update UPDATE_ARGS; -extern void wsrep_start_position_init INIT_ARGS; - -extern bool wsrep_provider_check CHECK_ARGS; -extern bool wsrep_provider_update UPDATE_ARGS; -extern void wsrep_provider_init INIT_ARGS; - -extern bool wsrep_provider_options_check CHECK_ARGS; -extern bool wsrep_provider_options_update UPDATE_ARGS; -extern void wsrep_provider_options_init INIT_ARGS; - -extern bool wsrep_cluster_address_check CHECK_ARGS; -extern bool wsrep_cluster_address_update UPDATE_ARGS; -extern void wsrep_cluster_address_init INIT_ARGS; - -extern bool wsrep_cluster_name_check CHECK_ARGS; -extern bool wsrep_cluster_name_update UPDATE_ARGS; - -extern bool wsrep_node_name_check CHECK_ARGS; -extern bool wsrep_node_name_update UPDATE_ARGS; - -extern bool wsrep_node_address_check CHECK_ARGS; -extern bool wsrep_node_address_update UPDATE_ARGS; -extern void wsrep_node_address_init INIT_ARGS; - -extern bool wsrep_sst_method_check CHECK_ARGS; -extern bool wsrep_sst_method_update UPDATE_ARGS; -extern void wsrep_sst_method_init INIT_ARGS; - -extern bool wsrep_sst_receive_address_check CHECK_ARGS; -extern bool wsrep_sst_receive_address_update UPDATE_ARGS; - -extern bool wsrep_sst_auth_check CHECK_ARGS; -extern bool wsrep_sst_auth_update UPDATE_ARGS; -extern void wsrep_sst_auth_init INIT_ARGS; - -extern bool wsrep_sst_donor_check CHECK_ARGS; -extern bool wsrep_sst_donor_update UPDATE_ARGS; - -extern bool wsrep_slave_threads_check CHECK_ARGS; -extern bool wsrep_slave_threads_update UPDATE_ARGS; - -extern bool wsrep_before_SE(); // initialize wsrep before storage - // engines (true) or after (false) -extern int wsrep_init(); -extern void wsrep_deinit(); -extern void wsrep_recover(); - - - -extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); -extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); -extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); -extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); -extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); -extern "C" const char * wsrep_thd_query_state_str(THD *thd); -extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(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_conflict_state( - THD *thd, enum wsrep_conflict_state state); - -extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); - -extern "C"void wsrep_thd_LOCK(THD *thd); -extern "C"void wsrep_thd_UNLOCK(THD *thd); -extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); -extern "C" time_t wsrep_thd_query_start(THD *thd); -extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); -extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); -extern "C" query_id_t wsrep_thd_query_id(THD *thd); -extern "C" char * wsrep_thd_query(THD *thd); -extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); -extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); - - - -/* wsrep initialization sequence at startup - * @param first wsrep_before_SE() value */ -extern void wsrep_init_startup(bool before); - -extern void wsrep_close_client_connections(my_bool wait_to_end); -extern int wsrep_wait_committing_connections_close(int wait_time); -extern void wsrep_close_applier(THD *thd); -extern void wsrep_wait_appliers_close(THD *thd); -extern void wsrep_close_applier_threads(int count); -extern void wsrep_create_appliers(long threads = wsrep_slave_threads); -extern void wsrep_create_rollbacker(); -extern void wsrep_kill_mysql(THD *thd); - -/* new defines */ -extern void wsrep_stop_replication(THD *thd); -extern bool wsrep_start_replication(); -extern bool wsrep_causal_wait(THD* thd); -extern int wsrep_check_opts (int argc, char* const* argv); -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(thd) \ - (WSREP_ON && (thd && thd->variables.wsrep_on)) - -#define WSREP_CLIENT(thd) \ - (WSREP(thd) && thd->wsrep_client_thread) - -#define WSREP_EMULATE_BINLOG(thd) \ - (WSREP(thd) && wsrep_emulate_bin_log) - -// MySQL logging functions don't seem to understand long long length modifer. -// This is a workaround. It also prefixes all messages with "WSREP" -#define WSREP_LOG(fun, ...) \ - { \ - char msg[1024] = {'\0'}; \ - snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ - fun("WSREP: %s", msg); \ - } - -#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, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ - wsrep_thd_query_state_str(thd), \ - wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \ - wsrep_thd_query(thd) \ - ); - -#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"); \ - } - -/*! Synchronizes applier thread start with init thread */ -extern void wsrep_sst_grab(); -/*! Init thread waits for SST completion */ -extern bool wsrep_sst_wait(); -/*! Signals wsrep that initialization is complete, writesets can be applied */ -extern void wsrep_sst_continue(); - -extern void wsrep_SE_init_grab(); /*! grab init critical section */ -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 */ - -extern void wsrep_ready_wait(); - -enum wsrep_trx_status { - WSREP_TRX_OK, - WSREP_TRX_ROLLBACK, - WSREP_TRX_ERROR, - }; - -extern enum wsrep_trx_status -wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); -class Ha_trx_info; -struct THD_TRANS; -void wsrep_register_hton(THD* thd, bool all); - -void wsrep_replication_process(THD *thd); -void wsrep_rollback_process(THD *thd); -void wsrep_brute_force_killer(THD *thd); -int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id); -extern "C" bool wsrep_consistency_check(void *thd_ptr); -extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); -extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, - my_bool signal); -extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); -void *wsrep_prepare_bf_thd(THD *thd); -void wsrep_return_from_bf_mode(void *shadow, THD *thd); - -/* this is visible for client build so that innodb plugin gets this */ -typedef struct wsrep_aborting_thd { - struct wsrep_aborting_thd *next; - THD *aborting_thd; -} *wsrep_aborting_thd_t; - -extern mysql_mutex_t LOCK_wsrep_ready; -extern mysql_cond_t COND_wsrep_ready; -extern mysql_mutex_t LOCK_wsrep_sst; -extern mysql_cond_t COND_wsrep_sst; -extern mysql_mutex_t LOCK_wsrep_sst_init; -extern mysql_cond_t COND_wsrep_sst_init; -extern mysql_mutex_t LOCK_wsrep_rollback; -extern mysql_cond_t COND_wsrep_rollback; -extern int wsrep_replaying; -extern mysql_mutex_t LOCK_wsrep_replaying; -extern mysql_cond_t COND_wsrep_replaying; -extern wsrep_aborting_thd_t wsrep_aborting_thd; -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_emulate_bin_log; -extern my_bool wsrep_auto_increment_control; -extern my_bool wsrep_drupal_282555_workaround; -extern long long wsrep_max_ws_size; -extern long wsrep_max_ws_rows; -extern int wsrep_to_isolation; -extern my_bool wsrep_certify_nonPK; -extern mysql_mutex_t LOCK_wsrep_slave_threads; - -extern PSI_mutex_key key_LOCK_wsrep_ready; -extern PSI_mutex_key key_COND_wsrep_ready; -extern PSI_mutex_key key_LOCK_wsrep_sst; -extern PSI_cond_key key_COND_wsrep_sst; -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; - -struct TABLE_LIST; -int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, - const TABLE_LIST* table_list); -void wsrep_to_isolation_end(THD *thd); - -void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); -void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow*); -int wsrep_to_buf_helper( - THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len); -int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len); -int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len); -int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len); - -const wsrep_uuid_t* wsrep_cluster_uuid(); -struct xid_t; -void wsrep_set_SE_checkpoint(xid_t*); - -void wsrep_xid_init(xid_t*, const wsrep_uuid_t*, wsrep_seqno_t); -const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*); -wsrep_seqno_t wsrep_xid_seqno(const xid_t*); -extern "C" int wsrep_is_wsrep_xid(const void* xid); - -#endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc deleted file mode 100644 index ff997d01183..00000000000 --- a/sql/wsrep_notify.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2010 Codership Oy - - 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 -#include "wsrep_priv.h" - -const char* wsrep_notify_cmd=""; - -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) -{ - if (!wsrep_notify_cmd || 0 == strlen(wsrep_notify_cmd)) - { - WSREP_INFO("wsrep_notify_cmd is not defined, skipping notification."); - return; - } - - 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; - - 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); - } - - if (0 != view) - { - char uuid_str[40]; - - wsrep_uuid_print (&view->uuid, uuid_str, sizeof(uuid_str)); - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --uuid %s", uuid_str); - - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --primary %s", view->view >= 0 ? "yes" : "no"); - - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --index %d", view->my_idx); - - 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); - } - } - - if (cmd_off == cmd_len) - { - WSREP_ERROR("Notification buffer too short (%ld). Aborting notification.", - cmd_len); - return; - } - - wsp::process p(cmd_ptr, "r"); - - p.wait(); - int err = p.error(); - - if (err) - { - WSREP_ERROR("Notification command failed: %d (%s): \"%s\"", - err, strerror(err), cmd_ptr); - } -} - diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h deleted file mode 100644 index 700639ebcb1..00000000000 --- a/sql/wsrep_priv.h +++ /dev/null @@ -1,233 +0,0 @@ -/* Copyright 2010 Codership Oy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//! @file declares symbols private to wsrep integration layer - -#ifndef WSREP_PRIV_H -#define WSREP_PRIV_H - -#include "wsrep_mysqld.h" -#include "../wsrep/wsrep_api.h" - -#include -#include -#include - -extern void wsrep_ready_set (my_bool x); - -extern ssize_t wsrep_sst_prepare (void** msg); -extern int wsrep_sst_donate_cb (void* app_ctx, - void* recv_ctx, - const void* msg, size_t msg_len, - const wsrep_uuid_t* current_uuid, - wsrep_seqno_t current_seqno, - const char* state, size_t state_len, - bool bypass); - -extern size_t guess_ip (char* buf, size_t buf_len); -extern size_t guess_address(char* buf, size_t buf_len); - -extern wsrep_uuid_t local_uuid; -extern wsrep_seqno_t local_seqno; - -/*! SST thread signals init thread about sst completion */ -extern void wsrep_sst_complete(const wsrep_uuid_t* uuid, wsrep_seqno_t, bool); - -extern void wsrep_notify_status (wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0); - -namespace wsp { -class node_status -{ -public: - node_status() : status(WSREP_MEMBER_UNDEFINED) {} - void set(wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0) - { - if (status != new_status || 0 != view) - { - wsrep_notify_status(new_status, view); - status = new_status; - } - } - wsrep_member_status_t get() const { return status; } -private: - wsrep_member_status_t status; -}; -} /* namespace wsp */ - -extern wsp::node_status local_status; - -namespace wsp { -/* A small class to run external programs. */ -class process -{ -private: - const char* const str_; - FILE* io_; - int err_; - pid_t pid_; - -public: -/*! @arg type is a pointer to a null-terminated string which must contain - either the letter 'r' for reading or the letter 'w' for writing. - */ - process (const char* cmd, const char* type); - ~process (); - - FILE* pipe () { return io_; } - int error() { return err_; } - int wait (); - const char* cmd() { return str_; } -}; -#ifdef REMOVED -class lock -{ - pthread_mutex_t* const mtx_; - -public: - - lock (pthread_mutex_t* mtx) : mtx_(mtx) - { - int err = pthread_mutex_lock (mtx_); - - if (err) - { - WSREP_ERROR("Mutex lock failed: %s", strerror(err)); - abort(); - } - } - - virtual ~lock () - { - int err = pthread_mutex_unlock (mtx_); - - if (err) - { - WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); - abort(); - } - } - - inline void wait (pthread_cond_t* cond) - { - pthread_cond_wait (cond, mtx_); - } - -private: - - lock (const lock&); - lock& operator=(const lock&); - -}; - -class monitor -{ - int mutable refcnt; - pthread_mutex_t mutable mtx; - pthread_cond_t mutable cond; - -public: - - monitor() : refcnt(0) - { - pthread_mutex_init (&mtx, NULL); - pthread_cond_init (&cond, NULL); - } - - ~monitor() - { - pthread_mutex_destroy (&mtx); - pthread_cond_destroy (&cond); - } - - void enter() const - { - lock l(&mtx); - - while (refcnt) - { - l.wait(&cond); - } - refcnt++; - } - - void leave() const - { - lock l(&mtx); - - refcnt--; - if (refcnt == 0) - { - pthread_cond_signal (&cond); - } - } - -private: - - monitor (const monitor&); - monitor& operator= (const monitor&); -}; - -class critical -{ - const monitor& mon; - -public: - - critical(const monitor& m) : mon(m) { mon.enter(); } - - ~critical() { mon.leave(); } - -private: - - critical (const critical&); - critical& operator= (const critical&); -}; -#endif - -class thd -{ - class thd_init - { - public: - thd_init() { my_thread_init(); } - ~thd_init() { my_thread_end(); } - } - init; - - thd (const thd&); - thd& operator= (const thd&); - -public: - - thd(my_bool wsrep_on); - ~thd(); - THD* const ptr; -}; - -class string -{ -public: - string() : string_(0) {} - void set(char* str) { if (string_) free (string_); string_ = str; } - ~string() { set (0); } -private: - char* string_; -}; - -} // namespace wsrep -#endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc deleted file mode 100644 index 597d0ea087d..00000000000 --- a/sql/wsrep_sst.cc +++ /dev/null @@ -1,1001 +0,0 @@ -/* Copyright 2008-2012 Codership Oy - - 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 -#include -#include -#include -#include -#include -#include "wsrep_priv.h" -#include -#include - -extern const char wsrep_defaults_file[]; - -#define WSREP_SST_OPT_ROLE "--role" -#define WSREP_SST_OPT_ADDR "--address" -#define WSREP_SST_OPT_AUTH "--auth" -#define WSREP_SST_OPT_DATA "--datadir" -#define WSREP_SST_OPT_CONF "--defaults-file" -#define WSREP_SST_OPT_PARENT "--parent" - -// mysqldump-specific options -#define WSREP_SST_OPT_USER "--user" -#define WSREP_SST_OPT_PSWD "--password" -#define WSREP_SST_OPT_HOST "--host" -#define WSREP_SST_OPT_PORT "--port" -#define WSREP_SST_OPT_LPORT "--local-port" - -// donor-specific -#define WSREP_SST_OPT_SOCKET "--socket" -#define WSREP_SST_OPT_GTID "--gtid" -#define WSREP_SST_OPT_BYPASS "--bypass" - -#define WSREP_SST_MYSQLDUMP "mysqldump" -#define WSREP_SST_SKIP "skip" -#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP -#define WSREP_SST_ADDRESS_AUTO "AUTO" -#define WSREP_SST_AUTH_MASK "********" - -const char* wsrep_sst_method = WSREP_SST_DEFAULT; -const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; -const char* wsrep_sst_donor = ""; - 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; - -bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* c_str = NULL; - - if ((res = var->value->val_str(&str)) && - (c_str = res->c_ptr()) && - strlen(c_str) > 0) - return 0; - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); - return 1; -} - -bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) -{ - return 0; -} - -static bool sst_receive_address_check (const char* str) -{ - if (!strncasecmp(str, "127.0.0.1", strlen("127.0.0.1")) || - !strncasecmp(str, "localhost", strlen("localhost"))) - { - return 1; - } - - return 0; -} - -bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) -{ - const char* c_str = var->value->str_value.c_ptr(); - - if (sst_receive_address_check (c_str)) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_receive_address", c_str ? c_str : "NULL"); - return 1; - } - - return 0; -} - -bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, - enum_var_type type) -{ - return 0; -} - -bool wsrep_sst_auth_check (sys_var *self, THD* thd, set_var* var) -{ - return 0; -} -static bool sst_auth_real_set (const char* value) -{ - const char* v = strdup (value); - - if (v) - { - if (sst_auth_real) free (const_cast(sst_auth_real)); - sst_auth_real = v; - - if (strlen(sst_auth_real)) - { - if (wsrep_sst_auth) - { - my_free ((void*)wsrep_sst_auth); - wsrep_sst_auth = my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); - //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, - // sizeof(wsrep_sst_auth) - 1); - } - else - wsrep_sst_auth = my_strdup (WSREP_SST_AUTH_MASK, MYF(0)); - } - return 0; - } - - return 1; -} - -bool wsrep_sst_auth_update (sys_var *self, THD* thd, enum_var_type type) -{ - return sst_auth_real_set (wsrep_sst_auth); -} - -void wsrep_sst_auth_init (const char* value) -{ - if (wsrep_sst_auth == value) wsrep_sst_auth = NULL; - if (value) sst_auth_real_set (value); -} - -bool wsrep_sst_donor_check (sys_var *self, THD* thd, set_var* var) -{ - return 0; -} - -bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) -{ - return 0; -} - -static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; - -bool wsrep_before_SE() -{ - return (wsrep_provider != NULL - && strcmp (wsrep_provider, WSREP_NONE) - && strcmp (wsrep_sst_method, WSREP_SST_SKIP) - && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); -} - -static bool sst_complete = false; -static bool sst_needed = false; - -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 () -{ - if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); - while (!sst_complete) - { - WSREP_INFO("Waiting for SST to complete."); - mysql_cond_wait (&COND_wsrep_sst, &LOCK_wsrep_sst); - } - - 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) -{ - 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 - { - WSREP_WARN("Nobody is waiting for SST."); - } - mysql_mutex_unlock (&LOCK_wsrep_sst); -} - -// Let applier threads to continue -void wsrep_sst_continue () -{ - if (sst_needed) - { - WSREP_INFO("Signalling provider to continue."); - wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); - } -} - -struct sst_thread_arg -{ - const char* cmd; - int err; - char* ret_str; - mysql_mutex_t lock; - mysql_cond_t cond; - - sst_thread_arg (const char* c) : cmd(c), err(-1), ret_str(0) - { - mysql_mutex_init(key_LOCK_wsrep_sst_thread, &lock, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL); - } - - ~sst_thread_arg() - { - mysql_cond_destroy (&cond); - mysql_mutex_unlock (&lock); - mysql_mutex_destroy (&lock); - } -}; - -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); - if (offt > 0 && strlen(str) > (unsigned int)offt && ':' == str[offt]) - { - *seqno = strtoll (str + offt + 1, NULL, 10); - if (*seqno != LLONG_MAX || errno != ERANGE) - { - return 0; - } - } - - WSREP_ERROR("Failed to parse uuid:seqno pair: '%s'", str); - return EINVAL; -} - -// get rid of trailing \n -static char* my_fgets (char* buf, size_t buf_len, FILE* stream) -{ - char* ret= fgets (buf, buf_len, stream); - - if (ret) - { - size_t len = strlen(ret); - if (len > 0 && ret[len - 1] == '\n') ret[len - 1] = '\0'; - } - - return ret; -} - -static void* sst_joiner_thread (void* a) -{ - sst_thread_arg* arg= (sst_thread_arg*) a; - int err= 1; - - { - 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); - - wsp::process proc (arg->cmd, "r"); - - if (proc.pipe() && !proc.error()) - { - const char* tmp= my_fgets (out, out_len, proc.pipe()); - - if (!tmp || strlen(tmp) < (magic_len + 2) || - strncasecmp (tmp, magic, magic_len)) - { - WSREP_ERROR("Failed to read '%s ' from: %s\n\tRead: '%s'", - magic, arg->cmd, tmp); - proc.wait(); - if (proc.error()) err = proc.error(); - } - else - { - err = 0; - } - } - else - { - 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 - mysql_mutex_lock (&arg->lock); - if (!err) - { - arg->ret_str = strdup (out + magic_len + 1); - if (!arg->ret_str) err = ENOMEM; - } - arg->err = -err; - mysql_cond_signal (&arg->cond); - mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. - - if (err) return NULL; /* lp:808417 - return immediately, don't signal - * initializer thread to ensure single thread of - * shutdown. */ - - 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()); - - proc.wait(); - err= EINVAL; - - if (!tmp) - { - WSREP_ERROR("Failed to read uuid:seqno from joiner script."); - if (proc.error()) err = proc.error(); - } - else - { - err= sst_scan_uuid_seqno (out, &ret_uuid, &ret_seqno); - } - - if (err) - { - ret_uuid= WSREP_UUID_UNDEFINED; - ret_seqno= -err; - } - - // Tell initializer thread that SST is complete - wsrep_sst_complete (&ret_uuid, ret_seqno, true); - } - - return NULL; -} - -static ssize_t sst_prepare_other (const char* method, - const char* addr_in, - const char** addr_out) -{ - ssize_t cmd_len= 1024; - char cmd_str[cmd_len]; - const char* sst_dir= mysql_real_data_home; - - int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s " - WSREP_SST_OPT_ROLE" 'joiner' " - WSREP_SST_OPT_ADDR" '%s' " - WSREP_SST_OPT_AUTH" '%s' " - WSREP_SST_OPT_DATA" '%s' " - WSREP_SST_OPT_CONF" '%s' " - WSREP_SST_OPT_PARENT" '%d'", - method, addr_in, (sst_auth_real) ? sst_auth_real : "", - sst_dir, wsrep_defaults_file, (int)getpid()); - - if (ret < 0 || ret >= cmd_len) - { - WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); - return (ret < 0 ? ret : -EMSGSIZE); - } - - pthread_t tmp; - sst_thread_arg arg(cmd_str); - mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg); - if (ret) - { - WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)", - ret, strerror(ret)); - return ret; - } - mysql_cond_wait (&arg.cond, &arg.lock); - - *addr_out= arg.ret_str; - - if (!arg.err) - ret = strlen(*addr_out); - else - { - assert (arg.err < 0); - ret = arg.err; - } - - pthread_detach (tmp); - - return ret; -} - -//extern ulong my_bind_addr; -extern uint mysqld_port; - -/*! Just tells donor where to send mysqldump */ -static ssize_t sst_prepare_mysqldump (const char* addr_in, - const char** addr_out) -{ - ssize_t ret = strlen (addr_in); - - if (!strrchr(addr_in, ':')) - { - ssize_t s = ret + 7; - char* tmp = (char*) malloc (s); - - if (tmp) - { - ret= snprintf (tmp, s, "%s:%u", addr_in, mysqld_port); - - if (ret > 0 && ret < s) - { - *addr_out= tmp; - return ret; - } - if (ret > 0) /* buffer too short */ ret = -EMSGSIZE; - free (tmp); - } - else { - ret= -ENOMEM; - } - - WSREP_ERROR ("Could not prepare state transfer request: " - "adding default port failed: %zd.", ret); - } - else { - *addr_out= addr_in; - } - - return ret; -} - -static bool SE_initialized = false; - -ssize_t wsrep_sst_prepare (void** msg) -{ - const ssize_t ip_max= 256; - char ip_buf[ip_max]; - const char* addr_in= NULL; - const char* addr_out= NULL; - - 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; - } - - // Figure out SST address. Common for all SST methods - if (wsrep_sst_receive_address && - strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) - { - addr_in= wsrep_sst_receive_address; - } - else if (wsrep_node_address && strlen(wsrep_node_address)) - { - const char* const colon= strchr (wsrep_node_address, ':'); - if (colon) - { - ptrdiff_t const len= colon - wsrep_node_address; - strncpy (ip_buf, wsrep_node_address, len); - ip_buf[len]= '\0'; - addr_in= ip_buf; - } - else - { - addr_in= wsrep_node_address; - } - } - else - { - ssize_t ret= guess_ip (ip_buf, ip_max); - - if (ret && ret < ip_max) - { - addr_in= ip_buf; - } - else - { - WSREP_ERROR("Could not prepare state transfer request: " - "failed to guess address to accept state transfer at. " - "wsrep_sst_receive_address must be set manually."); - unireg_abort(1); - } - } - - ssize_t addr_len= -ENOSYS; - if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP)) - { - addr_len= sst_prepare_mysqldump (addr_in, &addr_out); - if (addr_len < 0) unireg_abort(1); - } - else - { - /*! A heuristic workaround until we learn how to stop and start engines */ - if (SE_initialized) - { - // we already did SST at initializaiton, now engines are running - // sql_print_information() is here because the message is too long - // for WSREP_INFO. - sql_print_information ("WSREP: " - "You have configured '%s' state snapshot transfer method " - "which cannot be performed on a running server. " - "Wsrep provider won't be able to fall back to it " - "if other means of state transfer are unavailable. " - "In that case you will need to restart the server.", - wsrep_sst_method); - *msg = 0; - return 0; - } - - addr_len = sst_prepare_other (wsrep_sst_method, addr_in, &addr_out); - if (addr_len < 0) - { - WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", - wsrep_sst_method); - unireg_abort(1); - } - } - - size_t const method_len(strlen(wsrep_sst_method)); - size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); - - *msg = malloc (msg_len); - if (NULL != *msg) { - char* const method_ptr(reinterpret_cast(*msg)); - strcpy (method_ptr, wsrep_sst_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); - } - - if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); - - return msg_len; -} - -// helper method for donors -static int sst_run_shell (const char* cmd_str, int max_tries) -{ - int ret = 0; - - for (int tries=1; tries <= max_tries; tries++) - { - wsp::process proc (cmd_str, "r"); - - if (NULL != proc.pipe()) - { - proc.wait(); - } - - if ((ret = proc.error())) - { - WSREP_ERROR("Try %d/%d: '%s' failed: %d (%s)", - tries, max_tries, proc.cmd(), ret, strerror(ret)); - sleep (1); - } - else - { - WSREP_DEBUG("SST script successfully completed."); - break; - } - } - - return -ret; -} - -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); -} - -static int sst_mysqldump_check_addr (const char* user, const char* pswd, - const char* host, const char* port) -{ - return 0; -} - -static int sst_donate_mysqldump (const char* addr, - const wsrep_uuid_t* uuid, - const char* uuid_str, - wsrep_seqno_t seqno, - bool bypass) -{ - size_t host_len; - const char* port = strchr (addr, ':'); - - if (port) - { - port += 1; - host_len = port - addr; - } - else - { - port = ""; - host_len = strlen (addr) + 1; - } - - char host[host_len]; - - strncpy (host, addr, host_len - 1); - host[host_len - 1] = '\0'; - - const char* auth = sst_auth_real; - const char* pswd = (auth) ? strchr (auth, ':') : NULL; - size_t user_len; - - if (pswd) - { - pswd += 1; - user_len = pswd - auth; - } - else - { - pswd = ""; - user_len = (auth) ? strlen (auth) + 1 : 1; - } - - char user[user_len]; - - strncpy (user, (auth) ? auth : "", user_len - 1); - user[user_len - 1] = '\0'; - - int ret = sst_mysqldump_check_addr (user, pswd, host, port); - if (!ret) - { - size_t cmd_len= 1024; - char cmd_str[cmd_len]; - - if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); - - snprintf (cmd_str, cmd_len, - "wsrep_sst_mysqldump " - WSREP_SST_OPT_USER" '%s' " - WSREP_SST_OPT_PSWD" '%s' " - WSREP_SST_OPT_HOST" '%s' " - WSREP_SST_OPT_PORT" '%s' " - WSREP_SST_OPT_LPORT" '%u' " - WSREP_SST_OPT_SOCKET" '%s' " - WSREP_SST_OPT_GTID" '%s:%lld'" - "%s", - user, pswd, host, port, mysqld_port, mysqld_unix_port, uuid_str, - (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); - - WSREP_DEBUG("Running: '%s'", cmd_str); - - ret= sst_run_shell (cmd_str, 3); - } - - wsrep->sst_sent (wsrep, uuid, ret ? ret : seqno); - - return ret; -} - -wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - -static int run_sql_command(THD *thd, const char *query) -{ - thd->set_query((char *)query, strlen(query)); - - Parser_state ps; - if (ps.init(thd, thd->query(), thd->query_length())) - { - WSREP_ERROR("SST query: %s failed", query); - return -1; - } - - mysql_parse(thd, thd->query(), thd->query_length(), &ps); - if (thd->is_error()) - { - int const err= thd->stmt_da->sql_errno(); - WSREP_WARN ("error executing '%s': %d (%s)%s", - query, err, thd->stmt_da->message(), - err == ER_UNKNOWN_SYSTEM_VARIABLE ? - ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); - thd->clear_error(); - return -1; - } - return 0; -} - -static int sst_flush_tables(THD* thd) -{ - WSREP_INFO("Flushing tables for SST..."); - - int err; - int not_used; - if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) - { - WSREP_ERROR("Failed to flush and lock tables"); - err = -1; - } - else - { - /* make sure logs are flushed after global read lock acquired */ - err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG, - (TABLE_LIST*) 0, ¬_used); - } - - if (err) - { - WSREP_ERROR("Failed to flush tables: %d (%s)", err, strerror(err)); - } - else - { - WSREP_INFO("Tables flushed."); - const char base_name[]= "tables_flushed"; - ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; - char real_name[full_len]; - sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); - char tmp_name[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 - { - fprintf(file, "%s:%lld\n", - wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno); - 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)); - } - } - } - - return err; -} - -static void sst_disallow_writes (THD* thd, bool yes) -{ - char query_str[64] = { 0, }; - ssize_t const query_max = sizeof(query_str) - 1; - snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", - yes ? 1 : 0); - - if (run_sql_command(thd, query_str)) - { - WSREP_ERROR("Failed to disallow InnoDB writes"); - } -} - -static void* sst_donor_thread (void* a) -{ - sst_thread_arg* arg= (sst_thread_arg*)a; - - WSREP_INFO("Running: '%s'", arg->cmd); - - int err= 1; - bool locked= false; - - const char* out= NULL; - const size_t out_len= 128; - char out_buf[out_len]; - - wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; - wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST - - wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can - // operate with wsrep_ready == OFF - wsp::process proc(arg->cmd, "r"); - - err= proc.error(); - -/* Inform server about SST script startup and release TO isolation */ - mysql_mutex_lock (&arg->lock); - arg->err = -err; - mysql_cond_signal (&arg->cond); - mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. - - if (proc.pipe() && !err) - { -wait_signal: - out= my_fgets (out_buf, out_len, proc.pipe()); - - if (out) - { - const char magic_flush[]= "flush tables"; - const char magic_cont[]= "continue"; - const char magic_done[]= "done"; - - if (!strcasecmp (out, magic_flush)) - { - err= sst_flush_tables (thd.ptr); - if (!err) - { - sst_disallow_writes (thd.ptr, true); - locked= true; - goto wait_signal; - } - } - else if (!strcasecmp (out, magic_cont)) - { - if (locked) - { - sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); - locked= false; - } - err= 0; - goto wait_signal; - } - else if (!strncasecmp (out, magic_done, strlen(magic_done))) - { - err= sst_scan_uuid_seqno (out + strlen(magic_done) + 1, - &ret_uuid, &ret_seqno); - } - else - { - WSREP_WARN("Received unknown signal: '%s'", out); - } - } - else - { - WSREP_ERROR("Failed to read from: %s", proc.cmd()); - } - if (err && proc.error()) err= proc.error(); - } - else - { - WSREP_ERROR("Failed to execute: %s : %d (%s)", - proc.cmd(), err, strerror(err)); - } - - if (locked) // don't forget to unlock server before return - { - sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); - } - - // signal to donor that SST is over - wsrep->sst_sent (wsrep, &ret_uuid, err ? -err : ret_seqno); - proc.wait(); - - return NULL; -} - -static int sst_donate_other (const char* method, - const char* addr, - const char* uuid, - wsrep_seqno_t seqno, - bool bypass) -{ - ssize_t cmd_len = 4096; - char cmd_str[cmd_len]; - - int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s " - WSREP_SST_OPT_ROLE" 'donor' " - WSREP_SST_OPT_ADDR" '%s' " - WSREP_SST_OPT_AUTH" '%s' " - WSREP_SST_OPT_SOCKET" '%s' " - WSREP_SST_OPT_DATA" '%s' " - WSREP_SST_OPT_CONF" '%s' " - WSREP_SST_OPT_GTID" '%s:%lld'" - "%s", - method, addr, sst_auth_real, mysqld_unix_port, - mysql_real_data_home, wsrep_defaults_file, - uuid, (long long) seqno, - bypass ? " "WSREP_SST_OPT_BYPASS : ""); - - if (ret < 0 || ret >= cmd_len) - { - WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); - return (ret < 0 ? ret : -EMSGSIZE); - } - - if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); - - pthread_t tmp; - sst_thread_arg arg(cmd_str); - mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg); - if (ret) - { - WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)", - ret, strerror(ret)); - return ret; - } - mysql_cond_wait (&arg.cond, &arg.lock); - - WSREP_INFO("sst_donor_thread signaled with %d", arg.err); - return arg.err; -} - -int wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, - const void* msg, size_t msg_len, - const wsrep_uuid_t* current_uuid, - wsrep_seqno_t current_seqno, - const char* state, size_t state_len, - bool bypass) -{ - /* This will be reset when sync callback is called. - * Should we set wsrep_ready to FALSE here too? */ -// wsrep_notify_status(WSREP_MEMBER_DONOR); - local_status.set(WSREP_MEMBER_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 (current_uuid, uuid_str, sizeof(uuid_str)); - - int ret; - if (!strcmp (WSREP_SST_MYSQLDUMP, method)) - { - ret = sst_donate_mysqldump (data, current_uuid, uuid_str, current_seqno, - bypass); - } - else - { - ret = sst_donate_other (method, data, uuid_str, current_seqno, bypass); - } - - return (ret > 0 ? 0 : ret); -} - -void wsrep_SE_init_grab() -{ - if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); -} - -void wsrep_SE_init_wait() -{ - mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); - 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; -} diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc deleted file mode 100644 index daba0e4cab2..00000000000 --- a/sql/wsrep_utils.cc +++ /dev/null @@ -1,468 +0,0 @@ -/* Copyright 2010 Codership Oy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//! @file declares symbols private to wsrep integration layer - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE // POSIX_SPAWN_USEVFORK flag -#endif - -#include // posix_spawn() -#include // pipe() -#include // errno -#include // strerror() -#include // waitpid() - -#include -#include "wsrep_priv.h" - -extern char** environ; // environment variables - -static wsp::string wsrep_PATH; - -void -wsrep_prepend_PATH (const char* path) -{ - int count = 0; - - while (environ[count]) - { - if (strncmp (environ[count], "PATH=", 5)) - { - count++; - continue; - } - - char* const old_path (environ[count]); - - if (strstr (old_path, path)) return; // path already there - - size_t const new_path_len(strlen(old_path) + strlen(":") + - strlen(path) + 1); - - char* const new_path (reinterpret_cast(malloc(new_path_len))); - - if (new_path) - { - snprintf (new_path, new_path_len, "PATH=%s:%s", path, - old_path + strlen("PATH=")); - - wsrep_PATH.set (new_path); - environ[count] = new_path; - } - else - { - WSREP_ERROR ("Failed to allocate 'PATH' environment variable " - "buffer of size %zu.", new_path_len); - } - - return; - } - - WSREP_ERROR ("Failed to find 'PATH' environment variable. " - "State snapshot transfer may not be working."); -} - -namespace wsp -{ - -#define PIPE_READ 0 -#define PIPE_WRITE 1 -#define STDIN_FD 0 -#define STDOUT_FD 1 - -#ifndef POSIX_SPAWN_USEVFORK -# define POSIX_SPAWN_USEVFORK 0 -#endif - -process::process (const char* cmd, const char* type) - : str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0) -{ - if (0 == str_) - { - WSREP_ERROR ("Can't allocate command line of size: %zu", strlen(cmd)); - err_ = ENOMEM; - return; - } - - if (0 == strlen(str_)) - { - WSREP_ERROR ("Can't start a process: null or empty command line."); - return; - } - - if (NULL == type || (strcmp (type, "w") && strcmp(type, "r"))) - { - WSREP_ERROR ("type argument should be either \"r\" or \"w\"."); - return; - } - - int pipe_fds[2] = { -1, }; - if (::pipe(pipe_fds)) - { - err_ = errno; - WSREP_ERROR ("pipe() failed: %d (%s)", err_, strerror(err_)); - return; - } - - // which end of pipe will be returned to parent - int const parent_end (strcmp(type,"w") ? PIPE_READ : PIPE_WRITE); - 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 }; - if (!(pargv[0] && pargv[1] && pargv[2])) - { - err_ = ENOMEM; - WSREP_ERROR ("Failed to allocate pargv[] array."); - goto cleanup_pipe; - } - - posix_spawnattr_t attr; - err_ = posix_spawnattr_init (&attr); - if (err_) - { - WSREP_ERROR ("posix_spawnattr_init() failed: %d (%s)", - err_, strerror(err_)); - goto cleanup_pipe; - } - - err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | - POSIX_SPAWN_USEVFORK); - if (err_) - { - WSREP_ERROR ("posix_spawnattr_setflags() failed: %d (%s)", - err_, strerror(err_)); - goto cleanup_attr; - } - - posix_spawn_file_actions_t fact; - err_ = posix_spawn_file_actions_init (&fact); - if (err_) - { - WSREP_ERROR ("posix_spawn_file_actions_init() failed: %d (%s)", - err_, strerror(err_)); - goto cleanup_attr; - } - - // close child's stdout|stdin depending on what we returning - err_ = posix_spawn_file_actions_addclose (&fact, close_fd); - if (err_) - { - WSREP_ERROR ("posix_spawn_file_actions_addclose() failed: %d (%s)", - err_, strerror(err_)); - goto cleanup_fact; - } - - // substitute our pipe descriptor in place of the closed one - err_ = posix_spawn_file_actions_adddup2 (&fact, - pipe_fds[child_end], close_fd); - if (err_) - { - WSREP_ERROR ("posix_spawn_file_actions_addup2() failed: %d (%s)", - err_, strerror(err_)); - goto cleanup_fact; - } - - err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, environ); - 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 - goto cleanup_fact; - } - - io_ = fdopen (pipe_fds[parent_end], type); - - if (io_) - { - pipe_fds[parent_end] = -1; // skip close on cleanup - } - else - { - 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); - if (err) - { - WSREP_ERROR ("posix_spawn_file_actions_destroy() failed: %d (%s)\n", - err, strerror(err)); - } - -cleanup_attr: - err = posix_spawnattr_destroy (&attr); - if (err) - { - WSREP_ERROR ("posix_spawnattr_destroy() failed: %d (%s)", - err, strerror(err)); - } - -cleanup_pipe: - if (pipe_fds[0] >= 0) close (pipe_fds[0]); - if (pipe_fds[1] >= 0) close (pipe_fds[1]); - - free (pargv[0]); - free (pargv[1]); - free (pargv[2]); -} - -process::~process () -{ - if (io_) - { - assert (pid_); - assert (str_); - - WSREP_WARN("Closing pipe to child process: %s, PID(%ld) " - "which might still be running.", str_, (long)pid_); - - if (fclose (io_) == -1) - { - err_ = errno; - WSREP_ERROR("fclose() failed: %d (%s)", err_, strerror(err_)); - } - } - - if (str_) free (const_cast(str_)); -} - -int -process::wait () -{ - if (pid_) - { - int status; - if (-1 == waitpid(pid_, &status, 0)) - { - 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); - } - else { // command didn't complete with exit() - WSREP_ERROR("Process was aborted."); - 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 */ - } - WSREP_ERROR("Process completed with error: %s: %d (%s)", - str_, err_, strerror(err_)); - } - - pid_ = 0; - if (io_) fclose (io_); - io_ = NULL; - } - } - else { - assert (NULL == io_); - WSREP_ERROR("Command did not run: %s", str_); - } - - return err_; -} - -thd::thd (my_bool won) : init(), ptr(new THD) -{ - if (ptr) - { - ptr->thread_stack= (char*) &ptr; - ptr->store_globals(); - ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog - ptr->variables.wsrep_on = won; - ptr->security_ctx->master_access= ~(ulong)0; - lex_start(ptr); - } -} - -thd::~thd () -{ - if (ptr) - { - delete ptr; - my_pthread_setspecific_ptr (THR_THD, 0); - } -} - -} // namespace wsp - -extern ulong my_bind_addr; -extern uint mysqld_port; - -size_t guess_ip (char* buf, size_t buf_len) -{ - size_t ip_len = 0; - - if (htonl(INADDR_NONE) == my_bind_addr) { - WSREP_ERROR("Networking not configured, cannot receive state transfer."); - return 0; - } - - if (htonl(INADDR_ANY) != my_bind_addr) { - uint8_t* b = (uint8_t*)&my_bind_addr; - ip_len = snprintf (buf, buf_len, - "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); - return ip_len; - } - - // mysqld binds to all interfaces - try IP from wsrep_node_address - if (wsrep_node_address && wsrep_node_address[0] != '\0') { - const char* const colon_ptr = strchr(wsrep_node_address, ':'); - - if (colon_ptr) - ip_len = colon_ptr - wsrep_node_address; - else - ip_len = strlen(wsrep_node_address); - - if (ip_len >= buf_len) { - WSREP_WARN("default_ip(): buffer too short: %zu <= %zd", buf_len, ip_len); - return 0; - } - - memcpy (buf, wsrep_node_address, ip_len); - buf[ip_len] = '\0'; - return ip_len; - } - - // try to find the address of the first one -#if (TARGET_OS_LINUX == 1) - const char cmd[] = "/sbin/ifconfig | " -// "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "grep -E '^[[:space:]]+inet addr:' | grep -m1 -v 'inet addr:127' | " - "sed 's/:/ /' | awk '{ print $3 }'"; -#elif defined(__sun__) - const char cmd[] = "/sbin/ifconfig -a | " - "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; -#else - char *cmd; -#error "OS not supported" -#endif - wsp::process proc (cmd, "r"); - - if (NULL != proc.pipe()) { - char* ret; - - ret = fgets (buf, buf_len, proc.pipe()); - - if (proc.wait()) return 0; - - if (NULL == ret) { - WSREP_ERROR("Failed to read output of: '%s'", cmd); - return 0; - } - } - else { - WSREP_ERROR("Failed to execute: '%s'", cmd); - return 0; - } - - // clear possible \n at the end of ip string left by fgets() - ip_len = strlen (buf); - if (ip_len > 0 && '\n' == buf[ip_len - 1]) { - ip_len--; - buf[ip_len] = '\0'; - } - - if (INADDR_NONE == inet_addr(buf)) { - if (strlen(buf) != 0) { - WSREP_WARN("Shell command returned invalid address: '%s'", buf); - } - return 0; - } - - return ip_len; -} - -size_t guess_address(char* buf, size_t buf_len) -{ - size_t addr_len = guess_ip (buf, buf_len); - - if (addr_len && addr_len < buf_len) { - addr_len += snprintf (buf + addr_len, buf_len - addr_len, - ":%u", mysqld_port); - } - - return addr_len; -} - -/* - * WSREPXid - */ - -#define WSREP_XID_PREFIX "WSREPXid" -#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN -#define WSREP_XID_UUID_OFFSET 8 -#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) -{ - 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); - memcpy(xid->data + WSREP_XID_UUID_OFFSET, uuid, sizeof(wsrep_uuid_t)); - memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t)); -} - -const wsrep_uuid_t* wsrep_xid_uuid(const XID* xid) -{ - if (wsrep_is_wsrep_xid(xid)) - return reinterpret_cast(xid->data - + WSREP_XID_UUID_OFFSET); - else - return &WSREP_UUID_UNDEFINED; -} - -wsrep_seqno_t wsrep_xid_seqno(const XID* xid) -{ - - if (wsrep_is_wsrep_xid(xid)) - { - wsrep_seqno_t seqno; - memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); - return seqno; - } - else - { - return WSREP_SEQNO_UNDEFINED; - } -} - -extern "C" -int wsrep_is_wsrep_xid(const void* xid_ptr) -{ - const XID* xid= reinterpret_cast(xid_ptr); - return (xid->formatID == 1 && - xid->gtrid_length == WSREP_XID_GTRID_LEN && - xid->bqual_length == 0 && - !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)); -} diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc deleted file mode 100644 index 01f91b0a5ae..00000000000 --- a/sql/wsrep_var.cc +++ /dev/null @@ -1,548 +0,0 @@ -/* Copyright 2008 Codership Oy - - 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 -#include -#include -#include -#include -#include "wsrep_priv.h" -#include -#include -#include - -#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" -#define WSREP_CLUSTER_NAME "my_wsrep_cluster" - -const char* wsrep_provider = 0; -const char* wsrep_provider_options = 0; -const char* wsrep_cluster_address = 0; -const char* wsrep_cluster_name = 0; -const char* wsrep_node_name = 0; -static char node_address[256] = { 0, }; -const char* wsrep_node_address = node_address; // ??? -const char* wsrep_start_position = 0; -ulong wsrep_OSU_method_options; -static int wsrep_thread_change = 0; - -int wsrep_init_vars() -{ - wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME)); - wsrep_provider_options= my_strdup("", MYF(MY_WME)); - wsrep_cluster_address = my_strdup("", MYF(MY_WME)); - wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME)); - wsrep_node_name = my_strdup("", MYF(MY_WME)); - wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME)); - - global_system_variables.binlog_format=BINLOG_FORMAT_ROW; - return 0; -} - -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; - } - else { - } - -#ifdef REMOVED - if (thd->variables.wsrep_on) - thd->variables.option_bits |= (OPTION_BIN_LOG); - else - thd->variables.option_bits &= ~(OPTION_BIN_LOG); -#endif - return false; -} - -void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) -{ - if (var_type == OPT_GLOBAL) { - thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; - } - else { - } -} - -static int wsrep_start_position_verify (const char* start_str) -{ - size_t start_len; - wsrep_uuid_t uuid; - ssize_t uuid_len; - - start_len = strlen (start_str); - if (start_len < 34) - return 1; - - uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid); - if (uuid_len < 0 || (start_len - uuid_len) < 2) - return 1; - - if (start_str[uuid_len] != ':') // separator should follow UUID - return 1; - - char* endptr; - wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings - (strtoll(&start_str[uuid_len + 1], &endptr, 10)); - - if (*endptr == '\0') return 0; // remaining string was seqno - - return 1; -} - -bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* start_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - start_str = res->c_ptr(); - - if (!start_str) goto err; - - if (!wsrep_start_position_verify(start_str)) return 0; - -err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - start_str ? start_str : "NULL"); - return 1; -} - -void wsrep_set_local_position (const char* value) -{ - size_t value_len = strlen (value); - size_t uuid_len = wsrep_uuid_scan (value, value_len, &local_uuid); - - local_seqno = strtoll (value + uuid_len + 1, NULL, 10); - - XID xid; - wsrep_xid_init(&xid, &local_uuid, local_seqno); - wsrep_set_SE_checkpoint(&xid); - WSREP_INFO ("wsrep_start_position var submitted: '%s'", wsrep_start_position); -} - -bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) -{ - // since this value passed wsrep_start_position_check, don't check anything - // here - wsrep_set_local_position (wsrep_start_position); - - if (wsrep) { - wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); - } - - return 0; -} - -void wsrep_start_position_init (const char* val) -{ - if (NULL == val || wsrep_start_position_verify (val)) - { - WSREP_ERROR("Bad initial value for wsrep_start_position: %s", - (val ? val : "")); - return; - } - - wsrep_set_local_position (val); -} - -static bool refresh_provider_options() -{ - WSREP_DEBUG("refresh_provider_options: %s", - (wsrep_provider_options) ? wsrep_provider_options : "null"); - char* opts= wsrep->options_get(wsrep); - if (opts) - { - if (wsrep_provider_options) my_free((void *)wsrep_provider_options); - wsrep_provider_options = (char*)my_memdup(opts, strlen(opts) + 1, - MYF(MY_WME)); - } - else - { - WSREP_ERROR("Failed to get provider options"); - return true; - } - return false; -} - -static int wsrep_provider_verify (const char* provider_str) -{ - MY_STAT f_stat; - char path[FN_REFLEN]; - - if (!provider_str || strlen(provider_str)== 0) - return 1; - - if (!strcmp(provider_str, WSREP_NONE)) - return 0; - - if (!unpack_filename(path, provider_str)) - return 1; - - /* check that provider file exists */ - bzero(&f_stat, sizeof(MY_STAT)); - if (!my_stat(path, &f_stat, MYF(0))) - { - return 1; - } - return 0; -} - -bool wsrep_provider_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* provider_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - provider_str = res->c_ptr(); - - if (!provider_str) goto err; - - if (!wsrep_provider_verify(provider_str)) return 0; - -err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - provider_str ? provider_str : "NULL"); - return 1; -} - -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); - - wsrep_stop_replication(thd); - wsrep_deinit(); - - char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider - //when fails - if (wsrep_init()) - { - my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp); - 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); - - thd->variables.wsrep_on= wsrep_on_saved; - - refresh_provider_options(); - - return rcode; -} - -void wsrep_provider_init (const char* value) -{ - WSREP_DEBUG("wsrep_provider_init: %s -> %s", - (wsrep_provider) ? wsrep_provider : "null", - (value) ? value : "null"); - if (NULL == value || wsrep_provider_verify (value)) - { - WSREP_ERROR("Bad initial value for wsrep_provider: %s", - (value ? value : "")); - return; - } - - if (wsrep_provider) my_free((void *)wsrep_provider); - wsrep_provider = my_strdup(value, MYF(0)); -} - -bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) -{ - return 0; -} - -bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) -{ - wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options); - if (ret != WSREP_OK) - { - WSREP_ERROR("Set options returned %d", ret); - return true; - } - return refresh_provider_options(); -} - -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; -} - -static int wsrep_cluster_address_verify (const char* cluster_address_str) -{ - /* There is no predefined address format, it depends on provider. */ - return 0; -} - -bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* cluster_address_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - cluster_address_str = res->c_ptr(); - - if (!wsrep_cluster_address_verify(cluster_address_str)) return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - cluster_address_str ? cluster_address_str : "NULL"); - return 1 ; -} - -bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) -{ - bool wsrep_on_saved= thd->variables.wsrep_on; - thd->variables.wsrep_on= false; - - wsrep_stop_replication(thd); - - if (wsrep_start_replication()) - { - wsrep_create_rollbacker(); - wsrep_create_appliers(wsrep_slave_threads); - } - - thd->variables.wsrep_on= wsrep_on_saved; - - return false; -} - -void wsrep_cluster_address_init (const char* value) -{ - WSREP_DEBUG("wsrep_cluster_address_init: %s -> %s", - (wsrep_cluster_address) ? wsrep_cluster_address : "null", - (value) ? value : "null"); - - if (wsrep_cluster_address) my_free ((void*)wsrep_cluster_address); - wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; -} - -bool wsrep_cluster_name_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* cluster_name_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - cluster_name_str = res->c_ptr(); - - if (!cluster_name_str || strlen(cluster_name_str) == 0) goto err; - - return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - cluster_name_str ? cluster_name_str : "NULL"); - return 1; -} - -bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type) -{ - return 0; -} - -bool wsrep_node_name_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* node_name_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - node_name_str = res->c_ptr(); - - if (!node_name_str || strlen(node_name_str) == 0) goto err; - - return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - node_name_str ? node_name_str : "NULL"); - return 1; -} - -bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type) -{ - return 0; -} - -// TODO: do something more elaborate, like checking connectivity -bool wsrep_node_address_check (sys_var *self, THD* thd, set_var* var) -{ - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* node_address_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - node_address_str = res->c_ptr(); - - if (!node_address_str || strlen(node_address_str) == 0) goto err; - - return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - node_address_str ? node_address_str : "NULL"); - return 1; -} - -bool wsrep_node_address_update (sys_var *self, THD* thd, enum_var_type type) -{ - return 0; -} - -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; -} - -bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) -{ - mysql_mutex_lock(&LOCK_wsrep_slave_threads); - wsrep_thread_change = var->value->val_int() - wsrep_slave_threads; - mysql_mutex_unlock(&LOCK_wsrep_slave_threads); - - return 0; -} - -bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) -{ - if (wsrep_thread_change > 0) - { - wsrep_create_appliers(wsrep_thread_change); - } - else if (wsrep_thread_change < 0) - { - wsrep_close_applier_threads(-wsrep_thread_change); - } - return false; -} -/* - * Status variables stuff below - */ -static inline void -wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep) -{ - mysql->name = wsrep->name; - switch (wsrep->type) { - case WSREP_VAR_INT64: - mysql->value = (char*) &wsrep->value._int64; - mysql->type = SHOW_LONGLONG; - break; - case WSREP_VAR_STRING: - mysql->value = (char*) &wsrep->value._string; - mysql->type = SHOW_CHAR_PTR; - break; - case WSREP_VAR_DOUBLE: - mysql->value = (char*) &wsrep->value._double; - mysql->type = SHOW_DOUBLE; - break; - } -} - -#if DYNAMIC -// somehow this mysql status thing works only with statically allocated arrays. -static SHOW_VAR* mysql_status_vars = NULL; -static int mysql_status_len = -1; -#else -static SHOW_VAR mysql_status_vars[512 + 1]; -static const int mysql_status_len = 512; -#endif - -static void export_wsrep_status_to_mysql(THD* thd) -{ - int wsrep_status_len, i; - - thd->wsrep_status_vars = wsrep->stats_get(wsrep); - - if (!thd->wsrep_status_vars) { - return; - } - - for (wsrep_status_len = 0; - thd->wsrep_status_vars[wsrep_status_len].name != NULL; - wsrep_status_len++); - -#if DYNAMIC - if (wsrep_status_len != mysql_status_len) { - void* tmp = realloc (mysql_status_vars, - (wsrep_status_len + 1) * sizeof(SHOW_VAR)); - if (!tmp) { - - sql_print_error ("Out of memory for wsrep status variables." - "Number of variables: %d", wsrep_status_len); - return; - } - - mysql_status_len = wsrep_status_len; - mysql_status_vars = (SHOW_VAR*)tmp; - } - /* @TODO: fix this: */ -#else - if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len; -#endif - - for (i = 0; i < wsrep_status_len; i++) - wsrep_assign_to_mysql (mysql_status_vars + i, thd->wsrep_status_vars + i); - - mysql_status_vars[wsrep_status_len].name = NullS; - mysql_status_vars[wsrep_status_len].value = NullS; - mysql_status_vars[wsrep_status_len].type = SHOW_LONG; -} - -int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) -{ - export_wsrep_status_to_mysql(thd); - var->type= SHOW_ARRAY; - var->value= (char *) &mysql_status_vars; - return 0; -} - -void wsrep_free_status (THD* thd) -{ - if (thd->wsrep_status_vars) - { - wsrep->stats_free (wsrep, thd->wsrep_status_vars); - thd->wsrep_status_vars = 0; - } -} diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh deleted file mode 100644 index 507f83324b9..00000000000 --- a/support-files/wsrep.cnf.sh +++ /dev/null @@ -1,129 +0,0 @@ -# This file contains wsrep-related mysqld options. It should be included -# in the main MySQL configuration file. -# -# Options that need to be customized: -# - wsrep_provider -# - wsrep_cluster_address -# - wsrep_sst_auth -# The rest of defaults should work out of the box. - -## -## mysqld options _MANDATORY_ for correct opration of the cluster -## -[mysqld] - -# (This must be substituted by wsrep_format) -binlog_format=ROW - -# Currently only InnoDB storage engine is supported -default-storage-engine=innodb - -# to avoid issues with 'bulk mode inserts' using autoinc -innodb_autoinc_lock_mode=2 - -# This is a must for paralell applying -innodb_locks_unsafe_for_binlog=1 - -# Query Cache is not supported with wsrep -query_cache_size=0 -query_cache_type=0 - -# Override bind-address -# In some systems bind-address defaults to 127.0.0.1, and with mysqldump SST -# it will have (most likely) disastrous consequences on donor node -bind-address=0.0.0.0 - -## -## WSREP options -## - -# Full path to wsrep provider library or 'none' -wsrep_provider=none - -# Provider specific configuration options -#wsrep_provider_options= - -# Logical cluster name. Should be the same for all nodes. -wsrep_cluster_name="my_wsrep_cluster" - -# Group communication system handle -#wsrep_cluster_address="dummy://" - -# Human-readable node name (non-unique). Hostname by default. -#wsrep_node_name= - -# Base replication [:port] of the node. -# The values supplied will be used as defaults for state transfer receiving, -# listening ports and so on. Default: address of the first network interface. -#wsrep_node_address= - -# Address for incoming client connections. Autodetect by default. -#wsrep_node_incoming_address= - -# How many threads will process writesets from other nodes -wsrep_slave_threads=1 - -# DBUG options for wsrep provider -#wsrep_dbug_option - -# Generate fake primary keys for non-PK tables (required for multi-master -# and parallel applying operation) -wsrep_certify_nonPK=1 - -# Maximum number of rows in write set -wsrep_max_ws_rows=131072 - -# Maximum size of write set -wsrep_max_ws_size=1073741824 - -# to enable debug level logging, set this to 1 -wsrep_debug=0 - -# convert locking sessions into transactions -wsrep_convert_LOCK_to_trx=0 - -# how many times to retry deadlocked autocommits -wsrep_retry_autocommit=1 - -# change auto_increment_increment and auto_increment_offset automatically -wsrep_auto_increment_control=1 - -# retry autoinc insert, which failed for duplicate key error -wsrep_drupal_282555_workaround=0 - -# enable "strictly synchronous" semantics for read operations -wsrep_causal_reads=0 - -# Command to call when node status or cluster membership changes. -# Will be passed all or some of the following options: -# --status - new status of this node -# --uuid - UUID of the cluster -# --primary - whether the component is primary or not ("yes"/"no") -# --members - comma-separated list of members -# --index - index of this node in the list -wsrep_notify_cmd= - -## -## WSREP State Transfer options -## - -# State Snapshot Transfer method -wsrep_sst_method=mysqldump - -# Address which donor should send State Snapshot to. -# Should be the address of THIS node. DON'T SET IT TO DONOR ADDRESS!!! -# (SST method dependent. Defaults to the first IP of the first interface) -#wsrep_sst_receive_address= - -# SST authentication string. This will be used to send SST to joining nodes. -# Depends on SST method. For mysqldump method it is root: -wsrep_sst_auth=root: - -# Desired SST donor name. -#wsrep_sst_donor= - -# Reject client queries when donating SST (false) -#wsrep_sst_donor_rejects_queries=0 - -# Protocol version to use -# wsrep_protocol_version= diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh deleted file mode 100644 index bdbe3d12a39..00000000000 --- a/support-files/wsrep_notify.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/sh -eu - -# This is a simple example of wsrep notification script (wsrep_notify_cmd). -# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' -# and fill them on every membership or node status change. -# -# Edit parameters below to specify the address and login to server. - -USER=root -PSWD=rootpass -HOST=127.0.0.1 -PORT=3306 - -SCHEMA="wsrep" -MEMB_TABLE="$SCHEMA.membership" -STATUS_TABLE="$SCHEMA.status" - -BEGIN=" -SET wsrep_on=0; -DROP SCHEMA IF EXISTS $SCHEMA; CREATE SCHEMA $SCHEMA; -CREATE TABLE $MEMB_TABLE ( - idx INT UNIQUE PRIMARY KEY, - uuid CHAR(40) UNIQUE, /* node UUID */ - name VARCHAR(32), /* node name */ - addr VARCHAR(256) /* node address */ -) ENGINE=MEMORY; -CREATE TABLE $STATUS_TABLE ( - size INT, /* component size */ - idx INT, /* this node index */ - status CHAR(16), /* this node status */ - uuid CHAR(40), /* cluster UUID */ - prim BOOLEAN /* if component is primary */ -) ENGINE=MEMORY; -BEGIN; -DELETE FROM $MEMB_TABLE; -DELETE FROM $STATUS_TABLE; -" -END="COMMIT;" - -configuration_change() -{ - echo "$BEGIN;" - - local idx=0 - - for NODE in $(echo $MEMBERS | sed s/,/\ /g) - do - echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " - # Don't forget to properly quote string values - echo "'$NODE'" | sed s/\\//\',\'/g - echo ");" - idx=$(( $idx + 1 )) - done - - echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" - - echo "$END" -} - -status_update() -{ - echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;" -} - -COM=status_update # not a configuration change by default - -while [ $# -gt 0 ] -do - case $1 in - --status) - STATUS=$2 - shift - ;; - --uuid) - CLUSTER_UUID=$2 - shift - ;; - --primary) - [ "$2" = "yes" ] && PRIMARY="1" || PRIMARY="0" - COM=configuration_change - shift - ;; - --index) - INDEX=$2 - shift - ;; - --members) - MEMBERS=$2 - shift - ;; - esac - shift -done - -# Undefined means node is shutting down -if [ "$STATUS" != "Undefined" ] -then - $COM | mysql -B -u$USER -p$PSWD -h$HOST -P$PORT -fi - -exit 0 -# From f2837a3b33da3282b344a4adb442d12163d29e29 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 16:49:51 +0200 Subject: [PATCH 030/294] remerging wsrep files from lp:codership-mysql --- wsrep/CMakeLists.txt | 24 -- wsrep/Makefile.am | 2 - wsrep/wsrep_api.h | 875 ------------------------------------------- wsrep/wsrep_dummy.c | 368 ------------------ wsrep/wsrep_loader.c | 199 ---------- wsrep/wsrep_uuid.c | 78 ---- 6 files changed, 1546 deletions(-) delete mode 100644 wsrep/CMakeLists.txt delete mode 100644 wsrep/Makefile.am delete mode 100644 wsrep/wsrep_api.h delete mode 100644 wsrep/wsrep_dummy.c delete mode 100644 wsrep/wsrep_loader.c delete mode 100644 wsrep/wsrep_uuid.c diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt deleted file mode 100644 index 11d0e34d1b0..00000000000 --- a/wsrep/CMakeLists.txt +++ /dev/null @@ -1,24 +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 - -INCLUDE_DIRECTORIES( "." ) - -SET(WSREP_SOURCES wsrep_uuid.c wsrep_loader.c wsrep_dummy.c) - -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/Makefile.am b/wsrep/Makefile.am deleted file mode 100644 index 40e4b501e86..00000000000 --- a/wsrep/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -noinst_LIBRARIES = libwsrep.a -libwsrep_a_SOURCES = wsrep_api.h wsrep_loader.c wsrep_dummy.c wsrep_uuid.c diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h deleted file mode 100644 index 2cd10afc7ff..00000000000 --- a/wsrep/wsrep_api.h +++ /dev/null @@ -1,875 +0,0 @@ -/* Copyright (C) 2009-2011 Codership Oy - - 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_H -#define WSREP_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * wsrep replication API - */ - -#define WSREP_INTERFACE_VERSION "23" - -/*! - * Certain provider capabilities application may need to know - */ -#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_WRITE_SET_INCREMENTS ( 1ULL << 8 ) -#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) -#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) -#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) - -/*! - * Write set replication flags - */ -#define WSREP_FLAG_PA_SAFE ( 1ULL << 0 ) - -/* Empty backend spec */ -#define WSREP_NONE "none" - -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. - -/*! undefined seqno */ -#define WSREP_SEQNO_UNDEFINED (-1) - -/*! wsrep 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_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; - -/*! - * @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 library 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 *); - -/*! - * UUID type - for all unique IDs - */ -typedef struct wsrep_uuid { - uint8_t uuid[16]; -} wsrep_uuid_t; - -/*! Undefined UUID */ -static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; - -/*! - * Scan UUID from string - * @return length of UUID string representation or negative error code - */ -extern ssize_t -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 ssize_t -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 - -/*! - * 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_uuid_t uuid; //!< global state UUID - wsrep_seqno_t seqno; //!< global state seqno - wsrep_seqno_t view; //!< global view number - wsrep_view_status_t status; //!< view status - bool 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 in 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 void (*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, - ssize_t* sst_req_len); - -/*! - * @brief apply callback - * - * This handler is called from wsrep library to apply replicated write set - * 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 write set - * @param size data buffer size - * @param seqno global seqno part of the write set to be applied - * - * @return success code: - * @retval WSREP_OK - * @retval WSREP_NOT_IMPLEMENTED appl. does not support the write set format - * @retval WSREP_ERROR failed to apply the write set - */ -typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, - const void* data, - size_t size, - wsrep_seqno_t seqno); - -/*! - * @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 seqno global seqno part of the write set to be committed - * @param commit true - commit writeset, false - rollback writeset - * - * @return success code: - * @retval WSREP_OK - * @retval WSREP_ERROR call failed - */ -typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, - wsrep_seqno_t seqno, - bool commit); - -/*! - * @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 uuid current state uuid on this node - * @param seqno current state seqno 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 - * @return 0 for success or negative error code - */ -typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, - void* recv_ctx, - const void* msg, - size_t msg_len, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len, - bool 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, used as arguments for wsrep_init() - */ -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_uuid_t* state_uuid; //!< Application state sequence UUID - wsrep_seqno_t state_seqno; //!< Applicaiton state sequence number - const char* state; //!< Initial state for wsrep implementation - 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 - - /* 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 _int64; - double _double; - const char* _string; - } value; //!< variable value -}; - - -/*! Key part structure */ -typedef struct wsrep_key_part_ -{ - const void* buf; /*!< Buffer containing key part data */ - size_t buf_len; /*!< Length of buffer */ -} wsrep_key_part_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_key_part_t* key_parts; /*!< Array of key parts */ - size_t key_parts_len; /*!< Length of key parts array */ -} wsrep_key_t; - -/*! Transaction handle struct passed for wsrep transaction handling calls */ -typedef struct wsrep_trx_handle_ -{ - wsrep_trx_id_t trx_id; //!< transaction ID - void* opaque; //!< opaque provider transaction context data -} wsrep_trx_handle_t; - -/*! - * @brief Helper method to reset trx handle state when trx id changes - * - * Instead of passing wsrep_trx_handle_t directly for wsrep calls, - * wrapping handle with this call offloads bookkeeping from - * application. - */ -static inline wsrep_trx_handle_t* wsrep_trx_handle_for_id( - wsrep_trx_handle_t* trx_handle, - wsrep_trx_id_t trx_id) -{ - if (trx_handle->trx_id != trx_id) - { - trx_handle->trx_id = trx_id; - trx_handle->opaque = NULL; - } - return trx_handle; -} - - -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 this wsrep 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 this wsrep handle - */ - uint64_t (*capabilities) (wsrep_t* wsrep); - - /*! - * @brief Passes provider-specific configuration string to provider. - * - * @param wsrep this wsrep 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 this wsrep 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 this wsrep 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. - */ - wsrep_status_t (*connect) (wsrep_t* wsrep, - const char* cluster_name, - const char* cluster_url, - const char* state_donor); - - /*! - * @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 this wsrep 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 this wsrep handle - * @param trx_handle transaction which is committing - * @param conn_id connection ID - * @param app_data application specific applying data - * @param data_len the size of the applying data - * @param flags fine tuning the replication WSREP_FLAG_* - * @param seqno seqno part of the global transaction ID - * - * @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_trx_handle_t* trx_handle, - const void* app_data, - size_t data_len, - uint64_t flags, - wsrep_seqno_t* seqno); - - /*! - * @brief Releases resources after transaction commit. - * - * Ends commit critical section. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing - * @retval WSREP_OK post_commit succeeded - */ - wsrep_status_t (*post_commit) (wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle); - - /*! - * @brief Releases resources after transaction rollback. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing - * @retval WSREP_OK post_rollback succeeded - */ - wsrep_status_t (*post_rollback)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle); - - /*! - * @brief Replay trx as a slave write set - * - * 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 write sets and certification - * test based on write set content can be different to DBMS lock conflicts. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing - * @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_trx_handle_t* trx_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 this wsrep 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 query in transaction's write set - * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param query SQL statement string - * @param timeval time to use for time functions - * @param randseed seed for rand - */ - wsrep_status_t (*append_query)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const char* query, - time_t timeval, - uint32_t randseed); - - /*! - * @brief Appends a row reference in transaction's write set - * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param key array of keys - * @param key_len length of the array of keys - * @param shared boolean denoting if key corresponds to shared resource - */ - wsrep_status_t (*append_key)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const wsrep_key_t* key, - size_t key_len, - bool shared); - /*! - * @brief Appends data in transaction's write set - * - * This method can be called any time before commit and it - * appends data block into transaction's write set. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param data data buffer - * @param data_len data buffer length - */ - wsrep_status_t (*append_data)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const void* data, - size_t data_len); - - - /*! - * @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 - * seqno 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 this wsrep handle - * @param seqno location to store global transaction ID - */ - wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_seqno_t* seqno); - - /*! - * @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 this wsrep 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 query and returns success code, which - * caller must check. Total order isolation continues - * until to_execute_end() is called. - * - * @param wsrep this wsrep handle - * @param conn_id connection ID - * @param key array of keys - * @param key_len lenght of the array of keys - * @param query query to be executed - * @param query_len length of the query string - * @param seqno seqno part of the action 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_start)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id, - const wsrep_key_t* key, - size_t key_len, - const void* query, - size_t query_len, - wsrep_seqno_t* seqno); - - /*! - * @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 this wsrep 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 Signals to wsrep provider that state snapshot has been sent to - * joiner. - * - * @param wsrep this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation - */ - wsrep_status_t (*sst_sent)(wsrep_t* wsrep, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno); - - /*! - * @brief Signals to wsrep provider that new state snapshot has been received. - * May deadlock if called from sst_prepare_cb. - * - * @param wsrep this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation - * @param state initial state provided by SST donor - * @param state_len length of state buffer - */ - wsrep_status_t (*sst_received)(wsrep_t* wsrep, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len); - - - /*! - * @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 this wsrep 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 this wsrep 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 this wsrep handle. - */ - void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); - - /*! - * @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 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, int64_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, int64_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 - */ - bool (*is_locked) (wsrep_t* wsrep, const char* name, int64_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 this wsrep handle - */ - void (*free)(wsrep_t* wsrep); - - void *dlh; //!< reserved for future use - void *ctx; //!< reserved for implemetation private context -}; - -typedef int (*wsrep_loader_fun)(wsrep_t*); - -/*! - * - * @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 6d01ce14b4e..00000000000 --- a/wsrep/wsrep_dummy.c +++ /dev/null @@ -1,368 +0,0 @@ -/* Copyright (C) 2009-2010 Codership Oy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*! @file Dummy wsrep API implementation. */ - -#include - -#include "wsrep_api.h" - -/*! Dummy backend context. */ -typedef struct wsrep_dummy -{ - wsrep_log_cb_t log_fn; -} 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); - 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); - 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 __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static char* dummy_options_get (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return NULL; -} - -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_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_trx_handle_t* trx_handle __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - uint64_t flags __attribute__((unused)), - wsrep_seqno_t* seqno __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_post_commit( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_post_rollback( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_replay_trx( - wsrep_t* w, - wsrep_trx_handle_t* trx_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_query( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const char* query __attribute__((unused)), - const time_t timeval __attribute__((unused)), - const uint32_t randseed __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_row_key( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const wsrep_key_t* key __attribute__((unused)), - const size_t key_len __attribute__((unused)), - const bool shared __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_data( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const void* data __attribute__((unused)), - size_t data_len __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_causal_read( - wsrep_t* w, - wsrep_seqno_t* seqno __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_len __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - wsrep_seqno_t* seqno __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_sst_sent( - wsrep_t* w, - const wsrep_uuid_t* uuid __attribute__((unused)), - wsrep_seqno_t seqno __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_sst_received( - wsrep_t* w, - const wsrep_uuid_t* uuid __attribute__((unused)), - const wsrep_seqno_t seqno __attribute__((unused)), - const char* state __attribute__((unused)), - const size_t state_len __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 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)), - int64_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)), - int64_t o __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static bool dummy_is_locked (wsrep_t* w, - const char* s __attribute__((unused)), - int64_t* o __attribute__((unused)), - wsrep_uuid_t* t __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return false; -} - -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_query, - &dummy_append_row_key, - &dummy_append_data, - &dummy_causal_read, - &dummy_free_connection, - &dummy_to_execute_start, - &dummy_to_execute_end, - &dummy_sst_sent, - &dummy_sst_received, - &dummy_snapshot, - &dummy_stats_get, - &dummy_stats_free, - &dummy_pause, - &dummy_resume, - &dummy_desync, - &dummy_resync, - &dummy_lock, - &dummy_unlock, - &dummy_is_locked, - WSREP_NONE, - WSREP_INTERFACE_VERSION, - "Codership Oy ", - &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; - - return 0; -} - diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c deleted file mode 100644 index b4460658f80..00000000000 --- a/wsrep/wsrep_loader.c +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (C) 2009-2011 Codership Oy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*! @file wsrep implementation loader */ - -#include -#include -#include -#include - -#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 verify(const wsrep_t *wh, const char *iface_ver) -{ - const size_t msg_len = 128; - char msg[msg_len]; - -#define VERIFY(_p) if (!(_p)) { \ - snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ - logger (WSREP_LOG_ERROR, msg); \ - return EINVAL; \ - } - - VERIFY(wh); - VERIFY(wh->version); - - if (strcmp(wh->version, iface_ver)) { - snprintf (msg, msg_len, - "provider interface version mismatch: need '%s', found '%s'", - iface_ver, wh->version); - logger (WSREP_LOG_ERROR, msg); - 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_query); - VERIFY(wh->append_key); - VERIFY(wh->free_connection); - VERIFY(wh->to_execute_start); - VERIFY(wh->to_execute_end); - VERIFY(wh->sst_sent); - VERIFY(wh->sst_received); - VERIFY(wh->stats_get); - VERIFY(wh->stats_free); - 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; -} - - -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; -} - -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; - const size_t msg_len = 1024; - char msg[msg_len + 1]; - msg[msg_len] = 0; - - if (NULL != log_cb) - logger = log_cb; - - if (!(spec && hptr)) - return EINVAL; - - snprintf (msg, msg_len, - "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, msg_len, "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 ((ret = (*dlfun)(*hptr)) != 0) { - snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", - strerror(ret)); - logger (WSREP_LOG_ERROR, msg); - goto out; - } - - if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { - snprintf (msg, msg_len, - "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, msg_len, - "wsrep_load(): %s %s by %s loaded succesfully.", - (*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 c99240cc071..00000000000 --- a/wsrep/wsrep_uuid.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2009 Codership Oy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*! @file Helper functions to deal with history UUID string representations */ - -#include -#include -#include - -#include "wsrep_api.h" - -/*! - * Read UUID from string - * @return length of UUID string representation or -EINVAL in case of error - */ -ssize_t -wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) -{ - size_t uuid_len = 0; - size_t uuid_offt = 0; - - while (uuid_len + 1 < str_len) { - if ((4 == uuid_offt || 6 == uuid_offt || 8 == uuid_offt || - 10 == uuid_offt) && 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 - sscanf (str + uuid_len, "%2hhx", uuid->uuid + uuid_offt); - uuid_len += 2; - uuid_offt += 1; - if (sizeof (uuid->uuid) == 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 - */ -ssize_t -wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) -{ - if (str_len > 36) { - const unsigned char* u = uuid->uuid; - 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; - } -} - From 9da9a242faf1fd7b2f45dc0561e5bf742a7be47b Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 16:54:50 +0200 Subject: [PATCH 031/294] remerging wsrep files from lp:codership-mysql --- BUILD/compile-amd64-debug-wsrep | 11 + BUILD/compile-amd64-wsrep | 9 + BUILD/compile-pentium-debug-wsrep | 12 + BUILD/compile-pentium-wsrep | 11 + BUILD/compile-pentium64-wsrep | 28 + Docs/README-wsrep | 487 +++++++++++ cmake/wsrep.cmake | 59 ++ scripts/wsrep_sst_common.sh | 106 +++ scripts/wsrep_sst_mysqldump.sh | 121 +++ scripts/wsrep_sst_rsync.sh | 210 +++++ scripts/wsrep_sst_xtrabackup.sh | 222 +++++ sql/wsrep_check_opts.cc | 392 +++++++++ sql/wsrep_hton.cc | 449 ++++++++++ sql/wsrep_mysqld.cc | 1281 +++++++++++++++++++++++++++++ sql/wsrep_mysqld.h | 383 +++++++++ sql/wsrep_notify.cc | 107 +++ sql/wsrep_priv.h | 233 ++++++ sql/wsrep_sst.cc | 1001 ++++++++++++++++++++++ sql/wsrep_utils.cc | 467 +++++++++++ sql/wsrep_var.cc | 532 ++++++++++++ support-files/wsrep.cnf.sh | 129 +++ support-files/wsrep_notify.sh | 102 +++ wsrep/CMakeLists.txt | 24 + wsrep/Makefile.am | 2 + wsrep/wsrep_api.h | 875 ++++++++++++++++++++ wsrep/wsrep_dummy.c | 368 +++++++++ wsrep/wsrep_loader.c | 199 +++++ wsrep/wsrep_uuid.c | 78 ++ 28 files changed, 7898 insertions(+) create mode 100644 BUILD/compile-amd64-debug-wsrep create mode 100644 BUILD/compile-amd64-wsrep create mode 100644 BUILD/compile-pentium-debug-wsrep create mode 100644 BUILD/compile-pentium-wsrep create mode 100644 BUILD/compile-pentium64-wsrep create mode 100644 Docs/README-wsrep create mode 100644 cmake/wsrep.cmake create mode 100644 scripts/wsrep_sst_common.sh create mode 100644 scripts/wsrep_sst_mysqldump.sh create mode 100644 scripts/wsrep_sst_rsync.sh create mode 100644 scripts/wsrep_sst_xtrabackup.sh create mode 100644 sql/wsrep_check_opts.cc create mode 100644 sql/wsrep_hton.cc create mode 100644 sql/wsrep_mysqld.cc create mode 100644 sql/wsrep_mysqld.h create mode 100644 sql/wsrep_notify.cc create mode 100644 sql/wsrep_priv.h create mode 100644 sql/wsrep_sst.cc create mode 100644 sql/wsrep_utils.cc create mode 100644 sql/wsrep_var.cc create mode 100644 support-files/wsrep.cnf.sh create mode 100644 support-files/wsrep_notify.sh create mode 100644 wsrep/CMakeLists.txt create mode 100644 wsrep/Makefile.am create mode 100644 wsrep/wsrep_api.h create mode 100644 wsrep/wsrep_dummy.c create mode 100644 wsrep/wsrep_loader.c create mode 100644 wsrep/wsrep_uuid.c diff --git a/BUILD/compile-amd64-debug-wsrep b/BUILD/compile-amd64-debug-wsrep new file mode 100644 index 00000000000..995a8afcca9 --- /dev/null +++ b/BUILD/compile-amd64-debug-wsrep @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$amd64_cflags $debug_cflags -g -O0 $wsrep_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$amd64_configs $debug_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-amd64-wsrep b/BUILD/compile-amd64-wsrep new file mode 100644 index 00000000000..57dfbdd6da2 --- /dev/null +++ b/BUILD/compile-amd64-wsrep @@ -0,0 +1,9 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$amd64_cflags $fast_cflags -g $wsrep_cflags" +extra_configs="$amd64_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-debug-wsrep b/BUILD/compile-pentium-debug-wsrep new file mode 100644 index 00000000000..ee68e3fd0c1 --- /dev/null +++ b/BUILD/compile-pentium-debug-wsrep @@ -0,0 +1,12 @@ +#! /bin/sh -x + +path=`dirname $0` +set -- "$@" --with-debug=full +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $debug_cflags -g -O0 $wsrep_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$pentium_configs $debug_configs $wsrep_configs --with-wsrep" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-wsrep b/BUILD/compile-pentium-wsrep new file mode 100644 index 00000000000..eeb14310e4e --- /dev/null +++ b/BUILD/compile-pentium-wsrep @@ -0,0 +1,11 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $fast_cflags $wsrep_cflags" +extra_configs="$pentium_configs $wsrep_configs --with-wsrep" + +#strip=yes + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-wsrep b/BUILD/compile-pentium64-wsrep new file mode 100644 index 00000000000..0bccb34e753 --- /dev/null +++ b/BUILD/compile-pentium64-wsrep @@ -0,0 +1,28 @@ +#! /bin/sh + +# Copyright (C) 2006, 2007 MySQL AB +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$pentium64_cflags $fast_cflags -g $wsrep_cflags" +extra_configs="$pentium_configs $static_link $wsrep_configs --with-wsrep" +CC="$CC --pipe" +strip=yes + +. "$path/FINISH.sh" diff --git a/Docs/README-wsrep b/Docs/README-wsrep new file mode 100644 index 00000000000..025379764b2 --- /dev/null +++ b/Docs/README-wsrep @@ -0,0 +1,487 @@ +Codership Oy +http://www.codership.com + + +DISCLAIMER + +THIS SOFTWARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +IN NO EVENT SHALL CODERSHIP OY BE HELD LIABLE TO ANY PARTY FOR ANY DAMAGES +RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE. + +Trademark Information. + +MySQL is a trademark or registered trademark of Oracle and/or its affiliates. +Other trademarks are the property of their respective owners. + +Licensing Information. + +Please see file COPYING that came with this distribution + +Source code can be found at +wsrep API: https://launchpad.net/wsrep +MySQL patch: https://launchpad.net/codership-mysql + + +ABOUT THIS DOCUMENT + +This document covers installation and configuration issues specific to this +wsrep-patched MySQL distribution by Codership. It does not cover the use or +administration of MySQL server per se. The reader is assumed to know how to +install, configure, administer and use standard MySQL server version 5.1.xx. + + + MYSQL-5.5.x/wsrep-23.x + +CONTENTS: +========= +1. WHAT IS WSREP PATCH FOR MYSQL +2. INSTALLATION +3. FIRST TIME SETUP + 3.1 CONFIGURATION FILES + 3.2 DATABASE PRIVILEGES + 3.3 CHECK AND CORRECT FIREWALL SETTINGS + 3.4 SELINUX + 3.5 APPARMOR + 3.6 CONNECT TO CLUSTER +4. UPGRADING FROM MySQL 5.1.x +5. CONFIGURATION OPTIONS + 5.1 MANDATORY MYSQL OPTIONS + 5.2 WSREP OPTIONS +6. ONLINE SCHEMA UPGRADE + 6.1 TOTAL ORDER ISOLATION (TOI) + 6.2 ROLLING SCHEMA UPGRADE (RSU) +7. LIMITATIONS + + +1. WHAT IS WSREP PATCH FOR MYSQL/INNODB + +Wsrep API developed by Codership Oy is a modern generic (database-agnostic) +replication API for transactional databases with a goal to make database +replication/logging subsystem completely modular and pluggable. It is developed +with flexibility and completeness in mind to satisfy broad range of modern +replication scenarios. It is equally suitable for synchronous and asynchronous, +master-slave and multi-master replication. + +wsrep stands for Write Set REPlication. + +Wsrep patch for MySQL/InnoDB allows MySQL server to load and use various wsrep +API implementations ("wsrep providers") with different qualities of service. +Without wsrep provider MySQL-wsrep server will function like a regular +standalone server. + + +2. INSTALLATION + +In the examples below mysql authentication options are omitted for brevity. + +2.1 Download and install mysql-wsrep package. + +Download binary package for your Linux distribution from +https://launchpad.net/codership-mysql/ + +2.1.1 On Debian and Debian-derived distributions. + +Upgrade from mysql-server-5.0 to mysql-wsrep is not supported yet, please +upgrade to mysql-server-5.1 first. + +If you're installing over an existing mysql installation, mysql-server-wsrep +will conflict with mysql-server-5.1 package, so remove it first: + +$ sudo apt-get remove mysql-server-5.1 mysql-server-core-5.1 + +mysql-server-wsrep requires psmisc and mysql-client-5.1.47 (or later). +MySQL 5.1 packages can be found from backports repositories. +For further information about configuring and using Debian or Ubuntu +backports, see: + +* http://backports.debian.org + +* https://help.ubuntu.com/community/UbuntuBackports + +For example, installation of required packages on Debian Lenny: + +$ sudo apt-get install psmisc +$ sudo apt-get -t lenny-backports install mysql-client-5.1 + +Now you should be able to install mysql-wsrep package: + +$ sudo dpkg -i + +2.1.2 On CentOS and similar RPM-based distributions. + +If you're migrating from existing MySQL installation, there are two variants: + + a) If you're already using official MySQL-server-community 5.1.x RPM from + Oracle: + + # rpm -e mysql-server + + b) If you're upgrading from the stock mysql-5.0.77 on CentOS: + + 1) Make sure that the following packages are not installed: + # rpm --nodeps --allmatches -e mysql-server mysql-test mysql-bench + + 2) Install *official* MySQL-shared-compat-5.1.x from + http://dev.mysql.com/downloads/mysql/5.1.html + +Actual installation: + + # rpm -Uvh + + If this fails due to unsatisfied dependencies, install missing packages + (e.g. yum install perl-DBI) and retry. + +Additional packages to consider (if not yet installed): + * galera (multi-master replication provider, https://launchpad.net/galera) + * MySQL-client-community (for connecting to server and mysqldump-based SST) + * rsync (for rsync-based SST) + * xtrabackup and nc (for xtrabackup-based SST) + +2.2 Upgrade system tables. + +If you're upgrading a previous MySQL installation, it might be advisable to +upgrade system tables. To do that start mysqld and run mysql_upgrade command. +Consult MySQL documentation in case of errors. Normally they are not critical +and can be ignored unless specific functionality is needed. + + +3. FIRST TIME SETUP + +Unless you're upgrading an already installed mysql-wsrep package, you will need +to set up a few things to prepare server for operation. + +3.1 CONFIGURATION FILES + +* Make sure system-wide my.cnf does not bind mysqld to 127.0.0.1. That is, if + you have the following line in [mysqld] section, comment it out: + + #bind-address = 127.0.0.1 + +* Make sure system-wide my.cnf contains "!includedir /etc/mysql/conf.d/" line. + +* Edit /etc/mysql/conf.d/wsrep.cnf and set wsrep_provider option by specifying + a path to provider library. If you don't have a provider, leave it as it is. + +* When a new node joins the cluster it'll have to receive a state snapshot from + one of the peers. This requires a privileged MySQL account with access from + the rest of the cluster. Edit /etc/mysql/conf.d/wsrep.cnf and set mysql + login/password pair for SST, for example: + + wsrep_sst_auth=wsrep_sst:wspass + +* See CONFIGURATION section below about other configuration parameters that you + might want to change at this point. + +3.2 DATABASE PRIVILEGES + +Restart MySQL server and connect to it as root to grant privileges to SST +account (empty users confuse MySQL authentication matching rules, we need to +delete them too): + +$ mysql -e "SET wsrep_on=OFF; DELETE FROM mysql.user WHERE user='';" +$ mysql -e "SET wsrep_on=OFF; GRANT ALL ON *.* TO wsrep_sst@'%' IDENTIFIED BY 'wspass'"; + +3.3 CHECK AND CORRECT FIREWALL SETTINGS. + +MySQL-wsrep server needs to be accessible from other cluster members through +its client listening socket and through wsrep provider socket. See your +distribution and wsrep provider documentation for details. For example on +CentOS you might need to do something along these lines: + +# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 3306 -j ACCEPT +# iptables --insert RH-Firewall-1-INPUT 1 --proto tcp --source /24 --destination /32 --dport 4567 -j ACCEPT + +If there is a NAT firewall between the nodes, it must be configured to allow +direct connections between the nodes (e.g. via port forwarding). + +3.4 SELINUX + +If you have SELinux enabled, it may block mysqld from doing required operations. +You'll need to either disable it or configure to allow mysqld to run external +programs and open listen sockets at unprivileged ports (i.e. things that +an unprivileged user can do). See SELinux documentation about it. + +To quickly disable SELinux: +1) run 'setenforce 0' as root. +2) set 'SELINUX=permissive' in /etc/selinux/config + +3.5 APPARMOR + +AppArmor automatically comes with Ubuntu and may also prevent mysqld to from +opening additional ports or run scripts. See AppArmor documentation about its +configuration. To disable AppArmor for mysqld: + +$ cd /etc/apparmor.d/disable/ +$ sudo ln -s /etc/apparmor.d/usr.sbin.mysqld +$ sudo service apparmor restart + + +3.6 CONNECT TO CLUSTER + +Now you're ready to connect to cluster by setting wsrep_cluster_address variable +and monitor status of wsrep provider: + +mysql> SET GLOBAL wsrep_cluster_address=''; +mysql> SHOW STATUS LIKE 'wsrep%'; + + +4 UPGRADING FROM MySQL 5.1.x + +!!! THESE INSTRUCTIONS ARE PRELIMINARY AND INCOMPLETE !!! + +1) BEFORE UPGRADE (while running 5.1.x): + - comment out 'wsrep_provider' setting from configuration files + (my.cnf and/or wsrep.cnf) + - If performing a rolling upgrade on a running cluster, set + wsrep_sst_method=mysqldump. + You might also need to configure wsrep_sst_receive_address and + wsrep_sst_auth appropriately. mysqldump is the only way to transfer data + from 5.1.x to 5.5.x reliably. + - remove innodb_plugin settings from configuration files. + +2) Perform upgrade as usual: + http://dev.mysql.com/doc/refman/5.5/en/upgrading-from-previous-series.html + Don't forget to run 'mysql_upgrade' command. + +3) AFTER UPGRADING individual node: + - uncomment 'wsrep_provider' line in configuration file. + - restart the server and join the cluster. + +4) AFTER UPGRADING the whole cluster: + - revert to usual wsrep SST settings if not 'mysqldump'. + + +5. CONFIGURATION OPTIONS + +5.1 MANDATORY MYSQL OPTIONS + +binlog_format=ROW + This option is required to use row-level replication as opposed to + statement-level. For performance and consistency considerations don't change + that. As a side effect, binlog, if turned on, can be ROW only. In future this + option won't have special meaning. + +innodb_autoinc_lock_mode=2 + This is a required parameter. Without it INSERTs into tables with + AUTO_INCREMENT column may fail. + autoinc lock modes 0 and 1 can cause unresolved deadlock, and make + system unresponsive. + +innodb_locks_unsafe_for_binlog=1 + This option is required for parallel applying. + +5.2 WSREP OPTIONS + +All options are optional except for wsrep_provider, wsrep_cluster_address, and +wsrep_sst_auth. + +wsrep_provider=none + A full path to the library that implements WSREP interface. If none is + specified, the server behaves like a regular mysqld. + +wsrep_provider_options= + Provider-specific option string. Check wsrep provider documentation or + http://www.codership.com/wiki + +wsrep_cluster_address= + Provider-specific cluster address string. This is used to connect a node to + the desired cluster. This option can be given either on mysqld startup or set + during runtime. See wsrep provider documentation for possible values. + +wsrep_cluster_name="my_wsrep_cluster" + Logical cluster name, must be the same for all nodes of the cluster. + +wsrep_node_address= + An option to explicitly specify the network address of the node in the form +
[:port] if autoguessing for some reason does not produce desirable + results (multiple network interfaces, NAT, etc.) + If not explicitly overridden by wsrep_sst_receive_address, the
part + will be used to listen for SST (see below). And the whole
[:port] + will be passed to wsrep provider to be used as a base address in its + communications. + +wsrep_node_name= + Human readable node name (for easier log reading only). Defaults to hostname. + +wsrep_slave_threads=1 + Number of threads dedicated to processing of writesets from other nodes. + For best performance should be few per CPU core. + +wsrep_dbug_option + Options for the built-in DBUG library (independent from what MySQL uses). + Empty by default. Not currently in use. + +wsrep_debug=0 + Enable debug-level logging. + +wsrep_convert_LOCK_to_trx=0 + Implicitly convert locking sessions into transactions inside mysqld. By + itself it does not mean support for locking sessions, but it prevents the + database from going into logically inconsistent state. Note however, that + loading large database dump with LOCK statements might result in abnormally + large transactions and cause an out-of-memory condition + +wsrep_retry_autocommit=1 + Retry autocommit queries and single statement transactions should they fail + certification test. This is analogous to rescheduling an autocommit query + should it go into deadlock with other transactions in the database lock + manager. + +wsrep_auto_increment_control=1 + Automatically adjust auto_increment_increment and auto_increment_offset + variables based on the number of nodes in the cluster. Significantly reduces + certification conflict rate for INSERTS. + +wsrep_drupal_282555_workaround=1 + MySQL seems to have an obscure bug when INSERT into table with + AUTO_INCREMENT column with NULL value for that column can fail with a + duplicate key error. When this option is on, it retries such INSERTs. + Required for stable Drupal operation. Documented at: + http://bugs.mysql.com/bug.php?id=41984 + http://drupal.org/node/282555 + +wsrep_causal_reads=0 + Enforce strict READ COMMITTED semantics on reads and transactions. May + result in additional latencies. It is a session variable. + +wsrep_OSU_method=TOI + Online Schema Upgrade (OSU) can be performed with two alternative methods: + Total Order Isolation (TOI) runs DDL statement in all cluster nodes in + same total order sequence locking the affected table for the duration of the + operation. This may result in the whole cluster being blocked for the + duration of the operation. + Rolling Schema Upgrade (RSU) executes the DDL statement only locally, thus + blocking only one cluster node. During the DDL processing, the node + is not replicating and may be unable to process replication events (due to + table lock). Once DDL operation is complete, the node will catch up and sync + with the cluster to become fully operational again. The DDL statement or + its effects are not replicated, so it is user's responsibility to manually + perform this operation on each of the nodes. + +wsrep_forced_binlog_format=none + Force every transaction to use given binlog format. When this variable is + set to something else than NONE, all transactions will use the given forced + format, regardless of what the client session has specified in binlog_format. + Valid choices for wsrep_forced_binlog_format are: ROW, STATEMENT, MIXED and + special value NONE, meaning that there is no forced binlog format in effect. + This variable was intruduced to support STATEMENT format replication during + rolling schema upgrade processing. However, in most cases ROW replication + is valid for asymmetrict schema replication. + +State snapshot transfer options. + +When a new node joins the cluster it has to synchronize its initial state with +the other cluster members by transferring state snapshot from one of them. +The options below govern how this happens and should be set up before attempting +to join or start a cluster. + +wsrep_sst_method=mysqldump + What method to use to copy database state to a newly joined node. Supported + methods: + - mysqldump: slow (except for small datasets) but most tested. + - rsync: much faster on large datasets. + - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. + - xtrabackup: very fast and practically non-blocking SST method based on + Percona's xtrabackup tool. + + (for xtrabackup to work the following settings must be present in my.cnf + on all nodes: + [mysqld] + wsrep_sst_auth=root: + datadir= + [client] + socket= + ) + +wsrep_sst_receive_address= + Address (hostname:port) at which this node wants to receive state snapshot. + Defaults to mysqld bind address, and if that is not specified (0.0.0.0) - + to the first IP of eth0 + mysqld bind port. + NOTE: check that your firewall allows connections to this address from other + cluster nodes. + +wsrep_sst_auth= + Authentication information needed for state transfer. Depends on the state + transfer method. For mysqldump-based SST it is + : + and should be the same on all nodes - it is used to authenticate with both + state snapshot receiver and state snapshot donor. + +wsrep_sst_donor= + A name of the node which should serve as state snapshot donor. This allows + to control which node will serve state snapshot request. By default the + most suitable node is chosen by wsrep provider. This is the same as given in + wsrep_node_name. + + +6. ONLINE SCHEMA UPGRADE + + Schema upgrades mean any data definition statements (DDL statemnents) run + for the database. They change the database structure and are non- + transactional. + + Release 22.3 brings a new method for performing schema upgrades. User can + now choose whether to use the traditional total order isolation or new + rolling schema upgrade method. The OSU method choice is done by global + parameter: 'wsrep_OSU_method'. + +6.1 Total Order Isolation (TOI) + + With earlier releases, DDL processing happened always by Total Order + Isolation (TOI) method. With TOI, the DDL was scheduled to be processed in + same transaction seqeuncing 'slot' in each cluster node. + The processing is secured by locking the affected table from any other use. + With TOI method, the whole cluster has part of the database locked for the + duration of the DDL processing. + +6.2 Rolling Schema Upgrade (RSU) + + Rolling schema upgrade is new DDL processing method, where DDL will be + processed locally for the node. The node is disconnected of the replication + for the duration of the DDL processing, so that there is only DDL statement + processing in the node and it does not block the rest of the cluster. When + the DDL processing is complete, the node applies delayed replication events + and synchronizes back with the cluster. + The DDL can then be executed cluster-wide by running the same DDL statement + for each node in turn. When this rolling schema upgrade proceeds, part of + the cluster will have old schema structure and part of the cluster will have + new schema structure. + + +7. LIMITATIONS + +1) Currently replication works only with InnoDB storage engine. Any writes to + tables of other types, including system (mysql.*) tables are not replicated. + However, DDL statements are replicated in statement level, and changes + to mysql.* tables will get replicated that way. + So, you can safely issue: CREATE USER..., + but issuing: INSERT INTO mysql.user..., will not be replicated. + +2) DELETE operation is unsupported on tables without primary key. Also rows in + tables without primary key may appear in different order on different nodes. + As a result SELECT...LIMIT... may return slightly different sets. + +3) Unsupported queries: + * LOCK/UNLOCK TABLES cannot be supported in multi-master setups. + * lock functions (GET_LOCK(), RELEASE_LOCK()... ) + +4) Query log cannot be directed to table. If you enable query logging, + you must forward the log to a file: + log_output = FILE + Use general_log and general_log_file to choose query logging and the + log file name + +5) Maximum allowed transaction size is defined by wsrep_max_ws_rows and + wsrep_max_ws_size. Anything bigger (e.g. huge LOAD DATA) will be rejected. + +6) Due to cluster level optimistic concurrency control, transaction issuing + COMMIT may still be aborted at that stage. There can be two transactions. + writing to same rows and committing in separate cluster nodes, and only one + of the them can successfully commit. The failing one will be aborted. + For cluster level aborts, MySQL/galera cluster gives back deadlock error. + code (Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK)). + +7) XA transactions can not be supported due to possible rollback on commit. + diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake new file mode 100644 index 00000000000..bb646028285 --- /dev/null +++ b/cmake/wsrep.cmake @@ -0,0 +1,59 @@ +# Copyright (c) 2011, Codership Oy . +# +# 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 + +# We need to generate a proper spec file even without --with-wsrep flag, +# so WSREP_VERSION is produced regardless + +# Set the patch version +SET(WSREP_PATCH_VERSION "7") + +# Obtain patch revision number +SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) +IF(NOT WSREP_PATCH_REVNO) + EXECUTE_PROCESS( + COMMAND bzr revno + OUTPUT_VARIABLE WSREP_PATCH_REVNO + RESULT_VARIABLE RESULT + ) +STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_PATCH_REVNO "${WSREP_PATCH_REVNO}") +#FILE(WRITE "wsrep_config" "Debug: WSREP_PATCH_REVNO result: ${RESULT}\n") +ENDIF() +IF(NOT WSREP_PATCH_REVNO) + SET(WSREP_PATCH_REVNO "XXXX") +ENDIF() + +# Obtain wsrep API version +EXECUTE_PROCESS( + COMMAND sh -c "grep WSREP_INTERFACE_VERSION ${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h | cut -d '\"' -f 2" + OUTPUT_VARIABLE WSREP_API_VERSION + RESULT_VARIABLE RESULT +) +#FILE(WRITE "wsrep_config" "Debug: WSREP_API_VERSION result: ${RESULT}\n") +STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_API_VERSION "${WSREP_API_VERSION}") + +SET(WSREP_VERSION + "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" +) + +OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" OFF) +IF (WITH_WSREP) + SET(WSREP_C_FLAGS "-DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WSREP_C_FLAGS}") + SET(COMPILATION_COMMENT "${COMPILATION_COMMENT}, wsrep_${WSREP_VERSION}") + SET(WITH_EMBEDDED_SERVER OFF) +ENDIF() + +# diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh new file mode 100644 index 00000000000..5c292465ecc --- /dev/null +++ b/scripts/wsrep_sst_common.sh @@ -0,0 +1,106 @@ +# Copyright (C) 2010 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a common command line parser to be sourced by other SST scripts + +set -u + +WSREP_SST_OPT_BYPASS=0 + +while [ $# -gt 0 ]; do +case "$1" in + '--address') + readonly WSREP_SST_OPT_ADDR="$2" + shift + ;; + '--auth') + readonly WSREP_SST_OPT_AUTH="$2" + shift + ;; + '--bypass') + WSREP_SST_OPT_BYPASS=1 + ;; + '--datadir') + readonly WSREP_SST_OPT_DATA="$2" + shift + ;; + '--defaults-file') + readonly WSREP_SST_OPT_CONF="$2" + shift + ;; + '--host') + readonly WSREP_SST_OPT_HOST="$2" + shift + ;; + '--local-port') + readonly WSREP_SST_OPT_LPORT="$2" + shift + ;; + '--parent') + readonly WSREP_SST_OPT_PARENT="$2" + shift + ;; + '--password') + readonly WSREP_SST_OPT_PSWD="$2" + shift + ;; + '--port') + readonly WSREP_SST_OPT_PORT="$2" + shift + ;; + '--role') + readonly WSREP_SST_OPT_ROLE="$2" + shift + ;; + '--socket') + readonly WSREP_SST_OPT_SOCKET="$2" + shift + ;; + '--user') + readonly WSREP_SST_OPT_USER="$2" + shift + ;; + '--gtid') + readonly WSREP_SST_OPT_GTID="$2" + shift + ;; + *) # must be command + # usage + # exit 1 + ;; +esac +shift +done +readonly WSREP_SST_OPT_BYPASS + +wsrep_log() +{ + # echo everything to stderr so that it gets into common error log + # deliberately made to look different from the rest of the log + local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" + echo "WSREP_SST: $* ($tst)" >>/dev/stderr +} + +wsrep_log_error() +{ + wsrep_log "[ERROR] $*" +} + +wsrep_log_info() +{ + wsrep_log "[INFO] $*" +} + diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh new file mode 100644 index 00000000000..120533edc4e --- /dev/null +++ b/scripts/wsrep_sst_mysqldump.sh @@ -0,0 +1,121 @@ +#!/bin/sh -e +# Copyright (C) 2009 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for mysqldump-based state snapshot tansfer + +. $(dirname $0)/wsrep_sst_common + +EINVAL=22 + +local_ip() +{ + PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin + + [ "$1" = "127.0.0.1" ] && return 0 + [ "$1" = "localhost" ] && return 0 + [ "$1" = "$(hostname -s)" ] && return 0 + [ "$1" = "$(hostname -f)" ] && return 0 + [ "$1" = "$(hostname -d)" ] && return 0 + + # Now if ip program is not found in the path, we can't return 0 since + # it would block any address. Thankfully grep should fail in this case + ip route get "$1" | grep local >/dev/null && return 0 + + return 1 +} + +if test -z "$WSREP_SST_OPT_USER"; then err "USER cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_LPORT"; then err "LPORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_SOCKET";then err "SOCKET cannot be nil";exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_GTID"; then err "GTID cannot be nil"; exit $EINVAL; fi + +if local_ip $WSREP_SST_OPT_HOST && \ + [ "$WSREP_SST_OPT_PORT" = "$WSREP_SST_OPT_LPORT" ] +then + wsrep_log_error \ + "destination address '$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT' matches source address." + exit $EINVAL +fi + +# Check client version +if ! mysql --version | grep 'Distrib 5.5' >/dev/null +then + mysql --version >&2 + err "this operation requires MySQL client version 5.5.x" + exit $EINVAL +fi + +AUTH="-u$WSREP_SST_OPT_USER" +if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi + +STOP_WSREP="SET wsrep_on=OFF;" + +# NOTE: we don't use --routines here because we're dumping mysql.proc table +MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ +--add-drop-database --add-drop-table --skip-add-locks --create-options \ +--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ +--skip-comments --flush-privileges --all-databases" + +# mysqldump cannot restore CSV tables, fix this issue +CSV_TABLES_FIX=" +set sql_mode=''; + +USE mysql; + +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, thread_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, command_type VARCHAR(64) NOT NULL,argument MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"General log\"', 'SET @dummy = 0'); + +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt; + +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER UNSIGNED NOT NULL, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment=\"Slow log\"', 'SET @dummy = 0'); + +PREPARE stmt FROM @str; +EXECUTE stmt; +DROP PREPARE stmt;" + +SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" + +MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ +"--disable-reconnect --connect_timeout=10" + +# need to disable logging when loading the dump +# reason is that dump contains ALTER TABLE for log tables, and +# this causes an error if logging is enabled +GENERAL_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@GENERAL_LOG"` +SLOW_LOG_OPT=`$MYSQL --skip-column-names -e"$STOP_WSREP SELECT @@SLOW_QUERY_LOG"` +$MYSQL -e"$STOP_WSREP SET GLOBAL GENERAL_LOG=OFF" +$MYSQL -e"$STOP_WSREP SET GLOBAL SLOW_QUERY_LOG=OFF" + +# commands to restore log settings +RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" +RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" + +if [ $WSREP_SST_OPT_BYPASS -eq 0 ] +then + (echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX \ + && echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG \ + && echo $SET_START_POSITION \ + || echo "SST failed to complete;") | $MYSQL +else + wsrep_log_info "Bypassing state dump." + echo $SET_START_POSITION | $MYSQL +fi + +# diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh new file mode 100644 index 00000000000..d346eb240f2 --- /dev/null +++ b/scripts/wsrep_sst_rsync.sh @@ -0,0 +1,210 @@ +#!/bin/bash -ue + +# Copyright (C) 2010 Codership Oy +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for rsync-based state snapshot tansfer + +RSYNC_PID= +RSYNC_CONF= + +. $(dirname $0)/wsrep_sst_common + +cleanup_joiner() +{ + wsrep_log_info "Joiner cleanup." + local PID=$(cat "$RSYNC_PID" 2>/dev/null || echo 0) + [ "0" != "$PID" ] && kill $PID && sleep 0.5 && kill -9 $PID >/dev/null 2>&1 \ + || : + rm -rf "$RSYNC_CONF" + rm -rf "$MAGIC_FILE" + rm -rf "$RSYNC_PID" + echo " done." >&2 +} + +check_pid() +{ + local pid_file=$1 + [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 +} + +check_pid_and_port() +{ + local pid_file=$1 + local rsync_pid=$(cat $pid_file) + local rsync_port=$2 + + check_pid $pid_file && \ + netstat -anpt 2>/dev/null | \ + grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null +} + +MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" +rm -rf "$MAGIC_FILE" + +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] +then + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + + FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" + rm -rf "$FLUSHED" + + # Use deltaxfer only for WAN + inv=$(basename $0) + [ "$inv" = "wsrep_sst_rsync_wan" ] && WHOLE_FILE_OPT="" \ + || WHOLE_FILE_OPT="--whole-file" + + echo "flush tables" + + # wait for tables flushed and state ID written to the file + while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1 + do + sleep 0.2 + done + + STATE="$(cat $FLUSHED)" + rm -rf "$FLUSHED" + + sync + + # Old filter - include everything except selected + # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ + # --exclude '*.conf' --exclude core --exclude 'galera.*' \ + # --exclude grastate.txt --exclude '*.pem' \ + # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') + + # New filter - exclude everything except dirs (schemas) and innodb files + FILTER=(-f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') + + RC=0 + rsync --archive --no-times --ignore-times --inplace --delete --quiet \ + $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA" \ + rsync://$WSREP_SST_OPT_ADDR || RC=$? + + [ $RC -ne 0 ] && echo "rsync returned code $RC:" >> /dev/stderr + + case $RC in + 0) RC=0 # Success + ;; + 12) RC=71 # EPROTO + wsrep_log_error \ + "rsync server on the other end has incompatible protocol. " \ + "Make sure you have the same version of rsync on all nodes." + ;; + 22) RC=12 # ENOMEM + ;; + *) RC=255 # unknown error + ;; + esac + + [ $RC -ne 0 ] && exit $RC + + else # BYPASS + wsrep_log_info "Bypassing state dump." + STATE="$WSREP_SST_OPT_GTID" + fi + + echo "continue" # now server can resume updating data + + echo "$STATE" > "$MAGIC_FILE" + rsync -aqc "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR + + echo "done $STATE" + +elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ] +then + MYSQLD_PID=$WSREP_SST_OPT_PARENT + + MODULE="rsync_sst" + + RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" + + if check_pid $RSYNC_PID + then + echo "rsync daemon already running." + exit 114 # EALREADY + fi + rm -rf "$RSYNC_PID" + + ADDR=$WSREP_SST_OPT_ADDR + RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }') + if [ -z "$RSYNC_PORT" ] + then + RSYNC_PORT=4444 + ADDR="$(echo $ADDR | awk -F ':' '{ print $1 }'):$RSYNC_PORT" + fi + + trap "exit 32" HUP PIPE + trap "exit 3" INT TERM + trap cleanup_joiner EXIT + + MYUID=$(id -u) + MYGID=$(id -g) + RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" + +cat << EOF > "$RSYNC_CONF" +pid file = $RSYNC_PID +use chroot = no +[$MODULE] + path = $WSREP_SST_OPT_DATA + read only = no + timeout = 300 + uid = $MYUID + gid = $MYGID +EOF + +# rm -rf "$DATA"/ib_logfile* # we don't want old logs around + + # listen at all interfaces (for firewalled setups) + rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF" + + until check_pid_and_port $RSYNC_PID $RSYNC_PORT + do + sleep 0.2 + done + + echo "ready $ADDR/$MODULE" + + # wait for SST to complete by monitoring magic file + while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \ + ps -p $MYSQLD_PID >/dev/null + do + sleep 1 + done + + if ! ps -p $MYSQLD_PID >/dev/null + then + echo "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." >&2 + exit 32 + fi + + if [ -r "$MAGIC_FILE" ] + then + cat "$MAGIC_FILE" # output UUID:seqno + else + # this message should cause joiner to abort + echo "rsync process ended without creating '$MAGIC_FILE'" + fi + +# cleanup_joiner +else + echo "Unrecognized role: '$WSREP_SST_OPT_ROLE'" + exit 22 # EINVAL +fi + +exit 0 diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh new file mode 100644 index 00000000000..dd8532d6485 --- /dev/null +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -0,0 +1,222 @@ +#!/bin/bash -ue + +# Copyright (C) 2011 Percona Inc +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# This is a reference script for Percona XtraBackup-based state snapshot tansfer + +TMPDIR="/tmp" + +. $(dirname $0)/wsrep_sst_common + +cleanup_joiner() +{ +#set -x + local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') + wsrep_log_info "Killing nc pid $PID" + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$MAGIC_FILE" +#set +x +} + +check_pid() +{ + local pid_file=$1 + [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 +} + +kill_xtrabackup() +{ +#set -x + local PID=$(cat $XTRABACKUP_PID) + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$XTRABACKUP_PID" +#set +x +} + +# waits ~10 seconds for nc to open the port and then reports ready +# (regardless of timeout) +wait_for_nc() +{ + local PORT=$1 + local ADDR=$2 + local MODULE=$3 + for i in $(seq 1 50) + do + netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \ + sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break + sleep 0.2 + done + echo "ready ${ADDR}/${MODULE}" +} + +INNOBACKUPEX_BIN=innobackupex +INNOBACKUPEX_ARGS="" +NC_BIN=nc + +for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do + if ! which ${!TOOL_BIN} > /dev/null 2>&1 + then + echo "Can't find ${!TOOL_BIN} in the path" + exit 22 # EINVAL + fi +done + +#ROLE=$1 +#ADDR=$2 +readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) +readonly DATA="${WSREP_SST_OPT_DATA}" +#CONF=$5 + +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" + +MAGIC_FILE="${DATA}/${INFO_FILE}" +rm -f "${MAGIC_FILE}" + +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] +then + +# UUID=$6 +# SEQNO=$7 +# BYPASS=$8 + + NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') + REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + + INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar + --defaults-file=${WSREP_SST_OPT_CONF} + --socket=${WSREP_SST_OPT_SOCKET}" + + if [ "${AUTH[0]}" != "(null)" ]; then + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}" + fi + + if [ ${#AUTH[*]} -eq 2 ]; then + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" + fi + + set +e + + # This file and variable seems to have no effect and probably should be deleted + XTRABACKUP_PID=$(mktemp --tmpdir wsrep_sst_xtrabackupXXXX.pid) + + ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ + 2> ${DATA}/innobackup.backup.log | \ + ${NC_BIN} ${REMOTEIP} ${NC_PORT} + + RC=( "${PIPESTATUS[@]}" ) + set -e + + if [ ${RC[0]} -ne 0 ]; then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ + "Check ${DATA}/innobackup.backup.log" + exit 22 + elif [ ${RC[1]} -ne 0 ]; then + wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}" + exit 22 + fi + + if check_pid ${XTRABACKUP_PID} + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + exit 22 + fi + + rm -f ${XTRABACKUP_PID} + + else # BYPASS + STATE="${WSREP_SST_OPT_GTID}" + echo "continue" # now server can resume updating data + echo "${STATE}" > "${MAGIC_FILE}" + echo "1" > "${DATA}/${IST_FILE}" + (cd ${DATA}; tar cf - ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + rm -f ${DATA}/${IST_FILE} + fi + + echo "done ${WSREP_SST_OPT_GTID}" + +elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] +then + MODULE="xtrabackup_sst" + + rm -f ${DATA}/xtrabackup_* + + ADDR=${WSREP_SST_OPT_ADDR} + NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }') + if [ -z "${NC_PORT}" ] + then + NC_PORT=4444 + ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}" + fi + + wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & + +# trap "exit 32" HUP PIPE +# trap "exit 3" INT TERM + trap cleanup_joiner HUP PIPE INT TERM + + set +e + ${NC_BIN} -dl ${NC_PORT} | tar xfi - -C ${DATA} 1>&2 + RC=( "${PIPESTATUS[@]}" ) + set -e + + wait %% # join wait_for_nc thread + + if [ ${RC[0]} -ne 0 -o ${RC[1]} -ne 0 ]; + then + wsrep_log_error "Error while getting st data from donor node: " \ + "${RC[0]}, ${RC[1]}" + exit 32 + fi + + if [ ! -r "${MAGIC_FILE}" ] + then + # this message should cause joiner to abort + wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" + exit 32 + fi + + if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null + then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." >&2 + exit 32 + fi + + if [ ! -r "${IST_FILE}" ] + then + rm -f ${DATA}/ib_logfile* + ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \ + --ibbackup=xtrabackup ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log + if [ $? -ne 0 ]; + then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" >&2 + exit 22 + fi + fi + + cat "${MAGIC_FILE}" # output UUID:seqno + +else + wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}" + exit 22 # EINVAL +fi + +exit 0 diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc new file mode 100644 index 00000000000..5764be39093 --- /dev/null +++ b/sql/wsrep_check_opts.cc @@ -0,0 +1,392 @@ +/* Copyright 2011 Codership Oy + + 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 +#include +//#include +//#include + +#include "wsrep_mysqld.h" + +#include +#include +#include +#include + +/* This file is about checking for correctness of mysql configuration options */ + +struct opt +{ + const char* const name; + const char* value; +}; + +/* A list of options to check. + * At first we assume default values and then see if they are changed on CLI or + * in my.cnf */ +static struct opt opts[] = +{ + { "wsrep_slave_threads", "1" }, // mysqld.cc + { "bind_address", "0.0.0.0" }, // mysqld.cc + { "wsrep_sst_method","mysqldump" }, // mysqld.cc + { "wsrep_sst_receive_address","AUTO"}, // mysqld.cc + { "binlog_format", "ROW" }, // mysqld.cc + { "wsrep_provider", "none" }, // mysqld.cc + { "query_cache_type", "0" }, // mysqld.cc + { "query_cache_size", "0" }, // mysqld.cc + { "locked_in_memory", "0" }, // mysqld.cc + { "wsrep_cluster_address", "0" }, // mysqld.cc + { "locks_unsafe_for_binlog", "0" }, // ha_innodb.cc + { "autoinc_lock_mode", "1" }, // ha_innodb.cc + { 0, 0 } +}; + +enum +{ + WSREP_SLAVE_THREADS, + BIND_ADDRESS, + WSREP_SST_METHOD, + WSREP_SST_RECEIVE_ADDRESS, + BINLOG_FORMAT, + WSREP_PROVIDER, + QUERY_CACHE_TYPE, + QUERY_CACHE_SIZE, + LOCKED_IN_MEMORY, + WSREP_CLUSTER_ADDRESS, + LOCKS_UNSAFE_FOR_BINLOG, + AUTOINC_LOCK_MODE +}; + + +/* A class to make a copy of argv[] vector */ +struct argv_copy +{ + int const argc_; + char** argv_; + + argv_copy (int const argc, const char* const argv[]) : + argc_ (argc), + argv_ (reinterpret_cast(calloc(argc_, sizeof(char*)))) + { + if (argv_) + { + for (int i = 0; i < argc_; ++i) + { + argv_[i] = strdup(argv[i]); + + if (!argv_[i]) + { + argv_free (); // free whatever bee allocated + return; + } + } + } + } + + ~argv_copy () { argv_free (); } + +private: + argv_copy (const argv_copy&); + argv_copy& operator= (const argv_copy&); + + void argv_free() + { + if (argv_) + { + for (int i = 0; (i < argc_) && argv_[i] ; ++i) free (argv_[i]); + free (argv_); + argv_ = 0; + } + } +}; + +/* a short corresponding to '--' byte sequence */ +static short const long_opt_prefix ('-' + ('-' << 8)); + +/* Normalizes long options to have '_' instead of '-' */ +static int +normalize_opts (argv_copy& a) +{ + if (a.argv_) + { + for (int i = 0; i < a.argc_; ++i) + { + char* ptr = a.argv_[i]; + if (long_opt_prefix == *(short*)ptr) // long option + { + ptr += 2; + const char* end = strchr(ptr, '='); + + if (!end) end = ptr + strlen(ptr); + + for (; ptr != end; ++ptr) if ('-' == *ptr) *ptr = '_'; + } + } + + return 0; + } + + return EINVAL; +} + +/* Find required options in the argument list and change their values */ +static int +find_opts (argv_copy& a, struct opt* const opts) +{ + for (int i = 0; i < a.argc_; ++i) + { + char* ptr = a.argv_[i] + 2; // we're interested only in long options + + struct opt* opt = opts; + for (; 0 != opt->name; ++opt) + { + if (!strstr(ptr, opt->name)) continue; // try next option + + /* 1. try to find value after the '=' */ + opt->value = strchr(ptr, '=') + 1; + + /* 2. if no '=', try next element in the argument vector */ + if (reinterpret_cast(1) == opt->value) + { + /* also check that the next element is not an option itself */ + if (i + 1 < a.argc_ && *(a.argv_[i + 1]) != '-') + { + ++i; + opt->value = a.argv_[i]; + } + else opt->value = ""; // no value supplied (like boolean opt) + } + + break; // option found, break inner loop + } + } + + return 0; +} + +/* Parses string for an integer. Returns 0 on success. */ +int get_long_long (const struct opt& opt, long long* const val, int const base) +{ + const char* const str = opt.value; + + if ('\0' != *str) + { + char* endptr; + + *val = strtoll (str, &endptr, base); + + if ('k' == *endptr || 'K' == *endptr) + { + *val *= 1024L; + endptr++; + } + else if ('m' == *endptr || 'M' == *endptr) + { + *val *= 1024L * 1024L; + endptr++; + } + else if ('g' == *endptr || 'G' == *endptr) + { + *val *= 1024L * 1024L * 1024L; + endptr++; + } + + if ('\0' == *endptr) return 0; // the whole string was a valid integer + } + + WSREP_ERROR ("Bad value for *%s: '%s'. Should be integer.", + opt.name, opt.value); + + return EINVAL; +} + +/* This is flimzy coz hell knows how mysql interprets boolean strings... + * and, no, I'm not going to become versed in how mysql handles options - + * I'd rather sing. + + Aha, http://dev.mysql.com/doc/refman/5.1/en/dynamic-system-variables.html: + Variables that have a type of “boolean†can be set to 0, 1, ON or OFF. (If you + set them on the command line or in an option file, use the numeric values.) + + So it is '0' for FALSE, '1' or empty string for TRUE + + */ +int get_bool (const struct opt& opt, bool* const val) +{ + const char* str = opt.value; + + while (isspace(*str)) ++str; // skip initial whitespaces + + ssize_t str_len = strlen(str); + switch (str_len) + { + case 0: + *val = true; + return 0; + case 1: + if ('0' == *str || '1' == *str) + { + *val = ('1' == *str); + return 0; + } + } + + WSREP_ERROR ("Bad value for *%s: '%s'. Should be '0', '1' or empty string.", + opt.name, opt.value); + + return EINVAL; +} + +static int +check_opts (int const argc, const char* const argv[], struct opt opts[]) +{ + /* First, make a copy of argv to be able to manipulate it */ + argv_copy a(argc, argv); + + if (!a.argv_) + { + WSREP_ERROR ("Could not copy argv vector: not enough memory."); + return ENOMEM; + } + + int err = normalize_opts (a); + if (err) + { + WSREP_ERROR ("Failed to normalize options."); + return err; + } + + err = find_opts (a, opts); + if (err) + { + WSREP_ERROR ("Failed to parse options."); + return err; + } + + /* At this point we have updated default values in our option list to + what has been specified on the command line / my.cnf */ + + long long slave_threads; + err = get_long_long (opts[WSREP_SLAVE_THREADS], &slave_threads, 10); + if (err) return err; + + int rcode = 0; + + if (slave_threads > 1) + /* Need to check AUTOINC_LOCK_MODE and LOCKS_UNSAFE_FOR_BINLOG */ + { + long long autoinc_lock_mode; + err = get_long_long (opts[AUTOINC_LOCK_MODE], &autoinc_lock_mode, 10); + if (err) return err; + + bool locks_unsafe_for_binlog; + err = get_bool (opts[LOCKS_UNSAFE_FOR_BINLOG],&locks_unsafe_for_binlog); + if (err) return err; + + if (autoinc_lock_mode != 2) + { + WSREP_ERROR ("Parallel applying (wsrep_slave_threads > 1) requires" + " innodb_autoinc_lock_mode = 2."); + rcode = EINVAL; + } + } + + long long query_cache_size, query_cache_type; + if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10))) + return err; + if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10))) + return err; + + if (0 != query_cache_size && 0 != query_cache_type) + { + WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)", + query_cache_size, query_cache_type); + rcode = EINVAL; + } + + bool locked_in_memory; + err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory); + if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; } + if (locked_in_memory) + { + WSREP_ERROR ("Memory locking is not supported (locked_in_memory=%s)", + locked_in_memory ? "ON" : "OFF"); + rcode = EINVAL; + } + + if (!strcasecmp(opts[WSREP_SST_METHOD].value,"mysqldump")) + { + if (!strcasecmp(opts[BIND_ADDRESS].value, "127.0.0.1") || + !strcasecmp(opts[BIND_ADDRESS].value, "localhost")) + { + WSREP_ERROR ("wsrep_sst_method is set to 'mysqldump' yet " + "mysqld bind_address is set to '%s', which makes it " + "impossible to receive state transfer from another " + "node, since mysqld won't accept such connections. " + "If you wish to use mysqldump state transfer method, " + "set bind_address to allow mysql client connections " + "from other cluster members (e.g. 0.0.0.0).", + opts[BIND_ADDRESS].value); + rcode = EINVAL; + } + } + else + { + // non-mysqldump SST requires wsrep_cluster_address on startup + if (strlen(opts[WSREP_CLUSTER_ADDRESS].value) == 0) + { + WSREP_ERROR ("%s SST method requires wsrep_cluster_address to be " + "configured on startup.",opts[WSREP_SST_METHOD].value); + rcode = EINVAL; + } + } + + if (strcasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, "AUTO")) + { + if (!strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, + "127.0.0.1", strlen("127.0.0.1")) || + !strncasecmp(opts[WSREP_SST_RECEIVE_ADDRESS].value, + "localhost", strlen("localhost"))) + { + WSREP_WARN ("wsrep_sst_receive_address is set to '%s' which " + "makes it impossible for another host to reach this " + "one. Please set it to the address which this node " + "can be connected at by other cluster members.", + opts[WSREP_SST_RECEIVE_ADDRESS].value); +// rcode = EINVAL; + } + } + + if (strcasecmp(opts[WSREP_PROVIDER].value, "none")) + { + if (strcasecmp(opts[BINLOG_FORMAT].value, "ROW")) + { + WSREP_ERROR ("Only binlog_format = 'ROW' is currently supported. " + "Configured value: '%s'. Please adjust your " + "configuration.", opts[BINLOG_FORMAT].value); + + rcode = EINVAL; + } + } + + return rcode; +} + +int +wsrep_check_opts (int const argc, char* const* const argv) +{ + return check_opts (argc, argv, opts); +} + diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc new file mode 100644 index 00000000000..d1be802b286 --- /dev/null +++ b/sql/wsrep_hton.cc @@ -0,0 +1,449 @@ +/* Copyright 2008 Codership Oy + + 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 +#include "sql_base.h" +#include "rpl_filter.h" +#include +#include "wsrep_mysqld.h" +#include "wsrep_priv.h" +#include +#include + +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 + +enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); + +/* + a post-commit cleanup on behalf of wsrep. Can't be a part of hton struct. + Is called by THD::transactions.cleanup() +*/ +void wsrep_cleanup_transaction(THD *thd) +{ + if (thd->thread_id == 0) return; + if (thd->wsrep_exec_mode == LOCAL_COMMIT) + { + if (thd->variables.wsrep_on && + thd->wsrep_conflict_state != MUST_REPLAY) + { + if (thd->wsrep_seqno_changed) + { + if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("set committed fail")); + WSREP_WARN("set committed fail: %llu %d", + (long long)thd->real_id, thd->stmt_da->status()); + } + } + //else + //WSREP_DEBUG("no trx handle for %s", thd->query()); + thd_binlog_trx_reset(thd); + thd->wsrep_seqno_changed = false; + } + thd->wsrep_exec_mode= LOCAL_STATE; + } +} + +/* + wsrep hton +*/ +handlerton *wsrep_hton; + +void wsrep_register_hton(THD* thd, bool all) +{ + THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) + { + if (i->ht()->db_type == DB_TYPE_INNODB) + { + trans_register_ha(thd, all, wsrep_hton); + thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + 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_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_ROLLBACK, 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) +{ +#ifndef DBUG_OFF + //wsrep_seqno_t old = thd->wsrep_trx_seqno; +#endif + DBUG_ENTER("wsrep_prepare"); + if ((all || + !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) + { + switch (wsrep_run_wsrep_commit(thd, hton, all)) + { + case WSREP_TRX_OK: + // DBUG_ASSERT(thd->wsrep_trx_seqno > old || + // thd->wsrep_exec_mode == REPL_RECV || + // thd->wsrep_exec_mode == TOTAL_ORDER); + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + +static int wsrep_savepoint_set(handlerton *hton, THD *thd, void *sv) +{ + if (!wsrep_emulate_bin_log) return 0; + int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); + return rcode; +} +static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) +{ + if (!wsrep_emulate_bin_log) return 0; + int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); + return rcode; +} + +static int wsrep_rollback(handlerton *hton, THD *thd, bool all) +{ + DBUG_ENTER("wsrep_rollback"); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) + { + if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("setting rollback fail")); + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + (long long)thd->real_id, thd->query()); + } + } + + int rcode = 0; + if (!wsrep_emulate_bin_log) + { + if (all) thd_binlog_trx_reset(thd); + } + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(rcode); +} + +int wsrep_commit(handlerton *hton, THD *thd, bool all) +{ + DBUG_ENTER("wsrep_commit"); + + 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, handlerton *hton, bool all) +{ + int rcode = -1; + uint data_len = 0; + uchar *rbr_data = NULL; + IO_CACHE *cache; + int replay_round= 0; + + if (thd->stmt_da->is_error()) { + WSREP_ERROR("commit issue, error: %d %s", + thd->stmt_da->sql_errno(), thd->stmt_da->message()); + } + + DBUG_ENTER("wsrep_run_wsrep_commit"); + 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_wsrep_thd); + 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_wsrep_thd); + // + // 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_wsrep_thd); + } + 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_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + DBUG_PRINT("wsrep", ("replicate commit fail")); + thd->wsrep_conflict_state = ABORTED; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (wsrep_debug) { + WSREP_INFO("innobase_commit, abort %s", + (thd->query()) ? thd->query() : "void"); + } + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } + + mysql_mutex_lock(&LOCK_wsrep_replaying); + + while (wsrep_replaying > 0 && + thd->wsrep_conflict_state == NO_CONFLICT && + thd->killed == THD::NOT_KILLED && + !shutdown_in_progress) + { + + mysql_mutex_unlock(&LOCK_wsrep_replaying); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_mutex_lock(&thd->mysys_var->mutex); + thd_proc_info(thd, "wsrep waiting on replaying"); + thd->mysys_var->current_mutex= &LOCK_wsrep_replaying; + thd->mysys_var->current_cond= &COND_wsrep_replaying; + mysql_mutex_unlock(&thd->mysys_var->mutex); + + mysql_mutex_lock(&LOCK_wsrep_replaying); + // Using timedwait is a hack to avoid deadlock in case if BF victim + // misses the signal. + struct timespec wtime = {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: (%lu) conflict: %d (round: %d)", + wsrep_replaying, 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_wsrep_thd); + 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_wsrep_thd); + WSREP_DEBUG("innobase_commit abort after replaying wait %s", + (thd->query()) ? thd->query() : "void"); + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } + thd->wsrep_query_state = QUERY_COMMITTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + cache = get_trans_log(thd); + rcode = 0; + if (cache) { + thd->binlog_flush_pending_rows_event(true); + rcode = wsrep_write_cache(cache, &rbr_data, &data_len); + if (rcode) { + WSREP_ERROR("rbr write fail, data_len: %d, %d", data_len, rcode); + if (data_len) my_free(rbr_data); + DBUG_RETURN(WSREP_TRX_ROLLBACK); + } + } + if (data_len == 0) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_exec_mode = LOCAL_COMMIT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (thd->stmt_da->is_ok() && + thd->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->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()); + } + DBUG_RETURN(WSREP_TRX_OK); + } + if (!rcode) { + rcode = wsrep->pre_commit( + wsrep, + (wsrep_conn_id_t)thd->thread_id, + &thd->wsrep_trx_handle, + rbr_data, + data_len, + (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, + &thd->wsrep_trx_seqno); + if (rcode == WSREP_TRX_MISSING) { + rcode = WSREP_OK; + } else if (rcode == WSREP_BF_ABORT) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state = MUST_REPLAY; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying++; + WSREP_DEBUG("replaying increased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + thd->wsrep_seqno_changed = true; + } else { + WSREP_ERROR("I/O error reading from thd's binlog iocache: " + "errno=%d, io cache code=%d", my_errno, cache->error); + if (data_len) my_free(rbr_data); + DBUG_ASSERT(0); // failure like this can not normally happen + DBUG_RETURN(WSREP_TRX_ERROR); + } + + if (data_len) { + my_free(rbr_data); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + switch(rcode) { + case 0: + thd->wsrep_exec_mode = LOCAL_COMMIT; + /* 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, + wsrep_cluster_uuid(), + thd->wsrep_trx_seqno); + } + DBUG_PRINT("wsrep", ("replicating commit success")); + + break; + case WSREP_TRX_FAIL: + case WSREP_BF_ABORT: + 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_wsrep_thd); + + DBUG_RETURN(WSREP_TRX_ROLLBACK); + + case WSREP_CONN_FAIL: + WSREP_ERROR("connection failure"); + DBUG_RETURN(WSREP_TRX_ERROR); + default: + WSREP_ERROR("unknown connection failure"); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + thd->wsrep_query_state= QUERY_EXEC; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + 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=DB_TYPE_WSREP; + 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 + wsrep_hton->slot= 0; + return 0; +} + + +struct st_mysql_storage_engine wsrep_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + + +mysql_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 */ + NULL, /* config options */ + 0, /* flags */ +} +mysql_declare_plugin_end; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc new file mode 100644 index 00000000000..c31c02e6d33 --- /dev/null +++ b/sql/wsrep_mysqld.cc @@ -0,0 +1,1281 @@ +/* Copyright 2008 Codership Oy + + 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 +#include +#include +#include "wsrep_priv.h" +#include +#include +#include "log_event.h" + +wsrep_t *wsrep = NULL; +my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface + +/* + * Begin configuration options and their default values + */ + +const char* wsrep_data_home_dir = NULL; + +#define WSREP_NODE_INCOMING_AUTO "AUTO" +const char* wsrep_node_incoming_address = WSREP_NODE_INCOMING_AUTO; +const char* wsrep_dbug_option = ""; + +long wsrep_slave_threads = 1; // # of slave action appliers wanted +my_bool wsrep_debug = 0; // enable debug level logging +my_bool wsrep_convert_LOCK_to_trx = 1; // convert locking sessions to trx +ulong wsrep_retry_autocommit = 5; // retry aborted autocommit trx +my_bool wsrep_auto_increment_control = 1; // control auto increment variables +my_bool wsrep_drupal_282555_workaround = 1; // retry autoinc insert after dupkey +my_bool wsrep_incremental_data_collection = 0; // incremental data collection +long long wsrep_max_ws_size = 1073741824LL; //max ws (RBR buffer) size +long wsrep_max_ws_rows = 65536; // max number of rows in ws +int wsrep_to_isolation = 0; // # of active TO isolation threads +my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key +long wsrep_max_protocol_version = 2; // maximum protocol version to use +ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; +my_bool wsrep_recovery = 0; // recovery +my_bool wsrep_replicate_myisam = 0; // enable myisam replication +my_bool wsrep_log_conflicts = 0; // +ulong wsrep_mysql_replication_bundle = 0; + +/* + * End configuration options + */ + +static const wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; +const wsrep_uuid_t* wsrep_cluster_uuid() +{ + return &cluster_uuid; +} +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 + */ +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; +const char* wsrep_provider_name = provider_name; +const char* wsrep_provider_version = provider_version; +const char* wsrep_provider_vendor = provider_vendor; +/* End wsrep status variables */ + + +wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; +wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; +wsp::node_status local_status; +long wsrep_protocol_version = 2; + +// action execute callback +extern wsrep_status_t wsrep_apply_cb(void *ctx, + const void* buf, size_t buf_len, + wsrep_seqno_t global_seqno); + +extern wsrep_status_t wsrep_commit_cb (void *ctx, + wsrep_seqno_t global_seqno, + bool commit); + +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: + sql_print_error("WSREP: %s", msg); + break; + case WSREP_LOG_DEBUG: + if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); + default: + break; + } +} + +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); +} + +static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= reinterpret_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + if (hton->db_type == DB_TYPE_INNODB) + { + const wsrep_uuid_t* uuid(wsrep_xid_uuid(xid)); + char uuid_str[40] = {0, }; + wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(xid)); + hton->wsrep_set_checkpoint(hton, xid); + } + return FALSE; +} + +void wsrep_set_SE_checkpoint(XID* xid) +{ + plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); +} + +static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= reinterpret_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + if (hton->db_type == DB_TYPE_INNODB) + { + hton->wsrep_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_DEBUG("Read WSREPXid from InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(xid)); + + } + return FALSE; +} + +void wsrep_get_SE_checkpoint(XID* xid) +{ + plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); +} + +static void 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, + ssize_t* sst_req_len) +{ + wsrep_member_status_t new_status= local_status.get(); + + if (memcmp(&cluster_uuid, &view->uuid, sizeof(wsrep_uuid_t))) + { + memcpy((wsrep_uuid_t*)&cluster_uuid, &view->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->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) { + wsrep_ready_set(FALSE); + new_status= WSREP_MEMBER_UNDEFINED; + /* Always record local_uuid and local_seqno in non-prim since this + * may lead to re-initializing provider and start position is + * determined according to these variables */ + // 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; + } + + switch (view->proto_ver) + { + case 0: + case 1: + case 2: + // version change + if (view->proto_ver != wsrep_protocol_version) + { + my_bool wsrep_ready_saved= wsrep_ready; + 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 */ + WSREP_DEBUG("[debug]: closing client connections for PRIM"); + wsrep_close_client_connections(TRUE); + + *sst_req_len= wsrep_sst_prepare (sst_req); + + if (*sst_req_len < 0) + { + int err = *sst_req_len; + WSREP_ERROR("SST preparation failed: %d (%s)", -err, strerror(-err)); + new_status= WSREP_MEMBER_UNDEFINED; + } + else + { + new_status= WSREP_MEMBER_JOINER; + } + } + else + { + /* + * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized + * before - OR - it was reinitilized on startup (lp:992840) + */ + if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) || + 0 == wsrep_cluster_conf_id) + { + if (wsrep_init_first()) + { + wsrep_SE_init_grab(); + // Signal init thread to continue + wsrep_sst_complete (&cluster_uuid, view->seqno, false); + // and wait for SE initialization + wsrep_SE_init_wait(); + } + else + { + local_uuid= cluster_uuid; + local_seqno= view->seqno; + } + /* Init storage engine XIDs from first view */ + XID xid; + wsrep_xid_init(&xid, &local_uuid, local_seqno); + wsrep_set_SE_checkpoint(&xid); + new_status= WSREP_MEMBER_JOINED; + } + else // 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->seqno, + &local_uuid, -1); + abort(); + } + } + } + + if (wsrep_auto_increment_control) + { + global_system_variables.auto_increment_offset= view->my_idx + 1; + global_system_variables.auto_increment_increment= view->memb_num; + } + +out: + + local_status.set(new_status, view); +} + +void wsrep_ready_set (my_bool x) +{ + WSREP_DEBUG("Setting wsrep_ready to %d", x); + if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); + if (wsrep_ready != x) + { + wsrep_ready= x; + mysql_cond_signal (&COND_wsrep_ready); + } + mysql_mutex_unlock (&LOCK_wsrep_ready); +} + +// Wait until wsrep has reached ready state +void wsrep_ready_wait () +{ + 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); +} + +static void wsrep_synced_cb(void* app_ctx) +{ + WSREP_INFO("Synchronized with group, ready for connections"); + if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); + if (!wsrep_ready) + { + wsrep_ready= TRUE; + mysql_cond_signal (&COND_wsrep_ready); + } + local_status.set(WSREP_MEMBER_SYNCED); + mysql_mutex_unlock (&LOCK_wsrep_ready); +} + +static void wsrep_init_position() +{ + /* read XIDs from storage engines */ + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + wsrep_get_SE_checkpoint(&xid); + + if (xid.formatID == -1) + { + WSREP_INFO("Read nil XID from storage engines, skipping position init"); + return; + } + else if (!wsrep_is_wsrep_xid(&xid)) + { + WSREP_WARN("Read non-wsrep XID from storage engines, skipping position init"); + return; + } + + const wsrep_uuid_t* uuid= wsrep_xid_uuid(&xid); + const wsrep_seqno_t seqno= wsrep_xid_seqno(&xid); + + 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"); + } +} + + +int wsrep_init() +{ + int rcode= -1; + + 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 + (void) wsrep_init(); + return rcode; + } + 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); + } + } + + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) + { + // enable normal operation in case no provider is specified + wsrep_ready_set(TRUE); + global_system_variables.wsrep_on = 0; + return 0; + } + 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); + } + + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + wsrep_data_home_dir = mysql_real_data_home; + + char node_addr[512]= { 0, }; + if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) + { + size_t const node_addr_max= sizeof(node_addr); + size_t const ret= guess_ip(node_addr, node_addr_max); + if (!(ret > 0 && ret < node_addr_max)) + { + WSREP_WARN("Failed to guess base node address. Set it explicitly via " + "wsrep_node_address."); + node_addr[0]= '\0'; + } + } + else + { + strncpy(node_addr, wsrep_node_address, sizeof(node_addr) - 1); + } + + static char inc_addr[512]= { 0, }; + if ((!wsrep_node_incoming_address || + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + size_t const node_addr_len= strlen(node_addr); + if (node_addr_len > 0) + { + const char* const colon= strrchr(node_addr, ':'); + if (strchr(node_addr, ':') == colon) // 1 or 0 ':' + { + size_t const inc_addr_max= sizeof (inc_addr); + size_t const ip_len= colon ? colon - node_addr : node_addr_len; + if (ip_len + 7 /* :55555\0 */ < inc_addr_max) + { + memcpy (inc_addr, node_addr, ip_len); + snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",mysqld_port); + } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "address too long."); + inc_addr[0]= '\0'; + } + } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "too many colons :) ."); + inc_addr[0]= '\0'; + } + } + + // this is to display detected address on SHOW VARIABLES... + wsrep_node_incoming_address = inc_addr; + + if (!strlen(wsrep_node_incoming_address)) + { + WSREP_WARN("Guessing address for incoming client connections failed. " + "Try setting wsrep_node_incoming_address explicitly."); + } + } + + struct wsrep_init_args wsrep_args; + + 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 = wsrep_node_incoming_address; + wsrep_args.options = (wsrep_provider_options) ? + wsrep_provider_options : ""; + wsrep_args.proto_ver = wsrep_max_protocol_version; + + wsrep_args.state_uuid = &local_uuid; + wsrep_args.state_seqno = local_seqno; + + 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.sst_donate_cb = wsrep_sst_donate_cb; + wsrep_args.synced_cb = wsrep_synced_cb; + + rcode = wsrep->init(wsrep, &wsrep_args); + + if (rcode) + { + DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); + WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); + free(wsrep); + wsrep = NULL; + } + + return rcode; +} + +extern "C" int wsrep_on(void *); + +void wsrep_init_startup (bool first) +{ + if (wsrep_init()) unireg_abort(1); + + wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd, + wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); + + /* Skip replication start if no cluster address */ + if (!wsrep_cluster_address || strlen(wsrep_cluster_address) == 0) return; + + if (first) wsrep_sst_grab(); // do it so we can wait for SST below + + 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 +} + + +void wsrep_deinit() +{ + wsrep_unload(wsrep); + wsrep= 0; + provider_name[0]= '\0'; + provider_version[0]= '\0'; + provider_vendor[0]= '\0'; +} + +void wsrep_recover() +{ + if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) && + local_seqno == -2) + { + char uuid_str[40]; + wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str)); + WSREP_INFO("Position %s:%lld given at startup, skipping position recovery", + uuid_str, (long long)local_seqno); + return; + } + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + wsrep_get_SE_checkpoint(&xid); + char uuid_str[40]; + wsrep_uuid_print(wsrep_xid_uuid(&xid), uuid_str, sizeof(uuid_str)); + WSREP_INFO("Recovered position: %s:%lld", uuid_str, + (long long)wsrep_xid_seqno(&xid)); +} + + +void wsrep_stop_replication(THD *thd) +{ + WSREP_INFO("Stop replication"); + if (!wsrep) + { + WSREP_INFO("Provider was not loaded, in stop replication"); + return; + } + + /* disconnect from group first to get wsrep_ready == FALSE */ + WSREP_DEBUG("Provider disconnect"); + wsrep->disconnect(wsrep); + + wsrep_connected= FALSE; + + wsrep_close_client_connections(TRUE); + + /* wait until appliers have stopped */ + wsrep_wait_appliers_close(thd); + + return; +} + + +bool wsrep_start_replication() +{ + wsrep_status_t rcode; + + /* + if provider is trivial, don't even try to connect, + but resume local node operation + */ + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) + { + // enable normal operation in case no provider is specified + wsrep_ready_set(TRUE); + return true; + } + + if (!wsrep_cluster_address || strlen(wsrep_cluster_address)== 0) + { + // if provider is non-trivial, but no address is specified, wait for address + wsrep_ready_set(FALSE); + return true; + } + + WSREP_INFO("Start replication"); + + if ((rcode = wsrep->connect(wsrep, + wsrep_cluster_name, + wsrep_cluster_address, + wsrep_sst_donor))) + { + if (-ESOCKTNOSUPPORT == rcode) + { + DBUG_PRINT("wsrep",("unrecognized cluster address: '%s', rcode: %d", + wsrep_cluster_address, rcode)); + WSREP_ERROR("unrecognized cluster address: '%s', rcode: %d", + wsrep_cluster_address, rcode); + } + else + { + DBUG_PRINT("wsrep",("wsrep->connect() failed: %d", rcode)); + WSREP_ERROR("wsrep::connect() failed: %d", rcode); + } + + return false; + } + else + { + wsrep_connected= TRUE; + + uint64_t caps = wsrep->capabilities (wsrep); + + wsrep_incremental_data_collection = + (caps & WSREP_CAP_WRITE_SET_INCREMENTS); + + char* opts= wsrep->options_get(wsrep); + if (opts) + { + wsrep_provider_options_init(opts); + free(opts); + } + else + { + WSREP_WARN("Failed to get wsrep options"); + } + } + + return true; +} + +bool +wsrep_causal_wait (THD* thd) +{ + if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on && + !thd->in_active_multi_stmt_transaction() && + thd->wsrep_conflict_state != REPLAYING) + { + // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 + // TODO: modify to check if thd has locked any rows. + wsrep_seqno_t seqno; + wsrep_status_t ret= wsrep->causal_read (wsrep, &seqno); + + if (unlikely(WSREP_OK != ret)) + { + 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 + + switch (ret) + { + case WSREP_NOT_IMPLEMENTED: + msg= "consistent reads by wsrep backend. " + "Please unset wsrep_causal_reads variable."; + err= ER_NOT_SUPPORTED_YET; + break; + default: + msg= "Causal wait failed."; + err= ER_LOCK_WAIT_TIMEOUT; // NOTE: the above msg won't be displayed + // with ER_LOCK_WAIT_TIMEOUT + } + + my_error(err, MYF(0), msg); + + return true; + } + } + + return false; +} + +/* + * Helpers to deal with TOI key arrays + */ +typedef struct wsrep_key_arr +{ + wsrep_key_t* keys; + size_t keys_len; +} wsrep_key_arr_t; + + +static void wsrep_keys_free(wsrep_key_arr_t* key_arr) +{ + for (size_t i= 0; i < key_arr->keys_len; ++i) + { + my_free((wsrep_key_part_t*)key_arr->keys[i].key_parts); + } + my_free(key_arr->keys); + key_arr->keys= 0; + key_arr->keys_len= 0; +} + + +/*! + * @param db Database string + * @param table Table string + * @param key Array of wsrep_key_t + * @param key_len In: number of elements in key array, Out: number of + * elements populated + * + * @return true if preparation was successful, otherwise false. + */ + +static bool wsrep_prepare_key_for_isolation(const char* db, + const char* table, + wsrep_key_part_t* key, + size_t* key_len) +{ + if (*key_len < 2) return false; + + switch (wsrep_protocol_version) + { + case 0: + *key_len= 0; + break; + case 1: + case 2: + { + *key_len= 0; + if (db) + { + // sql_print_information("%s.%s", db, table); + if (db) + { + key[*key_len].buf= db; + key[*key_len].buf_len= strlen(db); + ++(*key_len); + if (table) + { + key[*key_len].buf= table; + key[*key_len].buf_len= strlen(table); + ++(*key_len); + } + } + } + break; + } + default: + return false; + } + + return true; +} + +/* Prepare key list from db/table and table_list */ +static bool wsrep_prepare_keys_for_isolation(THD* thd, + const char* db, + const char* table, + const TABLE_LIST* table_list, + wsrep_key_arr_t* ka) +{ + ka->keys= 0; + ka->keys_len= 0; + + extern TABLE* find_temporary_table(THD*, const TABLE_LIST*); + + if (db || table) + { + TABLE_LIST tmp_table; + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.table_name= (char*)db; + tmp_table.db= (char*)table; + if (!table || !find_temporary_table(thd, &tmp_table)) + { + if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0)))) + { + sql_print_error("Can't allocate memory for key_array"); + goto err; + } + ka->keys_len= 1; + if (!(ka->keys[0].key_parts= (wsrep_key_part_t*) + my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + { + sql_print_error("Can't allocate memory for key_parts"); + goto err; + } + ka->keys[0].key_parts_len= 2; + if (!wsrep_prepare_key_for_isolation( + db, table, + (wsrep_key_part_t*)ka->keys[0].key_parts, + &ka->keys[0].key_parts_len)) + { + sql_print_error("Preparing keys for isolation failed"); + goto err; + } + } + } + + for (const TABLE_LIST* table= table_list; table; table= table->next_global) + { + if (!find_temporary_table(thd, table)) + { + wsrep_key_t* tmp; + tmp= (wsrep_key_t*)my_realloc( + ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); + if (!tmp) + { + sql_print_error("Can't allocate memory for key_array"); + goto err; + } + ka->keys= tmp; + if (!(ka->keys[ka->keys_len].key_parts= (wsrep_key_part_t*) + my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + { + sql_print_error("Can't allocate memory for key_parts"); + goto err; + } + ka->keys[ka->keys_len].key_parts_len= 2; + ++ka->keys_len; + if (!wsrep_prepare_key_for_isolation( + table->db, table->table_name, + (wsrep_key_part_t*)ka->keys[ka->keys_len - 1].key_parts, + &ka->keys[ka->keys_len - 1].key_parts_len)) + { + sql_print_error("Preparing keys for isolation failed"); + goto err; + } + } + } + return true; +err: + wsrep_keys_free(ka); + return false; +} + + + +bool wsrep_prepare_key_for_innodb(const uchar* cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len) +{ + if (*key_len < 3) return false; + + *key_len= 0; + switch (wsrep_protocol_version) + { + case 0: + { + key[*key_len].buf = cache_key; + key[*key_len].buf_len = cache_key_len; + ++(*key_len); + break; + } + case 1: + case 2: + { + key[*key_len].buf = cache_key; + key[*key_len].buf_len = strlen( (char*)cache_key ); + ++(*key_len); + key[*key_len].buf = cache_key + strlen( (char*)cache_key ) + 1; + key[*key_len].buf_len = strlen( (char*)(key[*key_len].buf) ); + ++(*key_len); + break; + } + default: + return false; + } + + key[*key_len].buf = row_id; + key[*key_len].buf_len = row_id_len; + ++(*key_len); + + return true; +} + +/* + * Construct Query_log_Event from thd query and serialize it + * into buffer. + * + * Return 0 in case of success, 1 in case of error. + */ +int wsrep_to_buf_helper( + THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len) +{ + IO_CACHE tmp_io_cache; + if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, + 65536, MYF(MY_WME))) + return 1; + Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); + int ret(0); + if (ev.write(&tmp_io_cache)) ret= 1; + if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; + close_cached_file(&tmp_io_cache); + return ret; +} + +#include "sql_show.h" +static int +create_view_query(THD *thd, uchar** buf, uint* buf_len) +{ + LEX *lex= thd->lex; + SELECT_LEX *select_lex= &lex->select_lex; + TABLE_LIST *first_table= select_lex->table_list.first; + TABLE_LIST *views = first_table; + + String buff; + const LEX_STRING command[3]= + {{ C_STRING_WITH_LEN("CREATE ") }, + { C_STRING_WITH_LEN("ALTER ") }, + { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; + + buff.append(command[thd->lex->create_view_mode].str, + command[thd->lex->create_view_mode].length); + + if (!lex->definer) + { + /* + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. + */ + + if (!(lex->definer= create_default_definer(thd))) + { + WSREP_WARN("view default definer issue"); + } + } + + views->algorithm = lex->create_view_algorithm; + views->definer.user = lex->definer->user; + views->definer.host = lex->definer->host; + 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 ")); + /* Test if user supplied a db (ie: we did not use thd->db) */ + if (views->db && views->db[0] && + (thd->db == NULL || strcmp(views->db, thd->db))) + { + append_identifier(thd, &buff, views->db, + views->db_length); + buff.append('.'); + } + append_identifier(thd, &buff, views->table_name, + views->table_name_length); + if (lex->view_list.elements) + { + List_iterator_fast names(lex->view_list); + LEX_STRING *name; + int i; + + for (i= 0; (name= names++); i++) + { + buff.append(i ? ", " : "("); + append_identifier(thd, &buff, name->str, name->length); + } + 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); +} + +static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list) +{ + wsrep_status_t ret(WSREP_WARNING); + uchar* buf(0); + uint buf_len(0); + int buf_err; + + WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + switch (thd->lex->sql_command) + { + case SQLCOM_CREATE_VIEW: + buf_err= create_view_query(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_PROCEDURE: + case SQLCOM_CREATE_SPFUNCTION: + buf_err= wsrep_create_sp(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_TRIGGER: + buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); + break; + case SQLCOM_CREATE_EVENT: + buf_err= wsrep_create_event_query(thd, &buf, &buf_len); + break; + default: + buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, + &buf_len); + break; + } + + wsrep_key_arr_t key_arr= {0, 0}; + if (!buf_err && + wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&& + WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, + key_arr.keys, key_arr.keys_len, + buf, buf_len, + &thd->wsrep_trx_seqno))) + { + thd->wsrep_exec_mode= TOTAL_ORDER; + wsrep_to_isolation++; + if (buf) my_free(buf); + wsrep_keys_free(&key_arr); + WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode); + } + else { + /* jump to error handler in mysql_execute_command() */ + WSREP_WARN("TO isolation failed for: %d, sql: %s. Check wsrep " + "connection state and retry the query.", + ret, (thd->query()) ? thd->query() : "void"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " + "your wsrep connection state and retry the query."); + if (buf) my_free(buf); + wsrep_keys_free(&key_arr); + return -1; + } + return 0; +} + +static void wsrep_TOI_end(THD *thd) { + wsrep_status_t ret; + wsrep_to_isolation--; + WSREP_DEBUG("TO END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void") + if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { + WSREP_DEBUG("TO END: %lld", (long long)thd->wsrep_trx_seqno); + } + else { + WSREP_WARN("TO isolation end failed for: %d, sql: %s", + ret, (thd->query()) ? thd->query() : "void"); + } +} + +static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) +{ + wsrep_status_t ret(WSREP_WARNING); + WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + + ret = wsrep->desync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("RSU desync failed %d for %s", ret, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0)); + return(ret); + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying++; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + if (wsrep_wait_committing_connections_close(5000)) + { + /* no can do, bail out from DDL */ + WSREP_WARN("RSU failed due to pending transactions, %s", thd->query()); + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for %s", ret, thd->query()); + } + my_error(ER_LOCK_DEADLOCK, MYF(0)); + return(1); + } + + wsrep_seqno_t seqno = wsrep->pause(wsrep); + if (seqno == WSREP_SEQNO_UNDEFINED) + { + WSREP_WARN("pause failed %lld for %s", (long long)seqno, thd->query()); + return(1); + } + 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)thd->wsrep_trx_seqno, + thd->wsrep_exec_mode, thd->query() ); + + + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + ret = wsrep->resume(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resume failed %d for %s", ret, thd->query()); + } + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for %s", ret, thd->query()); + return; + } + thd->variables.wsrep_on = 1; + return; +} + +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list) +{ + int ret= 0; + if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) + { + switch (wsrep_OSU_method_options) { + case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_, + table_list); break; + case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; + } + if (!ret) + { + thd->wsrep_exec_mode= TOTAL_ORDER; + } + } + return ret; +} + +void wsrep_to_isolation_end(THD *thd) { + if (thd->wsrep_exec_mode==TOTAL_ORDER) + { + switch(wsrep_OSU_method_options) + { + case WSREP_OSU_TOI: return wsrep_TOI_end(thd); + case WSREP_OSU_RSU: return wsrep_RSU_end(thd); + } + } +} + +#define WSREP_MDL_LOG(severity, msg, req, gra) \ + WSREP_##severity( \ + "%s\n" \ + "request: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ + "granted: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ + msg, \ + req->thread_id, (long long)req->wsrep_trx_seqno, \ + req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \ + req->command, req->lex->sql_command, req->query(), \ + gra->thread_id, (long long)gra->wsrep_trx_seqno, \ + gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ + gra->command, gra->lex->sql_command, gra->query()); + +bool +wsrep_grant_mdl_exception(MDL_context *requestor_ctx, + MDL_ticket *ticket +) { + if (!WSREP_ON) return FALSE; + + THD *request_thd = requestor_ctx->get_thd(); + THD *granted_thd = ticket->get_ctx()->get_thd(); + bool ret = FALSE; + + mysql_mutex_lock(&request_thd->LOCK_wsrep_thd); + if (request_thd->wsrep_exec_mode == TOTAL_ORDER || + request_thd->wsrep_exec_mode == REPL_RECV) + { + mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); + WSREP_MDL_LOG(DEBUG, "MDL conflict ", request_thd, granted_thd); + + mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); + if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || + granted_thd->wsrep_exec_mode == REPL_RECV) + { + WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + ret = TRUE; + } + else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) + { + WSREP_DEBUG("mdl granted over FLUSH BF"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + ret = TRUE; + } + else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) + { + WSREP_DEBUG("DROP caused BF abort"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + } + else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) + { + WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + } + else + { + WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + } + } + else + { + mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); + } + return ret; +} diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h new file mode 100644 index 00000000000..d1c72e6001f --- /dev/null +++ b/sql/wsrep_mysqld.h @@ -0,0 +1,383 @@ +/* Copyright 2008-2012 Codership Oy + + 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_MYSQLD_H +#define WSREP_MYSQLD_H + +#include "mysqld.h" +typedef struct st_mysql_show_var SHOW_VAR; +#include +#include "../wsrep/wsrep_api.h" + +class set_var; +class THD; + +#ifdef WITH_WSREP +#include "../wsrep/wsrep_api.h" +//#include "wsrep_mysqld.h" + enum wsrep_exec_mode { + LOCAL_STATE, + REPL_RECV, + TOTAL_ORDER, + LOCAL_COMMIT, + }; + enum wsrep_query_state { + QUERY_IDLE, + QUERY_EXEC, + QUERY_COMMITTING, + QUERY_EXITING, + QUERY_ROLLINGBACK, + }; + enum wsrep_conflict_state { + NO_CONFLICT, + MUST_ABORT, + ABORTING, + ABORTED, + MUST_REPLAY, + REPLAYING, + RETRY_AUTOCOMMIT, + CERT_FAILURE, + }; + enum wsrep_consistency_check_mode { + NO_CONSISTENCY_CHECK, + CONSISTENCY_CHECK_DECLARED, + CONSISTENCY_CHECK_RUNNING, + }; +#endif + +// Global wsrep parameters +extern wsrep_t* wsrep; + +// MySQL wsrep options +extern const char* wsrep_provider; +extern const char* wsrep_provider_options; +extern const char* wsrep_cluster_name; +extern const char* wsrep_cluster_address; +extern const char* wsrep_node_name; +extern const char* wsrep_node_address; +extern const char* wsrep_node_incoming_address; +extern const char* wsrep_data_home_dir; +extern const char* wsrep_dbug_option; +extern long wsrep_slave_threads; +extern 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_sst_method; +extern const char* wsrep_sst_receive_address; +extern char* wsrep_sst_auth; +extern const char* wsrep_sst_donor; +extern my_bool wsrep_sst_donor_rejects_queries; +extern const char* wsrep_start_position; +extern long long wsrep_max_ws_size; +extern long wsrep_max_ws_rows; +extern const char* wsrep_notify_cmd; +extern my_bool wsrep_certify_nonPK; +extern long wsrep_max_protocol_version; +extern long wsrep_protocol_version; +extern ulong wsrep_forced_binlog_format; +extern ulong wsrep_OSU_method_options; +extern my_bool wsrep_recovery; +extern my_bool wsrep_replicate_myisam; +extern my_bool wsrep_log_conflicts; +extern ulong wsrep_mysql_replication_bundle; + +enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; + +// MySQL status variables +extern my_bool wsrep_connected; +extern my_bool wsrep_ready; +extern const char* wsrep_cluster_state_uuid; +extern long long wsrep_cluster_conf_id; +extern const char* wsrep_cluster_status; +extern long wsrep_cluster_size; +extern long wsrep_local_index; +extern const char* wsrep_provider_name; +extern const char* wsrep_provider_version; +extern const char* wsrep_provider_vendor; +extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); +extern void wsrep_free_status(THD *thd); + +#define WSREP_SST_ADDRESS_AUTO "AUTO" +// MySQL variables funcs + +#define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) +#define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) +#define DEFAULT_ARGS (THD* thd, enum_var_type var_type) +#define INIT_ARGS (const char* opt) + +extern int wsrep_init_vars(); + +extern bool wsrep_on_update UPDATE_ARGS; +extern void wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_start_position_check CHECK_ARGS; +extern bool wsrep_start_position_update UPDATE_ARGS; +extern void wsrep_start_position_init INIT_ARGS; + +extern bool wsrep_provider_check CHECK_ARGS; +extern bool wsrep_provider_update UPDATE_ARGS; +extern void wsrep_provider_init INIT_ARGS; + +extern bool wsrep_provider_options_check CHECK_ARGS; +extern bool wsrep_provider_options_update UPDATE_ARGS; +extern void wsrep_provider_options_init INIT_ARGS; + +extern bool wsrep_cluster_address_check CHECK_ARGS; +extern bool wsrep_cluster_address_update UPDATE_ARGS; +extern void wsrep_cluster_address_init INIT_ARGS; + +extern bool wsrep_cluster_name_check CHECK_ARGS; +extern bool wsrep_cluster_name_update UPDATE_ARGS; + +extern bool wsrep_node_name_check CHECK_ARGS; +extern bool wsrep_node_name_update UPDATE_ARGS; + +extern bool wsrep_node_address_check CHECK_ARGS; +extern bool wsrep_node_address_update UPDATE_ARGS; +extern void wsrep_node_address_init INIT_ARGS; + +extern bool wsrep_sst_method_check CHECK_ARGS; +extern bool wsrep_sst_method_update UPDATE_ARGS; +extern void wsrep_sst_method_init INIT_ARGS; + +extern bool wsrep_sst_receive_address_check CHECK_ARGS; +extern bool wsrep_sst_receive_address_update UPDATE_ARGS; + +extern bool wsrep_sst_auth_check CHECK_ARGS; +extern bool wsrep_sst_auth_update UPDATE_ARGS; +extern void wsrep_sst_auth_init INIT_ARGS; + +extern bool wsrep_sst_donor_check CHECK_ARGS; +extern bool wsrep_sst_donor_update UPDATE_ARGS; + +extern bool wsrep_slave_threads_check CHECK_ARGS; +extern bool wsrep_slave_threads_update UPDATE_ARGS; + +extern bool wsrep_init_first(); // initialize wsrep before storage + // engines (true) or after (false) +extern int wsrep_init(); +extern void wsrep_deinit(); +extern void wsrep_recover(); + + + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); +extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); +extern "C" const char * wsrep_thd_query_state_str(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(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_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); + + + +/* wsrep initialization sequence at startup + * @param first wsrep_init_first() value */ +extern void wsrep_init_startup(bool first); + +extern void wsrep_close_client_connections(my_bool wait_to_end); +extern int wsrep_wait_committing_connections_close(int wait_time); +extern void wsrep_close_applier(THD *thd); +extern void wsrep_wait_appliers_close(THD *thd); +extern void wsrep_close_applier_threads(int count); +extern void wsrep_create_appliers(long threads = wsrep_slave_threads); +extern void wsrep_create_rollbacker(); +extern void wsrep_kill_mysql(THD *thd); + +/* new defines */ +extern void wsrep_stop_replication(THD *thd); +extern bool wsrep_start_replication(); +extern bool wsrep_causal_wait(THD* thd); +extern int wsrep_check_opts (int argc, char* const* argv); +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(thd) \ + (WSREP_ON && (thd && thd->variables.wsrep_on)) + +#define WSREP_CLIENT(thd) \ + (WSREP(thd) && thd->wsrep_client_thread) + +#define WSREP_EMULATE_BINLOG(thd) \ + (WSREP(thd) && wsrep_emulate_bin_log) + +// MySQL logging functions don't seem to understand long long length modifer. +// This is a workaround. It also prefixes all messages with "WSREP" +#define WSREP_LOG(fun, ...) \ + { \ + char msg[1024] = {'\0'}; \ + snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ + fun("WSREP: %s", msg); \ + } + +#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: %ld\n " \ + " SQL: %s", \ + role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ + wsrep_thd_query_state_str(thd), \ + wsrep_thd_conflict_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"); \ + } + +/*! Synchronizes applier thread start with init thread */ +extern void wsrep_sst_grab(); +/*! Init thread waits for SST completion */ +extern bool wsrep_sst_wait(); +/*! Signals wsrep that initialization is complete, writesets can be applied */ +extern void wsrep_sst_continue(); + +extern void wsrep_SE_init_grab(); /*! grab init critical section */ +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 */ + +extern void wsrep_ready_wait(); + +enum wsrep_trx_status { + WSREP_TRX_OK, + WSREP_TRX_ROLLBACK, + WSREP_TRX_ERROR, + }; + +extern enum wsrep_trx_status +wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); +class Ha_trx_info; +struct THD_TRANS; +void wsrep_register_hton(THD* thd, bool all); + +void wsrep_replication_process(THD *thd); +void wsrep_rollback_process(THD *thd); +void wsrep_brute_force_killer(THD *thd); +int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id); +extern "C" bool wsrep_consistency_check(void *thd_ptr); +extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); +extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, + my_bool signal); +extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); +void *wsrep_prepare_bf_thd(THD *thd); +void wsrep_return_from_bf_mode(void *shadow, THD *thd); + +/* this is visible for client build so that innodb plugin gets this */ +typedef struct wsrep_aborting_thd { + struct wsrep_aborting_thd *next; + THD *aborting_thd; +} *wsrep_aborting_thd_t; + +extern mysql_mutex_t LOCK_wsrep_ready; +extern mysql_cond_t COND_wsrep_ready; +extern mysql_mutex_t LOCK_wsrep_sst; +extern mysql_cond_t COND_wsrep_sst; +extern mysql_mutex_t LOCK_wsrep_sst_init; +extern mysql_cond_t COND_wsrep_sst_init; +extern mysql_mutex_t LOCK_wsrep_rollback; +extern mysql_cond_t COND_wsrep_rollback; +extern int wsrep_replaying; +extern mysql_mutex_t LOCK_wsrep_replaying; +extern mysql_cond_t COND_wsrep_replaying; +extern wsrep_aborting_thd_t wsrep_aborting_thd; +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_emulate_bin_log; +extern my_bool wsrep_auto_increment_control; +extern my_bool wsrep_drupal_282555_workaround; +extern long long wsrep_max_ws_size; +extern long wsrep_max_ws_rows; +extern int wsrep_to_isolation; +extern my_bool wsrep_certify_nonPK; +extern mysql_mutex_t LOCK_wsrep_slave_threads; + +extern PSI_mutex_key key_LOCK_wsrep_ready; +extern PSI_mutex_key key_COND_wsrep_ready; +extern PSI_mutex_key key_LOCK_wsrep_sst; +extern PSI_cond_key key_COND_wsrep_sst; +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; + +struct TABLE_LIST; +int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, + const TABLE_LIST* table_list); +void wsrep_to_isolation_end(THD *thd); + +void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); +void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow*); +int wsrep_to_buf_helper( + THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len); +int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len); +int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len); +int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len); + +const wsrep_uuid_t* wsrep_cluster_uuid(); +struct xid_t; +void wsrep_set_SE_checkpoint(xid_t*); + +void wsrep_xid_init(xid_t*, const wsrep_uuid_t*, wsrep_seqno_t); +const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*); +wsrep_seqno_t wsrep_xid_seqno(const xid_t*); +extern "C" int wsrep_is_wsrep_xid(const void* xid); + +#endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc new file mode 100644 index 00000000000..ff997d01183 --- /dev/null +++ b/sql/wsrep_notify.cc @@ -0,0 +1,107 @@ +/* Copyright 2010 Codership Oy + + 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 +#include "wsrep_priv.h" + +const char* wsrep_notify_cmd=""; + +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) +{ + if (!wsrep_notify_cmd || 0 == strlen(wsrep_notify_cmd)) + { + WSREP_INFO("wsrep_notify_cmd is not defined, skipping notification."); + return; + } + + 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; + + 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); + } + + if (0 != view) + { + char uuid_str[40]; + + wsrep_uuid_print (&view->uuid, uuid_str, sizeof(uuid_str)); + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --uuid %s", uuid_str); + + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --primary %s", view->view >= 0 ? "yes" : "no"); + + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, + " --index %d", view->my_idx); + + 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); + } + } + + if (cmd_off == cmd_len) + { + WSREP_ERROR("Notification buffer too short (%ld). Aborting notification.", + cmd_len); + return; + } + + wsp::process p(cmd_ptr, "r"); + + p.wait(); + int err = p.error(); + + if (err) + { + WSREP_ERROR("Notification command failed: %d (%s): \"%s\"", + err, strerror(err), cmd_ptr); + } +} + diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h new file mode 100644 index 00000000000..700639ebcb1 --- /dev/null +++ b/sql/wsrep_priv.h @@ -0,0 +1,233 @@ +/* Copyright 2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//! @file declares symbols private to wsrep integration layer + +#ifndef WSREP_PRIV_H +#define WSREP_PRIV_H + +#include "wsrep_mysqld.h" +#include "../wsrep/wsrep_api.h" + +#include +#include +#include + +extern void wsrep_ready_set (my_bool x); + +extern ssize_t wsrep_sst_prepare (void** msg); +extern int wsrep_sst_donate_cb (void* app_ctx, + void* recv_ctx, + const void* msg, size_t msg_len, + const wsrep_uuid_t* current_uuid, + wsrep_seqno_t current_seqno, + const char* state, size_t state_len, + bool bypass); + +extern size_t guess_ip (char* buf, size_t buf_len); +extern size_t guess_address(char* buf, size_t buf_len); + +extern wsrep_uuid_t local_uuid; +extern wsrep_seqno_t local_seqno; + +/*! SST thread signals init thread about sst completion */ +extern void wsrep_sst_complete(const wsrep_uuid_t* uuid, wsrep_seqno_t, bool); + +extern void wsrep_notify_status (wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0); + +namespace wsp { +class node_status +{ +public: + node_status() : status(WSREP_MEMBER_UNDEFINED) {} + void set(wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0) + { + if (status != new_status || 0 != view) + { + wsrep_notify_status(new_status, view); + status = new_status; + } + } + wsrep_member_status_t get() const { return status; } +private: + wsrep_member_status_t status; +}; +} /* namespace wsp */ + +extern wsp::node_status local_status; + +namespace wsp { +/* A small class to run external programs. */ +class process +{ +private: + const char* const str_; + FILE* io_; + int err_; + pid_t pid_; + +public: +/*! @arg type is a pointer to a null-terminated string which must contain + either the letter 'r' for reading or the letter 'w' for writing. + */ + process (const char* cmd, const char* type); + ~process (); + + FILE* pipe () { return io_; } + int error() { return err_; } + int wait (); + const char* cmd() { return str_; } +}; +#ifdef REMOVED +class lock +{ + pthread_mutex_t* const mtx_; + +public: + + lock (pthread_mutex_t* mtx) : mtx_(mtx) + { + int err = pthread_mutex_lock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex lock failed: %s", strerror(err)); + abort(); + } + } + + virtual ~lock () + { + int err = pthread_mutex_unlock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); + abort(); + } + } + + inline void wait (pthread_cond_t* cond) + { + pthread_cond_wait (cond, mtx_); + } + +private: + + lock (const lock&); + lock& operator=(const lock&); + +}; + +class monitor +{ + int mutable refcnt; + pthread_mutex_t mutable mtx; + pthread_cond_t mutable cond; + +public: + + monitor() : refcnt(0) + { + pthread_mutex_init (&mtx, NULL); + pthread_cond_init (&cond, NULL); + } + + ~monitor() + { + pthread_mutex_destroy (&mtx); + pthread_cond_destroy (&cond); + } + + void enter() const + { + lock l(&mtx); + + while (refcnt) + { + l.wait(&cond); + } + refcnt++; + } + + void leave() const + { + lock l(&mtx); + + refcnt--; + if (refcnt == 0) + { + pthread_cond_signal (&cond); + } + } + +private: + + monitor (const monitor&); + monitor& operator= (const monitor&); +}; + +class critical +{ + const monitor& mon; + +public: + + critical(const monitor& m) : mon(m) { mon.enter(); } + + ~critical() { mon.leave(); } + +private: + + critical (const critical&); + critical& operator= (const critical&); +}; +#endif + +class thd +{ + class thd_init + { + public: + thd_init() { my_thread_init(); } + ~thd_init() { my_thread_end(); } + } + init; + + thd (const thd&); + thd& operator= (const thd&); + +public: + + thd(my_bool wsrep_on); + ~thd(); + THD* const ptr; +}; + +class string +{ +public: + string() : string_(0) {} + void set(char* str) { if (string_) free (string_); string_ = str; } + ~string() { set (0); } +private: + char* string_; +}; + +} // namespace wsrep +#endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc new file mode 100644 index 00000000000..53e3bbcfc79 --- /dev/null +++ b/sql/wsrep_sst.cc @@ -0,0 +1,1001 @@ +/* Copyright 2008-2012 Codership Oy + + 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 +#include +#include +#include +#include +#include +#include "wsrep_priv.h" +#include +#include + +extern const char wsrep_defaults_file[]; + +#define WSREP_SST_OPT_ROLE "--role" +#define WSREP_SST_OPT_ADDR "--address" +#define WSREP_SST_OPT_AUTH "--auth" +#define WSREP_SST_OPT_DATA "--datadir" +#define WSREP_SST_OPT_CONF "--defaults-file" +#define WSREP_SST_OPT_PARENT "--parent" + +// mysqldump-specific options +#define WSREP_SST_OPT_USER "--user" +#define WSREP_SST_OPT_PSWD "--password" +#define WSREP_SST_OPT_HOST "--host" +#define WSREP_SST_OPT_PORT "--port" +#define WSREP_SST_OPT_LPORT "--local-port" + +// donor-specific +#define WSREP_SST_OPT_SOCKET "--socket" +#define WSREP_SST_OPT_GTID "--gtid" +#define WSREP_SST_OPT_BYPASS "--bypass" + +#define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_SKIP "skip" +#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP +#define WSREP_SST_ADDRESS_AUTO "AUTO" +#define WSREP_SST_AUTH_MASK "********" + +const char* wsrep_sst_method = WSREP_SST_DEFAULT; +const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; +const char* wsrep_sst_donor = ""; + 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; + +bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* c_str = NULL; + + if ((res = var->value->val_str(&str)) && + (c_str = res->c_ptr()) && + strlen(c_str) > 0) + return 0; + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); + return 1; +} + +bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +static bool sst_receive_address_check (const char* str) +{ + if (!strncasecmp(str, "127.0.0.1", strlen("127.0.0.1")) || + !strncasecmp(str, "localhost", strlen("localhost"))) + { + return 1; + } + + return 0; +} + +bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) +{ + const char* c_str = var->value->str_value.c_ptr(); + + if (sst_receive_address_check (c_str)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_receive_address", c_str ? c_str : "NULL"); + return 1; + } + + return 0; +} + +bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, + enum_var_type type) +{ + return 0; +} + +bool wsrep_sst_auth_check (sys_var *self, THD* thd, set_var* var) +{ + return 0; +} +static bool sst_auth_real_set (const char* value) +{ + const char* v = strdup (value); + + if (v) + { + if (sst_auth_real) free (const_cast(sst_auth_real)); + sst_auth_real = v; + + if (strlen(sst_auth_real)) + { + if (wsrep_sst_auth) + { + my_free ((void*)wsrep_sst_auth); + wsrep_sst_auth = my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); + //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, + // sizeof(wsrep_sst_auth) - 1); + } + else + wsrep_sst_auth = my_strdup (WSREP_SST_AUTH_MASK, MYF(0)); + } + return 0; + } + + return 1; +} + +bool wsrep_sst_auth_update (sys_var *self, THD* thd, enum_var_type type) +{ + return sst_auth_real_set (wsrep_sst_auth); +} + +void wsrep_sst_auth_init (const char* value) +{ + if (wsrep_sst_auth == value) wsrep_sst_auth = NULL; + if (value) sst_auth_real_set (value); +} + +bool wsrep_sst_donor_check (sys_var *self, THD* thd, set_var* var) +{ + return 0; +} + +bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; + +bool wsrep_init_first() +{ + return (wsrep_provider != NULL + && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_sst_method, WSREP_SST_SKIP) + && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); +} + +static bool sst_complete = false; +static bool sst_needed = false; + +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 () +{ + if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); + while (!sst_complete) + { + WSREP_INFO("Waiting for SST to complete."); + mysql_cond_wait (&COND_wsrep_sst, &LOCK_wsrep_sst); + } + + 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) +{ + 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 + { + WSREP_WARN("Nobody is waiting for SST."); + } + mysql_mutex_unlock (&LOCK_wsrep_sst); +} + +// Let applier threads to continue +void wsrep_sst_continue () +{ + if (sst_needed) + { + WSREP_INFO("Signalling provider to continue."); + wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + } +} + +struct sst_thread_arg +{ + const char* cmd; + int err; + char* ret_str; + mysql_mutex_t lock; + mysql_cond_t cond; + + sst_thread_arg (const char* c) : cmd(c), err(-1), ret_str(0) + { + mysql_mutex_init(key_LOCK_wsrep_sst_thread, &lock, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_sst_thread, &cond, NULL); + } + + ~sst_thread_arg() + { + mysql_cond_destroy (&cond); + mysql_mutex_unlock (&lock); + mysql_mutex_destroy (&lock); + } +}; + +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); + if (offt > 0 && strlen(str) > (unsigned int)offt && ':' == str[offt]) + { + *seqno = strtoll (str + offt + 1, NULL, 10); + if (*seqno != LLONG_MAX || errno != ERANGE) + { + return 0; + } + } + + WSREP_ERROR("Failed to parse uuid:seqno pair: '%s'", str); + return EINVAL; +} + +// get rid of trailing \n +static char* my_fgets (char* buf, size_t buf_len, FILE* stream) +{ + char* ret= fgets (buf, buf_len, stream); + + if (ret) + { + size_t len = strlen(ret); + if (len > 0 && ret[len - 1] == '\n') ret[len - 1] = '\0'; + } + + return ret; +} + +static void* sst_joiner_thread (void* a) +{ + sst_thread_arg* arg= (sst_thread_arg*) a; + int err= 1; + + { + 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); + + wsp::process proc (arg->cmd, "r"); + + if (proc.pipe() && !proc.error()) + { + const char* tmp= my_fgets (out, out_len, proc.pipe()); + + if (!tmp || strlen(tmp) < (magic_len + 2) || + strncasecmp (tmp, magic, magic_len)) + { + WSREP_ERROR("Failed to read '%s ' from: %s\n\tRead: '%s'", + magic, arg->cmd, tmp); + proc.wait(); + if (proc.error()) err = proc.error(); + } + else + { + err = 0; + } + } + else + { + 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 + mysql_mutex_lock (&arg->lock); + if (!err) + { + arg->ret_str = strdup (out + magic_len + 1); + if (!arg->ret_str) err = ENOMEM; + } + arg->err = -err; + mysql_cond_signal (&arg->cond); + mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. + + if (err) return NULL; /* lp:808417 - return immediately, don't signal + * initializer thread to ensure single thread of + * shutdown. */ + + 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()); + + proc.wait(); + err= EINVAL; + + if (!tmp) + { + WSREP_ERROR("Failed to read uuid:seqno from joiner script."); + if (proc.error()) err = proc.error(); + } + else + { + err= sst_scan_uuid_seqno (out, &ret_uuid, &ret_seqno); + } + + if (err) + { + ret_uuid= WSREP_UUID_UNDEFINED; + ret_seqno= -err; + } + + // Tell initializer thread that SST is complete + wsrep_sst_complete (&ret_uuid, ret_seqno, true); + } + + return NULL; +} + +static ssize_t sst_prepare_other (const char* method, + const char* addr_in, + const char** addr_out) +{ + ssize_t cmd_len= 1024; + char cmd_str[cmd_len]; + const char* sst_dir= mysql_real_data_home; + + int ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'joiner' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_PARENT" '%d'", + method, addr_in, (sst_auth_real) ? sst_auth_real : "", + sst_dir, wsrep_defaults_file, (int)getpid()); + + if (ret < 0 || ret >= cmd_len) + { + WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); + return (ret < 0 ? ret : -EMSGSIZE); + } + + pthread_t tmp; + sst_thread_arg arg(cmd_str); + mysql_mutex_lock (&arg.lock); + ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg); + if (ret) + { + WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)", + ret, strerror(ret)); + return ret; + } + mysql_cond_wait (&arg.cond, &arg.lock); + + *addr_out= arg.ret_str; + + if (!arg.err) + ret = strlen(*addr_out); + else + { + assert (arg.err < 0); + ret = arg.err; + } + + pthread_detach (tmp); + + return ret; +} + +//extern ulong my_bind_addr; +extern uint mysqld_port; + +/*! Just tells donor where to send mysqldump */ +static ssize_t sst_prepare_mysqldump (const char* addr_in, + const char** addr_out) +{ + ssize_t ret = strlen (addr_in); + + if (!strrchr(addr_in, ':')) + { + ssize_t s = ret + 7; + char* tmp = (char*) malloc (s); + + if (tmp) + { + ret= snprintf (tmp, s, "%s:%u", addr_in, mysqld_port); + + if (ret > 0 && ret < s) + { + *addr_out= tmp; + return ret; + } + if (ret > 0) /* buffer too short */ ret = -EMSGSIZE; + free (tmp); + } + else { + ret= -ENOMEM; + } + + WSREP_ERROR ("Could not prepare state transfer request: " + "adding default port failed: %zd.", ret); + } + else { + *addr_out= addr_in; + } + + return ret; +} + +static bool SE_initialized = false; + +ssize_t wsrep_sst_prepare (void** msg) +{ + const ssize_t ip_max= 256; + char ip_buf[ip_max]; + const char* addr_in= NULL; + const char* addr_out= NULL; + + 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; + } + + // Figure out SST address. Common for all SST methods + if (wsrep_sst_receive_address && + strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) + { + addr_in= wsrep_sst_receive_address; + } + else if (wsrep_node_address && strlen(wsrep_node_address)) + { + const char* const colon= strchr (wsrep_node_address, ':'); + if (colon) + { + ptrdiff_t const len= colon - wsrep_node_address; + strncpy (ip_buf, wsrep_node_address, len); + ip_buf[len]= '\0'; + addr_in= ip_buf; + } + else + { + addr_in= wsrep_node_address; + } + } + else + { + ssize_t ret= guess_ip (ip_buf, ip_max); + + if (ret && ret < ip_max) + { + addr_in= ip_buf; + } + else + { + WSREP_ERROR("Could not prepare state transfer request: " + "failed to guess address to accept state transfer at. " + "wsrep_sst_receive_address must be set manually."); + unireg_abort(1); + } + } + + ssize_t addr_len= -ENOSYS; + if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP)) + { + addr_len= sst_prepare_mysqldump (addr_in, &addr_out); + if (addr_len < 0) unireg_abort(1); + } + else + { + /*! A heuristic workaround until we learn how to stop and start engines */ + if (SE_initialized) + { + // we already did SST at initializaiton, now engines are running + // sql_print_information() is here because the message is too long + // for WSREP_INFO. + sql_print_information ("WSREP: " + "You have configured '%s' state snapshot transfer method " + "which cannot be performed on a running server. " + "Wsrep provider won't be able to fall back to it " + "if other means of state transfer are unavailable. " + "In that case you will need to restart the server.", + wsrep_sst_method); + *msg = 0; + return 0; + } + + addr_len = sst_prepare_other (wsrep_sst_method, addr_in, &addr_out); + if (addr_len < 0) + { + WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", + wsrep_sst_method); + unireg_abort(1); + } + } + + size_t const method_len(strlen(wsrep_sst_method)); + size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); + + *msg = malloc (msg_len); + if (NULL != *msg) { + char* const method_ptr(reinterpret_cast(*msg)); + strcpy (method_ptr, wsrep_sst_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); + } + + if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); + + return msg_len; +} + +// helper method for donors +static int sst_run_shell (const char* cmd_str, int max_tries) +{ + int ret = 0; + + for (int tries=1; tries <= max_tries; tries++) + { + wsp::process proc (cmd_str, "r"); + + if (NULL != proc.pipe()) + { + proc.wait(); + } + + if ((ret = proc.error())) + { + WSREP_ERROR("Try %d/%d: '%s' failed: %d (%s)", + tries, max_tries, proc.cmd(), ret, strerror(ret)); + sleep (1); + } + else + { + WSREP_DEBUG("SST script successfully completed."); + break; + } + } + + return -ret; +} + +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); +} + +static int sst_mysqldump_check_addr (const char* user, const char* pswd, + const char* host, const char* port) +{ + return 0; +} + +static int sst_donate_mysqldump (const char* addr, + const wsrep_uuid_t* uuid, + const char* uuid_str, + wsrep_seqno_t seqno, + bool bypass) +{ + size_t host_len; + const char* port = strchr (addr, ':'); + + if (port) + { + port += 1; + host_len = port - addr; + } + else + { + port = ""; + host_len = strlen (addr) + 1; + } + + char host[host_len]; + + strncpy (host, addr, host_len - 1); + host[host_len - 1] = '\0'; + + const char* auth = sst_auth_real; + const char* pswd = (auth) ? strchr (auth, ':') : NULL; + size_t user_len; + + if (pswd) + { + pswd += 1; + user_len = pswd - auth; + } + else + { + pswd = ""; + user_len = (auth) ? strlen (auth) + 1 : 1; + } + + char user[user_len]; + + strncpy (user, (auth) ? auth : "", user_len - 1); + user[user_len - 1] = '\0'; + + int ret = sst_mysqldump_check_addr (user, pswd, host, port); + if (!ret) + { + size_t cmd_len= 1024; + char cmd_str[cmd_len]; + + if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); + + snprintf (cmd_str, cmd_len, + "wsrep_sst_mysqldump " + WSREP_SST_OPT_USER" '%s' " + WSREP_SST_OPT_PSWD" '%s' " + WSREP_SST_OPT_HOST" '%s' " + WSREP_SST_OPT_PORT" '%s' " + WSREP_SST_OPT_LPORT" '%u' " + WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_GTID" '%s:%lld'" + "%s", + user, pswd, host, port, mysqld_port, mysqld_unix_port, uuid_str, + (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); + + WSREP_DEBUG("Running: '%s'", cmd_str); + + ret= sst_run_shell (cmd_str, 3); + } + + wsrep->sst_sent (wsrep, uuid, ret ? ret : seqno); + + return ret; +} + +wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + +static int run_sql_command(THD *thd, const char *query) +{ + thd->set_query((char *)query, strlen(query)); + + Parser_state ps; + if (ps.init(thd, thd->query(), thd->query_length())) + { + WSREP_ERROR("SST query: %s failed", query); + return -1; + } + + mysql_parse(thd, thd->query(), thd->query_length(), &ps); + if (thd->is_error()) + { + int const err= thd->stmt_da->sql_errno(); + WSREP_WARN ("error executing '%s': %d (%s)%s", + query, err, thd->stmt_da->message(), + err == ER_UNKNOWN_SYSTEM_VARIABLE ? + ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); + thd->clear_error(); + return -1; + } + return 0; +} + +static int sst_flush_tables(THD* thd) +{ + WSREP_INFO("Flushing tables for SST..."); + + int err; + int not_used; + if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) + { + WSREP_ERROR("Failed to flush and lock tables"); + err = -1; + } + else + { + /* make sure logs are flushed after global read lock acquired */ + err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG, + (TABLE_LIST*) 0, ¬_used); + } + + if (err) + { + WSREP_ERROR("Failed to flush tables: %d (%s)", err, strerror(err)); + } + else + { + WSREP_INFO("Tables flushed."); + const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; + char real_name[full_len]; + sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); + char tmp_name[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 + { + fprintf(file, "%s:%lld\n", + wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno); + 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)); + } + } + } + + return err; +} + +static void sst_disallow_writes (THD* thd, bool yes) +{ + char query_str[64] = { 0, }; + ssize_t const query_max = sizeof(query_str) - 1; + snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", + yes ? 1 : 0); + + if (run_sql_command(thd, query_str)) + { + WSREP_ERROR("Failed to disallow InnoDB writes"); + } +} + +static void* sst_donor_thread (void* a) +{ + sst_thread_arg* arg= (sst_thread_arg*)a; + + WSREP_INFO("Running: '%s'", arg->cmd); + + int err= 1; + bool locked= false; + + const char* out= NULL; + const size_t out_len= 128; + char out_buf[out_len]; + + wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST + + wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can + // operate with wsrep_ready == OFF + wsp::process proc(arg->cmd, "r"); + + err= proc.error(); + +/* Inform server about SST script startup and release TO isolation */ + mysql_mutex_lock (&arg->lock); + arg->err = -err; + mysql_cond_signal (&arg->cond); + mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. + + if (proc.pipe() && !err) + { +wait_signal: + out= my_fgets (out_buf, out_len, proc.pipe()); + + if (out) + { + const char magic_flush[]= "flush tables"; + const char magic_cont[]= "continue"; + const char magic_done[]= "done"; + + if (!strcasecmp (out, magic_flush)) + { + err= sst_flush_tables (thd.ptr); + if (!err) + { + sst_disallow_writes (thd.ptr, true); + locked= true; + goto wait_signal; + } + } + else if (!strcasecmp (out, magic_cont)) + { + if (locked) + { + sst_disallow_writes (thd.ptr, false); + thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + locked= false; + } + err= 0; + goto wait_signal; + } + else if (!strncasecmp (out, magic_done, strlen(magic_done))) + { + err= sst_scan_uuid_seqno (out + strlen(magic_done) + 1, + &ret_uuid, &ret_seqno); + } + else + { + WSREP_WARN("Received unknown signal: '%s'", out); + } + } + else + { + WSREP_ERROR("Failed to read from: %s", proc.cmd()); + } + if (err && proc.error()) err= proc.error(); + } + else + { + WSREP_ERROR("Failed to execute: %s : %d (%s)", + proc.cmd(), err, strerror(err)); + } + + if (locked) // don't forget to unlock server before return + { + sst_disallow_writes (thd.ptr, false); + thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + } + + // signal to donor that SST is over + wsrep->sst_sent (wsrep, &ret_uuid, err ? -err : ret_seqno); + proc.wait(); + + return NULL; +} + +static int sst_donate_other (const char* method, + const char* addr, + const char* uuid, + wsrep_seqno_t seqno, + bool bypass) +{ + ssize_t cmd_len = 4096; + char cmd_str[cmd_len]; + + int ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'donor' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_GTID" '%s:%lld'" + "%s", + method, addr, sst_auth_real, mysqld_unix_port, + mysql_real_data_home, wsrep_defaults_file, + uuid, (long long) seqno, + bypass ? " "WSREP_SST_OPT_BYPASS : ""); + + if (ret < 0 || ret >= cmd_len) + { + WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); + return (ret < 0 ? ret : -EMSGSIZE); + } + + if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(FALSE); + + pthread_t tmp; + sst_thread_arg arg(cmd_str); + mysql_mutex_lock (&arg.lock); + ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg); + if (ret) + { + WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)", + ret, strerror(ret)); + return ret; + } + mysql_cond_wait (&arg.cond, &arg.lock); + + WSREP_INFO("sst_donor_thread signaled with %d", arg.err); + return arg.err; +} + +int wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, + const void* msg, size_t msg_len, + const wsrep_uuid_t* current_uuid, + wsrep_seqno_t current_seqno, + const char* state, size_t state_len, + bool bypass) +{ + /* This will be reset when sync callback is called. + * Should we set wsrep_ready to FALSE here too? */ +// wsrep_notify_status(WSREP_MEMBER_DONOR); + local_status.set(WSREP_MEMBER_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 (current_uuid, uuid_str, sizeof(uuid_str)); + + int ret; + if (!strcmp (WSREP_SST_MYSQLDUMP, method)) + { + ret = sst_donate_mysqldump (data, current_uuid, uuid_str, current_seqno, + bypass); + } + else + { + ret = sst_donate_other (method, data, uuid_str, current_seqno, bypass); + } + + return (ret > 0 ? 0 : ret); +} + +void wsrep_SE_init_grab() +{ + if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); +} + +void wsrep_SE_init_wait() +{ + mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); + 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; +} diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc new file mode 100644 index 00000000000..b1bd6de07cf --- /dev/null +++ b/sql/wsrep_utils.cc @@ -0,0 +1,467 @@ +/* Copyright 2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//! @file declares symbols private to wsrep integration layer + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // POSIX_SPAWN_USEVFORK flag +#endif + +#include // posix_spawn() +#include // pipe() +#include // errno +#include // strerror() +#include // waitpid() + +#include +#include "wsrep_priv.h" + +extern char** environ; // environment variables + +static wsp::string wsrep_PATH; + +void +wsrep_prepend_PATH (const char* path) +{ + int count = 0; + + while (environ[count]) + { + if (strncmp (environ[count], "PATH=", 5)) + { + count++; + continue; + } + + char* const old_path (environ[count]); + + if (strstr (old_path, path)) return; // path already there + + size_t const new_path_len(strlen(old_path) + strlen(":") + + strlen(path) + 1); + + char* const new_path (reinterpret_cast(malloc(new_path_len))); + + if (new_path) + { + snprintf (new_path, new_path_len, "PATH=%s:%s", path, + old_path + strlen("PATH=")); + + wsrep_PATH.set (new_path); + environ[count] = new_path; + } + else + { + WSREP_ERROR ("Failed to allocate 'PATH' environment variable " + "buffer of size %zu.", new_path_len); + } + + return; + } + + WSREP_ERROR ("Failed to find 'PATH' environment variable. " + "State snapshot transfer may not be working."); +} + +namespace wsp +{ + +#define PIPE_READ 0 +#define PIPE_WRITE 1 +#define STDIN_FD 0 +#define STDOUT_FD 1 + +#ifndef POSIX_SPAWN_USEVFORK +# define POSIX_SPAWN_USEVFORK 0 +#endif + +process::process (const char* cmd, const char* type) + : str_(cmd ? strdup(cmd) : strdup("")), io_(NULL), err_(EINVAL), pid_(0) +{ + if (0 == str_) + { + WSREP_ERROR ("Can't allocate command line of size: %zu", strlen(cmd)); + err_ = ENOMEM; + return; + } + + if (0 == strlen(str_)) + { + WSREP_ERROR ("Can't start a process: null or empty command line."); + return; + } + + if (NULL == type || (strcmp (type, "w") && strcmp(type, "r"))) + { + WSREP_ERROR ("type argument should be either \"r\" or \"w\"."); + return; + } + + int pipe_fds[2] = { -1, }; + if (::pipe(pipe_fds)) + { + err_ = errno; + WSREP_ERROR ("pipe() failed: %d (%s)", err_, strerror(err_)); + return; + } + + // which end of pipe will be returned to parent + int const parent_end (strcmp(type,"w") ? PIPE_READ : PIPE_WRITE); + 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 }; + if (!(pargv[0] && pargv[1] && pargv[2])) + { + err_ = ENOMEM; + WSREP_ERROR ("Failed to allocate pargv[] array."); + goto cleanup_pipe; + } + + posix_spawnattr_t attr; + err_ = posix_spawnattr_init (&attr); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_init() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_pipe; + } + + err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_USEVFORK); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setflags() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + posix_spawn_file_actions_t fact; + err_ = posix_spawn_file_actions_init (&fact); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_init() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + // close child's stdout|stdin depending on what we returning + err_ = posix_spawn_file_actions_addclose (&fact, close_fd); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_addclose() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_fact; + } + + // substitute our pipe descriptor in place of the closed one + err_ = posix_spawn_file_actions_adddup2 (&fact, + pipe_fds[child_end], close_fd); + if (err_) + { + WSREP_ERROR ("posix_spawn_file_actions_addup2() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_fact; + } + + err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, environ); + 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 + goto cleanup_fact; + } + + io_ = fdopen (pipe_fds[parent_end], type); + + if (io_) + { + pipe_fds[parent_end] = -1; // skip close on cleanup + } + else + { + 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); + if (err) + { + WSREP_ERROR ("posix_spawn_file_actions_destroy() failed: %d (%s)\n", + err, strerror(err)); + } + +cleanup_attr: + err = posix_spawnattr_destroy (&attr); + if (err) + { + WSREP_ERROR ("posix_spawnattr_destroy() failed: %d (%s)", + err, strerror(err)); + } + +cleanup_pipe: + if (pipe_fds[0] >= 0) close (pipe_fds[0]); + if (pipe_fds[1] >= 0) close (pipe_fds[1]); + + free (pargv[0]); + free (pargv[1]); + free (pargv[2]); +} + +process::~process () +{ + if (io_) + { + assert (pid_); + assert (str_); + + WSREP_WARN("Closing pipe to child process: %s, PID(%ld) " + "which might still be running.", str_, (long)pid_); + + if (fclose (io_) == -1) + { + err_ = errno; + WSREP_ERROR("fclose() failed: %d (%s)", err_, strerror(err_)); + } + } + + if (str_) free (const_cast(str_)); +} + +int +process::wait () +{ + if (pid_) + { + int status; + if (-1 == waitpid(pid_, &status, 0)) + { + 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); + } + else { // command didn't complete with exit() + WSREP_ERROR("Process was aborted."); + 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 */ + } + WSREP_ERROR("Process completed with error: %s: %d (%s)", + str_, err_, strerror(err_)); + } + + pid_ = 0; + if (io_) fclose (io_); + io_ = NULL; + } + } + else { + assert (NULL == io_); + WSREP_ERROR("Command did not run: %s", str_); + } + + return err_; +} + +thd::thd (my_bool won) : init(), ptr(new THD) +{ + if (ptr) + { + ptr->thread_stack= (char*) &ptr; + ptr->store_globals(); + ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog + ptr->variables.wsrep_on = won; + ptr->security_ctx->master_access= ~(ulong)0; + lex_start(ptr); + } +} + +thd::~thd () +{ + if (ptr) + { + delete ptr; + my_pthread_setspecific_ptr (THR_THD, 0); + } +} + +} // namespace wsp + +extern ulong my_bind_addr; +extern uint mysqld_port; + +size_t guess_ip (char* buf, size_t buf_len) +{ + size_t ip_len = 0; + + if (htonl(INADDR_NONE) == my_bind_addr) { + WSREP_ERROR("Networking not configured, cannot receive state transfer."); + return 0; + } + + if (htonl(INADDR_ANY) != my_bind_addr) { + uint8_t* b = (uint8_t*)&my_bind_addr; + ip_len = snprintf (buf, buf_len, + "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); + return ip_len; + } + + // mysqld binds to all interfaces - try IP from wsrep_node_address + if (wsrep_node_address && wsrep_node_address[0] != '\0') { + const char* const colon_ptr = strchr(wsrep_node_address, ':'); + + if (colon_ptr) + ip_len = colon_ptr - wsrep_node_address; + else + ip_len = strlen(wsrep_node_address); + + if (ip_len >= buf_len) { + WSREP_WARN("default_ip(): buffer too short: %zu <= %zd", buf_len, ip_len); + return 0; + } + + memcpy (buf, wsrep_node_address, ip_len); + buf[ip_len] = '\0'; + return ip_len; + } + + // try to find the address of the first one +#if (TARGET_OS_LINUX == 1) + const char cmd[] = "/sbin/ifconfig | " + "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +#elif defined(__sun__) + const char cmd[] = "/sbin/ifconfig -a | " + "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; +#else + char *cmd; +#error "OS not supported" +#endif + wsp::process proc (cmd, "r"); + + if (NULL != proc.pipe()) { + char* ret; + + ret = fgets (buf, buf_len, proc.pipe()); + + if (proc.wait()) return 0; + + if (NULL == ret) { + WSREP_ERROR("Failed to read output of: '%s'", cmd); + return 0; + } + } + else { + WSREP_ERROR("Failed to execute: '%s'", cmd); + return 0; + } + + // clear possible \n at the end of ip string left by fgets() + ip_len = strlen (buf); + if (ip_len > 0 && '\n' == buf[ip_len - 1]) { + ip_len--; + buf[ip_len] = '\0'; + } + + if (INADDR_NONE == inet_addr(buf)) { + if (strlen(buf) != 0) { + WSREP_WARN("Shell command returned invalid address: '%s'", buf); + } + return 0; + } + + return ip_len; +} + +size_t guess_address(char* buf, size_t buf_len) +{ + size_t addr_len = guess_ip (buf, buf_len); + + if (addr_len && addr_len < buf_len) { + addr_len += snprintf (buf + addr_len, buf_len - addr_len, + ":%u", mysqld_port); + } + + return addr_len; +} + +/* + * WSREPXid + */ + +#define WSREP_XID_PREFIX "WSREPXid" +#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN +#define WSREP_XID_UUID_OFFSET 8 +#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) +{ + 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); + memcpy(xid->data + WSREP_XID_UUID_OFFSET, uuid, sizeof(wsrep_uuid_t)); + memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t)); +} + +const wsrep_uuid_t* wsrep_xid_uuid(const XID* xid) +{ + if (wsrep_is_wsrep_xid(xid)) + return reinterpret_cast(xid->data + + WSREP_XID_UUID_OFFSET); + else + return &WSREP_UUID_UNDEFINED; +} + +wsrep_seqno_t wsrep_xid_seqno(const XID* xid) +{ + + if (wsrep_is_wsrep_xid(xid)) + { + wsrep_seqno_t seqno; + memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); + return seqno; + } + else + { + return WSREP_SEQNO_UNDEFINED; + } +} + +extern "C" +int wsrep_is_wsrep_xid(const void* xid_ptr) +{ + const XID* xid= reinterpret_cast(xid_ptr); + return (xid->formatID == 1 && + xid->gtrid_length == WSREP_XID_GTRID_LEN && + xid->bqual_length == 0 && + !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)); +} diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc new file mode 100644 index 00000000000..3136f905109 --- /dev/null +++ b/sql/wsrep_var.cc @@ -0,0 +1,532 @@ +/* Copyright 2008 Codership Oy + + 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 +#include +#include +#include +#include +#include "wsrep_priv.h" +#include +#include +#include + +#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" + +// trx history position to start with +const char* wsrep_start_position = WSREP_START_POSITION_ZERO; +const char* wsrep_provider = WSREP_NONE; +const char* wsrep_provider_options = (const char*)my_memdup("", 1, MYF(MY_WME)); +const char* wsrep_cluster_address = NULL; +const char* wsrep_cluster_name = "my_wsrep_cluster"; +const char* wsrep_node_name = glob_hostname; +static char node_address[256] = { 0, }; +const char* wsrep_node_address = node_address; +ulong wsrep_OSU_method_options; +static int wsrep_thread_change = 0; + +int wsrep_init_vars() +{ + global_system_variables.binlog_format=BINLOG_FORMAT_ROW; + return 0; +} + +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; + } + else { + } + +#ifdef REMOVED + if (thd->variables.wsrep_on) + thd->variables.option_bits |= (OPTION_BIN_LOG); + else + thd->variables.option_bits &= ~(OPTION_BIN_LOG); +#endif + return false; +} + +void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) +{ + if (var_type == OPT_GLOBAL) { + thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; + } + else { + } +} + +static int wsrep_start_position_verify (const char* start_str) +{ + size_t start_len; + wsrep_uuid_t uuid; + ssize_t uuid_len; + + start_len = strlen (start_str); + if (start_len < 34) + return 1; + + uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid); + if (uuid_len < 0 || (start_len - uuid_len) < 2) + return 1; + + if (start_str[uuid_len] != ':') // separator should follow UUID + return 1; + + char* endptr; + wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings + (strtoll(&start_str[uuid_len + 1], &endptr, 10)); + + if (*endptr == '\0') return 0; // remaining string was seqno + + return 1; +} + +bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* start_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + start_str = res->c_ptr(); + + if (!start_str) goto err; + + if (!wsrep_start_position_verify(start_str)) return 0; + +err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + start_str ? start_str : "NULL"); + return 1; +} + +void wsrep_set_local_position (const char* value) +{ + size_t value_len = strlen (value); + size_t uuid_len = wsrep_uuid_scan (value, value_len, &local_uuid); + + local_seqno = strtoll (value + uuid_len + 1, NULL, 10); + + XID xid; + wsrep_xid_init(&xid, &local_uuid, local_seqno); + wsrep_set_SE_checkpoint(&xid); + WSREP_INFO ("wsrep_start_position var submitted: '%s'", wsrep_start_position); +} + +bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) +{ + // since this value passed wsrep_start_position_check, don't check anything + // here + wsrep_set_local_position (wsrep_start_position); + + if (wsrep) { + wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + } + + return 0; +} + +void wsrep_start_position_init (const char* val) +{ + if (NULL == val || wsrep_start_position_verify (val)) + { + WSREP_ERROR("Bad initial value for wsrep_start_position: %s", + (val ? val : "")); + return; + } + + wsrep_start_position = my_strdup(val, MYF(0)); + + wsrep_set_local_position (val); +} + +static bool refresh_provider_options() +{ + char* opts= wsrep->options_get(wsrep); + if (opts) + { + if (wsrep_provider_options) my_free((void *)wsrep_provider_options); + wsrep_provider_options = (char*)my_memdup(opts, strlen(opts) + 1, + MYF(MY_WME)); + } + else + { + WSREP_ERROR("Failed to get provider options"); + return true; + } + return false; +} + +static int wsrep_provider_verify (const char* provider_str) +{ + MY_STAT f_stat; + char path[FN_REFLEN]; + + if (!provider_str || strlen(provider_str)== 0) + return 1; + + if (!strcmp(provider_str, WSREP_NONE)) + return 0; + + if (!unpack_filename(path, provider_str)) + return 1; + + /* check that provider file exists */ + bzero(&f_stat, sizeof(MY_STAT)); + if (!my_stat(path, &f_stat, MYF(0))) + { + return 1; + } + return 0; +} + +bool wsrep_provider_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* provider_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + provider_str = res->c_ptr(); + + if (!provider_str) goto err; + + if (!wsrep_provider_verify(provider_str)) return 0; + +err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + provider_str ? provider_str : "NULL"); + return 1; +} + +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_stop_replication(thd); + wsrep_deinit(); + + char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider + //when fails + if (wsrep_init()) + { + my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp); + 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); + + thd->variables.wsrep_on= wsrep_on_saved; + + refresh_provider_options(); + + return rcode; +} + +void wsrep_provider_init (const char* value) +{ + if (NULL == value || wsrep_provider_verify (value)) + { + WSREP_ERROR("Bad initial value for wsrep_provider: %s", + (value ? value : "")); + return; + } + wsrep_provider = my_strdup(value, MYF(0)); +} + +bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) +{ + return 0; +} + +bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) +{ + wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options); + if (ret != WSREP_OK) + { + WSREP_ERROR("Set options returned %d", ret); + return true; + } + return refresh_provider_options(); +} + +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; +} + +static int wsrep_cluster_address_verify (const char* cluster_address_str) +{ + /* There is no predefined address format, it depends on provider. */ + return 0; +} + +bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* cluster_address_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + cluster_address_str = res->c_ptr(); + + if (!wsrep_cluster_address_verify(cluster_address_str)) return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + cluster_address_str ? cluster_address_str : "NULL"); + return 1 ; +} + +bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) +{ + bool wsrep_on_saved= thd->variables.wsrep_on; + thd->variables.wsrep_on= false; + + wsrep_stop_replication(thd); + + if (wsrep_start_replication()) + { + wsrep_create_rollbacker(); + wsrep_create_appliers(wsrep_slave_threads); + } + + thd->variables.wsrep_on= wsrep_on_saved; + + return false; +} + +void wsrep_cluster_address_init (const char* value) +{ + if (wsrep_cluster_address && wsrep_cluster_address != value) + my_free ((void*)wsrep_cluster_address); + + wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; +} + +bool wsrep_cluster_name_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* cluster_name_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + cluster_name_str = res->c_ptr(); + + if (!cluster_name_str || strlen(cluster_name_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + cluster_name_str ? cluster_name_str : "NULL"); + return 1; +} + +bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +bool wsrep_node_name_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* node_name_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + node_name_str = res->c_ptr(); + + if (!node_name_str || strlen(node_name_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + node_name_str ? node_name_str : "NULL"); + return 1; +} + +bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +// TODO: do something more elaborate, like checking connectivity +bool wsrep_node_address_check (sys_var *self, THD* thd, set_var* var) +{ + char buff[FN_REFLEN]; + String str(buff, sizeof(buff), system_charset_info), *res; + const char* node_address_str = NULL; + + if (!(res = var->value->val_str(&str))) goto err; + + node_address_str = res->c_ptr(); + + if (!node_address_str || strlen(node_address_str) == 0) goto err; + + return 0; + + err: + + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + node_address_str ? node_address_str : "NULL"); + return 1; +} + +bool wsrep_node_address_update (sys_var *self, THD* thd, enum_var_type type) +{ + return 0; +} + +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; +} + +bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) +{ + mysql_mutex_lock(&LOCK_wsrep_slave_threads); + wsrep_thread_change = var->value->val_int() - wsrep_slave_threads; + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + + return 0; +} + +bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) +{ + if (wsrep_thread_change > 0) + { + wsrep_create_appliers(wsrep_thread_change); + } + else if (wsrep_thread_change < 0) + { + wsrep_close_applier_threads(-wsrep_thread_change); + } + return false; +} +/* + * Status variables stuff below + */ +static inline void +wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep) +{ + mysql->name = wsrep->name; + switch (wsrep->type) { + case WSREP_VAR_INT64: + mysql->value = (char*) &wsrep->value._int64; + mysql->type = SHOW_LONGLONG; + break; + case WSREP_VAR_STRING: + mysql->value = (char*) &wsrep->value._string; + mysql->type = SHOW_CHAR_PTR; + break; + case WSREP_VAR_DOUBLE: + mysql->value = (char*) &wsrep->value._double; + mysql->type = SHOW_DOUBLE; + break; + } +} + +#if DYNAMIC +// somehow this mysql status thing works only with statically allocated arrays. +static SHOW_VAR* mysql_status_vars = NULL; +static int mysql_status_len = -1; +#else +static SHOW_VAR mysql_status_vars[512 + 1]; +static const int mysql_status_len = 512; +#endif + +static void export_wsrep_status_to_mysql(THD* thd) +{ + int wsrep_status_len, i; + + thd->wsrep_status_vars = wsrep->stats_get(wsrep); + + if (!thd->wsrep_status_vars) { + return; + } + + for (wsrep_status_len = 0; + thd->wsrep_status_vars[wsrep_status_len].name != NULL; + wsrep_status_len++); + +#if DYNAMIC + if (wsrep_status_len != mysql_status_len) { + void* tmp = realloc (mysql_status_vars, + (wsrep_status_len + 1) * sizeof(SHOW_VAR)); + if (!tmp) { + + sql_print_error ("Out of memory for wsrep status variables." + "Number of variables: %d", wsrep_status_len); + return; + } + + mysql_status_len = wsrep_status_len; + mysql_status_vars = (SHOW_VAR*)tmp; + } + /* @TODO: fix this: */ +#else + if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len; +#endif + + for (i = 0; i < wsrep_status_len; i++) + wsrep_assign_to_mysql (mysql_status_vars + i, thd->wsrep_status_vars + i); + + mysql_status_vars[wsrep_status_len].name = NullS; + mysql_status_vars[wsrep_status_len].value = NullS; + mysql_status_vars[wsrep_status_len].type = SHOW_LONG; +} + +int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) +{ + export_wsrep_status_to_mysql(thd); + var->type= SHOW_ARRAY; + var->value= (char *) &mysql_status_vars; + return 0; +} + +void wsrep_free_status (THD* thd) +{ + if (thd->wsrep_status_vars) + { + wsrep->stats_free (wsrep, thd->wsrep_status_vars); + thd->wsrep_status_vars = 0; + } +} diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh new file mode 100644 index 00000000000..507f83324b9 --- /dev/null +++ b/support-files/wsrep.cnf.sh @@ -0,0 +1,129 @@ +# This file contains wsrep-related mysqld options. It should be included +# in the main MySQL configuration file. +# +# Options that need to be customized: +# - wsrep_provider +# - wsrep_cluster_address +# - wsrep_sst_auth +# The rest of defaults should work out of the box. + +## +## mysqld options _MANDATORY_ for correct opration of the cluster +## +[mysqld] + +# (This must be substituted by wsrep_format) +binlog_format=ROW + +# Currently only InnoDB storage engine is supported +default-storage-engine=innodb + +# to avoid issues with 'bulk mode inserts' using autoinc +innodb_autoinc_lock_mode=2 + +# This is a must for paralell applying +innodb_locks_unsafe_for_binlog=1 + +# Query Cache is not supported with wsrep +query_cache_size=0 +query_cache_type=0 + +# Override bind-address +# In some systems bind-address defaults to 127.0.0.1, and with mysqldump SST +# it will have (most likely) disastrous consequences on donor node +bind-address=0.0.0.0 + +## +## WSREP options +## + +# Full path to wsrep provider library or 'none' +wsrep_provider=none + +# Provider specific configuration options +#wsrep_provider_options= + +# Logical cluster name. Should be the same for all nodes. +wsrep_cluster_name="my_wsrep_cluster" + +# Group communication system handle +#wsrep_cluster_address="dummy://" + +# Human-readable node name (non-unique). Hostname by default. +#wsrep_node_name= + +# Base replication [:port] of the node. +# The values supplied will be used as defaults for state transfer receiving, +# listening ports and so on. Default: address of the first network interface. +#wsrep_node_address= + +# Address for incoming client connections. Autodetect by default. +#wsrep_node_incoming_address= + +# How many threads will process writesets from other nodes +wsrep_slave_threads=1 + +# DBUG options for wsrep provider +#wsrep_dbug_option + +# Generate fake primary keys for non-PK tables (required for multi-master +# and parallel applying operation) +wsrep_certify_nonPK=1 + +# Maximum number of rows in write set +wsrep_max_ws_rows=131072 + +# Maximum size of write set +wsrep_max_ws_size=1073741824 + +# to enable debug level logging, set this to 1 +wsrep_debug=0 + +# convert locking sessions into transactions +wsrep_convert_LOCK_to_trx=0 + +# how many times to retry deadlocked autocommits +wsrep_retry_autocommit=1 + +# change auto_increment_increment and auto_increment_offset automatically +wsrep_auto_increment_control=1 + +# retry autoinc insert, which failed for duplicate key error +wsrep_drupal_282555_workaround=0 + +# enable "strictly synchronous" semantics for read operations +wsrep_causal_reads=0 + +# Command to call when node status or cluster membership changes. +# Will be passed all or some of the following options: +# --status - new status of this node +# --uuid - UUID of the cluster +# --primary - whether the component is primary or not ("yes"/"no") +# --members - comma-separated list of members +# --index - index of this node in the list +wsrep_notify_cmd= + +## +## WSREP State Transfer options +## + +# State Snapshot Transfer method +wsrep_sst_method=mysqldump + +# Address which donor should send State Snapshot to. +# Should be the address of THIS node. DON'T SET IT TO DONOR ADDRESS!!! +# (SST method dependent. Defaults to the first IP of the first interface) +#wsrep_sst_receive_address= + +# SST authentication string. This will be used to send SST to joining nodes. +# Depends on SST method. For mysqldump method it is root: +wsrep_sst_auth=root: + +# Desired SST donor name. +#wsrep_sst_donor= + +# Reject client queries when donating SST (false) +#wsrep_sst_donor_rejects_queries=0 + +# Protocol version to use +# wsrep_protocol_version= diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh new file mode 100644 index 00000000000..bdbe3d12a39 --- /dev/null +++ b/support-files/wsrep_notify.sh @@ -0,0 +1,102 @@ +#!/bin/sh -eu + +# This is a simple example of wsrep notification script (wsrep_notify_cmd). +# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' +# and fill them on every membership or node status change. +# +# Edit parameters below to specify the address and login to server. + +USER=root +PSWD=rootpass +HOST=127.0.0.1 +PORT=3306 + +SCHEMA="wsrep" +MEMB_TABLE="$SCHEMA.membership" +STATUS_TABLE="$SCHEMA.status" + +BEGIN=" +SET wsrep_on=0; +DROP SCHEMA IF EXISTS $SCHEMA; CREATE SCHEMA $SCHEMA; +CREATE TABLE $MEMB_TABLE ( + idx INT UNIQUE PRIMARY KEY, + uuid CHAR(40) UNIQUE, /* node UUID */ + name VARCHAR(32), /* node name */ + addr VARCHAR(256) /* node address */ +) ENGINE=MEMORY; +CREATE TABLE $STATUS_TABLE ( + size INT, /* component size */ + idx INT, /* this node index */ + status CHAR(16), /* this node status */ + uuid CHAR(40), /* cluster UUID */ + prim BOOLEAN /* if component is primary */ +) ENGINE=MEMORY; +BEGIN; +DELETE FROM $MEMB_TABLE; +DELETE FROM $STATUS_TABLE; +" +END="COMMIT;" + +configuration_change() +{ + echo "$BEGIN;" + + local idx=0 + + for NODE in $(echo $MEMBERS | sed s/,/\ /g) + do + echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " + # Don't forget to properly quote string values + echo "'$NODE'" | sed s/\\//\',\'/g + echo ");" + idx=$(( $idx + 1 )) + done + + echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" + + echo "$END" +} + +status_update() +{ + echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;" +} + +COM=status_update # not a configuration change by default + +while [ $# -gt 0 ] +do + case $1 in + --status) + STATUS=$2 + shift + ;; + --uuid) + CLUSTER_UUID=$2 + shift + ;; + --primary) + [ "$2" = "yes" ] && PRIMARY="1" || PRIMARY="0" + COM=configuration_change + shift + ;; + --index) + INDEX=$2 + shift + ;; + --members) + MEMBERS=$2 + shift + ;; + esac + shift +done + +# Undefined means node is shutting down +if [ "$STATUS" != "Undefined" ] +then + $COM | mysql -B -u$USER -p$PSWD -h$HOST -P$PORT +fi + +exit 0 +# diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt new file mode 100644 index 00000000000..11d0e34d1b0 --- /dev/null +++ b/wsrep/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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 + +INCLUDE_DIRECTORIES( "." ) + +SET(WSREP_SOURCES wsrep_uuid.c wsrep_loader.c wsrep_dummy.c) + +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/Makefile.am b/wsrep/Makefile.am new file mode 100644 index 00000000000..40e4b501e86 --- /dev/null +++ b/wsrep/Makefile.am @@ -0,0 +1,2 @@ +noinst_LIBRARIES = libwsrep.a +libwsrep_a_SOURCES = wsrep_api.h wsrep_loader.c wsrep_dummy.c wsrep_uuid.c diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h new file mode 100644 index 00000000000..2cd10afc7ff --- /dev/null +++ b/wsrep/wsrep_api.h @@ -0,0 +1,875 @@ +/* Copyright (C) 2009-2011 Codership Oy + + 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_H +#define WSREP_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * wsrep replication API + */ + +#define WSREP_INTERFACE_VERSION "23" + +/*! + * Certain provider capabilities application may need to know + */ +#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_WRITE_SET_INCREMENTS ( 1ULL << 8 ) +#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) +#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) +#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) + +/*! + * Write set replication flags + */ +#define WSREP_FLAG_PA_SAFE ( 1ULL << 0 ) + +/* Empty backend spec */ +#define WSREP_NONE "none" + +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. + +/*! undefined seqno */ +#define WSREP_SEQNO_UNDEFINED (-1) + +/*! wsrep 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_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; + +/*! + * @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 library 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 *); + +/*! + * UUID type - for all unique IDs + */ +typedef struct wsrep_uuid { + uint8_t uuid[16]; +} wsrep_uuid_t; + +/*! Undefined UUID */ +static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; + +/*! + * Scan UUID from string + * @return length of UUID string representation or negative error code + */ +extern ssize_t +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 ssize_t +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 + +/*! + * 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_uuid_t uuid; //!< global state UUID + wsrep_seqno_t seqno; //!< global state seqno + wsrep_seqno_t view; //!< global view number + wsrep_view_status_t status; //!< view status + bool 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 in 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 void (*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, + ssize_t* sst_req_len); + +/*! + * @brief apply callback + * + * This handler is called from wsrep library to apply replicated write set + * 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 write set + * @param size data buffer size + * @param seqno global seqno part of the write set to be applied + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_NOT_IMPLEMENTED appl. does not support the write set format + * @retval WSREP_ERROR failed to apply the write set + */ +typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, + const void* data, + size_t size, + wsrep_seqno_t seqno); + +/*! + * @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 seqno global seqno part of the write set to be committed + * @param commit true - commit writeset, false - rollback writeset + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_ERROR call failed + */ +typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, + wsrep_seqno_t seqno, + bool commit); + +/*! + * @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 uuid current state uuid on this node + * @param seqno current state seqno 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 + * @return 0 for success or negative error code + */ +typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, + void* recv_ctx, + const void* msg, + size_t msg_len, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno, + const char* state, + size_t state_len, + bool 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, used as arguments for wsrep_init() + */ +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_uuid_t* state_uuid; //!< Application state sequence UUID + wsrep_seqno_t state_seqno; //!< Applicaiton state sequence number + const char* state; //!< Initial state for wsrep implementation + 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 + + /* 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 _int64; + double _double; + const char* _string; + } value; //!< variable value +}; + + +/*! Key part structure */ +typedef struct wsrep_key_part_ +{ + const void* buf; /*!< Buffer containing key part data */ + size_t buf_len; /*!< Length of buffer */ +} wsrep_key_part_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_key_part_t* key_parts; /*!< Array of key parts */ + size_t key_parts_len; /*!< Length of key parts array */ +} wsrep_key_t; + +/*! Transaction handle struct passed for wsrep transaction handling calls */ +typedef struct wsrep_trx_handle_ +{ + wsrep_trx_id_t trx_id; //!< transaction ID + void* opaque; //!< opaque provider transaction context data +} wsrep_trx_handle_t; + +/*! + * @brief Helper method to reset trx handle state when trx id changes + * + * Instead of passing wsrep_trx_handle_t directly for wsrep calls, + * wrapping handle with this call offloads bookkeeping from + * application. + */ +static inline wsrep_trx_handle_t* wsrep_trx_handle_for_id( + wsrep_trx_handle_t* trx_handle, + wsrep_trx_id_t trx_id) +{ + if (trx_handle->trx_id != trx_id) + { + trx_handle->trx_id = trx_id; + trx_handle->opaque = NULL; + } + return trx_handle; +} + + +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 this wsrep 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 this wsrep handle + */ + uint64_t (*capabilities) (wsrep_t* wsrep); + + /*! + * @brief Passes provider-specific configuration string to provider. + * + * @param wsrep this wsrep 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 this wsrep 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 this wsrep 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. + */ + wsrep_status_t (*connect) (wsrep_t* wsrep, + const char* cluster_name, + const char* cluster_url, + const char* state_donor); + + /*! + * @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 this wsrep 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 this wsrep handle + * @param trx_handle transaction which is committing + * @param conn_id connection ID + * @param app_data application specific applying data + * @param data_len the size of the applying data + * @param flags fine tuning the replication WSREP_FLAG_* + * @param seqno seqno part of the global transaction ID + * + * @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_trx_handle_t* trx_handle, + const void* app_data, + size_t data_len, + uint64_t flags, + wsrep_seqno_t* seqno); + + /*! + * @brief Releases resources after transaction commit. + * + * Ends commit critical section. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @retval WSREP_OK post_commit succeeded + */ + wsrep_status_t (*post_commit) (wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle); + + /*! + * @brief Releases resources after transaction rollback. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @retval WSREP_OK post_rollback succeeded + */ + wsrep_status_t (*post_rollback)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle); + + /*! + * @brief Replay trx as a slave write set + * + * 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 write sets and certification + * test based on write set content can be different to DBMS lock conflicts. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction which is committing + * @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_trx_handle_t* trx_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 this wsrep 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 query in transaction's write set + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param query SQL statement string + * @param timeval time to use for time functions + * @param randseed seed for rand + */ + wsrep_status_t (*append_query)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const char* query, + time_t timeval, + uint32_t randseed); + + /*! + * @brief Appends a row reference in transaction's write set + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param key array of keys + * @param key_len length of the array of keys + * @param shared boolean denoting if key corresponds to shared resource + */ + wsrep_status_t (*append_key)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const wsrep_key_t* key, + size_t key_len, + bool shared); + /*! + * @brief Appends data in transaction's write set + * + * This method can be called any time before commit and it + * appends data block into transaction's write set. + * + * @param wsrep this wsrep handle + * @param trx_handle transaction handle + * @param data data buffer + * @param data_len data buffer length + */ + wsrep_status_t (*append_data)(wsrep_t* wsrep, + wsrep_trx_handle_t* trx_handle, + const void* data, + size_t data_len); + + + /*! + * @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 + * seqno 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 this wsrep handle + * @param seqno location to store global transaction ID + */ + wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_seqno_t* seqno); + + /*! + * @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 this wsrep 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 query and returns success code, which + * caller must check. Total order isolation continues + * until to_execute_end() is called. + * + * @param wsrep this wsrep handle + * @param conn_id connection ID + * @param key array of keys + * @param key_len lenght of the array of keys + * @param query query to be executed + * @param query_len length of the query string + * @param seqno seqno part of the action 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_start)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_key_t* key, + size_t key_len, + const void* query, + size_t query_len, + wsrep_seqno_t* seqno); + + /*! + * @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 this wsrep 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 Signals to wsrep provider that state snapshot has been sent to + * joiner. + * + * @param wsrep this wsrep handle + * @param uuid sequence UUID (group UUID) + * @param seqno sequence number or negative error code of the operation + */ + wsrep_status_t (*sst_sent)(wsrep_t* wsrep, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno); + + /*! + * @brief Signals to wsrep provider that new state snapshot has been received. + * May deadlock if called from sst_prepare_cb. + * + * @param wsrep this wsrep handle + * @param uuid sequence UUID (group UUID) + * @param seqno sequence number or negative error code of the operation + * @param state initial state provided by SST donor + * @param state_len length of state buffer + */ + wsrep_status_t (*sst_received)(wsrep_t* wsrep, + const wsrep_uuid_t* uuid, + wsrep_seqno_t seqno, + const char* state, + size_t state_len); + + + /*! + * @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 this wsrep 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 this wsrep 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 this wsrep handle. + */ + void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); + + /*! + * @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 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, int64_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, int64_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 + */ + bool (*is_locked) (wsrep_t* wsrep, const char* name, int64_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 this wsrep handle + */ + void (*free)(wsrep_t* wsrep); + + void *dlh; //!< reserved for future use + void *ctx; //!< reserved for implemetation private context +}; + +typedef int (*wsrep_loader_fun)(wsrep_t*); + +/*! + * + * @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 new file mode 100644 index 00000000000..6d01ce14b4e --- /dev/null +++ b/wsrep/wsrep_dummy.c @@ -0,0 +1,368 @@ +/* Copyright (C) 2009-2010 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Dummy wsrep API implementation. */ + +#include + +#include "wsrep_api.h" + +/*! Dummy backend context. */ +typedef struct wsrep_dummy +{ + wsrep_log_cb_t log_fn; +} 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); + 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); + 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 __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static char* dummy_options_get (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return NULL; +} + +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_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_trx_handle_t* trx_handle __attribute__((unused)), + const void* query __attribute__((unused)), + const size_t query_len __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_seqno_t* seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_commit( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_rollback( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_replay_trx( + wsrep_t* w, + wsrep_trx_handle_t* trx_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_query( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const char* query __attribute__((unused)), + const time_t timeval __attribute__((unused)), + const uint32_t randseed __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_row_key( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const size_t key_len __attribute__((unused)), + const bool shared __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_data( + wsrep_t* w, + wsrep_trx_handle_t* trx_handle __attribute__((unused)), + const void* data __attribute__((unused)), + size_t data_len __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_causal_read( + wsrep_t* w, + wsrep_seqno_t* seqno __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_len __attribute__((unused)), + const void* query __attribute__((unused)), + const size_t query_len __attribute__((unused)), + wsrep_seqno_t* seqno __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_sst_sent( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + wsrep_seqno_t seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_sst_received( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + const wsrep_seqno_t seqno __attribute__((unused)), + const char* state __attribute__((unused)), + const size_t state_len __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 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)), + int64_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)), + int64_t o __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static bool dummy_is_locked (wsrep_t* w, + const char* s __attribute__((unused)), + int64_t* o __attribute__((unused)), + wsrep_uuid_t* t __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return false; +} + +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_query, + &dummy_append_row_key, + &dummy_append_data, + &dummy_causal_read, + &dummy_free_connection, + &dummy_to_execute_start, + &dummy_to_execute_end, + &dummy_sst_sent, + &dummy_sst_received, + &dummy_snapshot, + &dummy_stats_get, + &dummy_stats_free, + &dummy_pause, + &dummy_resume, + &dummy_desync, + &dummy_resync, + &dummy_lock, + &dummy_unlock, + &dummy_is_locked, + WSREP_NONE, + WSREP_INTERFACE_VERSION, + "Codership Oy ", + &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; + + return 0; +} + diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c new file mode 100644 index 00000000000..b4460658f80 --- /dev/null +++ b/wsrep/wsrep_loader.c @@ -0,0 +1,199 @@ +/* Copyright (C) 2009-2011 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file wsrep implementation loader */ + +#include +#include +#include +#include + +#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 verify(const wsrep_t *wh, const char *iface_ver) +{ + const size_t msg_len = 128; + char msg[msg_len]; + +#define VERIFY(_p) if (!(_p)) { \ + snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ + logger (WSREP_LOG_ERROR, msg); \ + return EINVAL; \ + } + + VERIFY(wh); + VERIFY(wh->version); + + if (strcmp(wh->version, iface_ver)) { + snprintf (msg, msg_len, + "provider interface version mismatch: need '%s', found '%s'", + iface_ver, wh->version); + logger (WSREP_LOG_ERROR, msg); + 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_query); + VERIFY(wh->append_key); + VERIFY(wh->free_connection); + VERIFY(wh->to_execute_start); + VERIFY(wh->to_execute_end); + VERIFY(wh->sst_sent); + VERIFY(wh->sst_received); + VERIFY(wh->stats_get); + VERIFY(wh->stats_free); + 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; +} + + +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; +} + +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; + const size_t msg_len = 1024; + char msg[msg_len + 1]; + msg[msg_len] = 0; + + if (NULL != log_cb) + logger = log_cb; + + if (!(spec && hptr)) + return EINVAL; + + snprintf (msg, msg_len, + "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, msg_len, "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 ((ret = (*dlfun)(*hptr)) != 0) { + snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", + strerror(ret)); + logger (WSREP_LOG_ERROR, msg); + goto out; + } + + if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { + snprintf (msg, msg_len, + "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, msg_len, + "wsrep_load(): %s %s by %s loaded succesfully.", + (*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 new file mode 100644 index 00000000000..c99240cc071 --- /dev/null +++ b/wsrep/wsrep_uuid.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2009 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Helper functions to deal with history UUID string representations */ + +#include +#include +#include + +#include "wsrep_api.h" + +/*! + * Read UUID from string + * @return length of UUID string representation or -EINVAL in case of error + */ +ssize_t +wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) +{ + size_t uuid_len = 0; + size_t uuid_offt = 0; + + while (uuid_len + 1 < str_len) { + if ((4 == uuid_offt || 6 == uuid_offt || 8 == uuid_offt || + 10 == uuid_offt) && 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 + sscanf (str + uuid_len, "%2hhx", uuid->uuid + uuid_offt); + uuid_len += 2; + uuid_offt += 1; + if (sizeof (uuid->uuid) == 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 + */ +ssize_t +wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) +{ + if (str_len > 36) { + const unsigned char* u = uuid->uuid; + 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; + } +} + From 800fa186e3ab77ee93e75e929fe7917983e607e9 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 17:54:42 +0200 Subject: [PATCH 032/294] merged with codership-mysql up to revision 3839 bzr merge -r3810..3839 lp:codership-mysql/5.5 --- cmake/wsrep.cmake | 2 +- scripts/wsrep_sst_rsync.sh | 2 +- scripts/wsrep_sst_xtrabackup.sh | 25 +++++++---- sql/sql_class.cc | 2 +- sql/sys_vars.cc | 2 +- sql/wsrep_hton.cc | 8 +++- sql/wsrep_mysqld.cc | 60 ++++++++++++++++++++------- sql/wsrep_mysqld.h | 12 +++--- sql/wsrep_sst.cc | 4 +- sql/wsrep_utils.cc | 5 ++- sql/wsrep_var.cc | 42 +++++++++++++------ storage/innobase/handler/ha_innodb.cc | 45 ++++++++++++++++++-- storage/innobase/include/rem0rec.h | 5 ++- storage/innobase/rem/rem0rec.c | 45 ++++++++++++-------- 14 files changed, 185 insertions(+), 74 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index bb646028285..c1dc5a54958 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7") +SET(WSREP_PATCH_VERSION "7a") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index d346eb240f2..d510477535c 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -38,7 +38,7 @@ cleanup_joiner() check_pid() { local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + [ -r "$pid_file" ] && ps -p $(cat $pid_file) >/dev/null 2>&1 } check_pid_and_port() diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index dd8532d6485..08cd221c2a2 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -18,8 +18,6 @@ # This is a reference script for Percona XtraBackup-based state snapshot tansfer -TMPDIR="/tmp" - . $(dirname $0)/wsrep_sst_common cleanup_joiner() @@ -34,8 +32,8 @@ cleanup_joiner() check_pid() { - local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + local pid_file="$1" + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 } kill_xtrabackup() @@ -100,6 +98,15 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then + TMPDIR=${TMPDIR:-""} + if [ -z "${TMPDIR}" ]; then + # try to get it from my.cnf + TMPDIR=$(grep -E '^\s*tmpdir' $WSREP_SST_OPT_CONF | \ + awk -F = '{ print $2 }' | sed 's/^\s//g' | sed 's/\s.*//g' ) + # if failed default to /tmp + [ -z "${TMPDIR}" ] && TMPDIR="/tmp" + fi + INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar --defaults-file=${WSREP_SST_OPT_CONF} --socket=${WSREP_SST_OPT_SOCKET}" @@ -114,9 +121,6 @@ then set +e - # This file and variable seems to have no effect and probably should be deleted - XTRABACKUP_PID=$(mktemp --tmpdir wsrep_sst_xtrabackupXXXX.pid) - ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ 2> ${DATA}/innobackup.backup.log | \ ${NC_BIN} ${REMOTEIP} ${NC_PORT} @@ -133,14 +137,17 @@ then exit 22 fi - if check_pid ${XTRABACKUP_PID} + # innobackupex implicitly writes PID to fixed location in ${TMPDIR} + XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" + + if check_pid "${XTRABACKUP_PID}" then wsrep_log_error "xtrabackup process is still running. Killing... " kill_xtrabackup exit 22 fi - rm -f ${XTRABACKUP_PID} + rm -f "${XTRABACKUP_PID}" else # BYPASS STATE="${WSREP_SST_OPT_GTID}" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 68f85ea579f..f25c59db761 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1100,7 +1100,7 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); - wsrep_trx_handle.trx_id = -1; + wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_trx_handle.opaque = NULL; //wsrep_retry_autocommit= ::wsrep_retry_autocommit; wsrep_retry_counter = 0; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1efe724e6f9..e3df253f873 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3662,7 +3662,7 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(glob_hostname), + IN_FS_CHARSET, DEFAULT(wsrep_node_name), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_charptr Sys_wsrep_node_address ( diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index d1be802b286..0d5a9fde7ca 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -59,6 +59,7 @@ void wsrep_cleanup_transaction(THD *thd) } thd->wsrep_exec_mode= LOCAL_STATE; } + thd->wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; } /* @@ -321,7 +322,12 @@ wsrep_run_wsrep_commit( } DBUG_RETURN(WSREP_TRX_OK); } - if (!rcode) { + if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_handle.trx_id) + { + WSREP_WARN("SQL statement was ineffective: %s\n => Skipping replication", thd->query()); + } + else if (!rcode) + { rcode = wsrep->pre_commit( wsrep, (wsrep_conn_id_t)thd->thread_id, diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c31c02e6d33..62397c58a6e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -21,6 +21,7 @@ #include #include "log_event.h" +extern Format_description_log_event *wsrep_format_desc; wsrep_t *wsrep = NULL; my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface @@ -94,6 +95,11 @@ wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; long wsrep_protocol_version = 2; +// 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; + // action execute callback extern wsrep_status_t wsrep_apply_cb(void *ctx, const void* buf, size_t buf_len, @@ -283,13 +289,12 @@ static void wsrep_view_handler_cb (void* app_ctx, * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized * before - OR - it was reinitilized on startup (lp:992840) */ - if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) || - 0 == wsrep_cluster_conf_id) + if (wsrep_startup) { - if (wsrep_init_first()) + if (wsrep_before_SE()) { wsrep_SE_init_grab(); - // Signal init thread to continue + // Signal mysqld init thread to continue wsrep_sst_complete (&cluster_uuid, view->seqno, false); // and wait for SE initialization wsrep_SE_init_wait(); @@ -305,15 +310,14 @@ static void wsrep_view_handler_cb (void* app_ctx, wsrep_set_SE_checkpoint(&xid); new_status= WSREP_MEMBER_JOINED; } - else // just some sanity check + + // just some sanity check + if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t))) { - 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->seqno, - &local_uuid, -1); - abort(); - } + WSREP_ERROR("Undetected state gap. Can't continue."); + wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->seqno, + &local_uuid, -1); + unireg_abort(1); } } @@ -324,7 +328,7 @@ static void wsrep_view_handler_cb (void* app_ctx, } out: - + wsrep_startup= FALSE; local_status.set(new_status, view); } @@ -415,7 +419,7 @@ int wsrep_init() wsrep_ready_set(FALSE); assert(wsrep_provider); - + wsrep_format_desc= new Format_description_log_event(4); wsrep_init_position(); if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) @@ -476,8 +480,10 @@ int wsrep_init() } static char inc_addr[512]= { 0, }; + if ((!wsrep_node_incoming_address || - !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) + { size_t const node_addr_len= strlen(node_addr); if (node_addr_len > 0) { @@ -579,6 +585,9 @@ void wsrep_deinit() provider_name[0]= '\0'; provider_version[0]= '\0'; provider_vendor[0]= '\0'; + + delete wsrep_format_desc; + wsrep_format_desc= NULL; } void wsrep_recover() @@ -1181,6 +1190,21 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list) { int ret= 0; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) + { + WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", + thd->thread_id, thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + return WSREP_TRX_FAIL; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (wsrep_debug && thd->mdl_context.has_locks()) + { + WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", + thd->query(), thd->thread_id); + } if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { @@ -1236,24 +1260,28 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, { mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); WSREP_MDL_LOG(DEBUG, "MDL conflict ", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || granted_thd->wsrep_exec_mode == REPL_RECV) { WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); + ticket->wsrep_report(true); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) { WSREP_DEBUG("mdl granted over FLUSH BF"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) { WSREP_DEBUG("DROP caused BF abort"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1261,6 +1289,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) { WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1268,6 +1297,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else { WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index d1c72e6001f..e9cd227efcf 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -21,6 +21,8 @@ typedef struct st_mysql_show_var SHOW_VAR; #include #include "../wsrep/wsrep_api.h" +#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX + class set_var; class THD; @@ -167,7 +169,7 @@ extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_slave_threads_check CHECK_ARGS; extern bool wsrep_slave_threads_update UPDATE_ARGS; -extern bool wsrep_init_first(); // initialize wsrep before storage +extern bool wsrep_before_SE(); // initialize wsrep before storage // engines (true) or after (false) extern int wsrep_init(); extern void wsrep_deinit(); @@ -206,8 +208,8 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); /* wsrep initialization sequence at startup - * @param first wsrep_init_first() value */ -extern void wsrep_init_startup(bool first); + * @param first wsrep_before_SE() value */ +extern void wsrep_init_startup(bool before); extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); @@ -258,11 +260,11 @@ extern wsrep_seqno_t wsrep_locked_seqno; #define WSREP_LOG_CONFLICT_THD(thd, role) \ WSREP_LOG(sql_print_information, \ "%s: \n " \ - " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %ld\n " \ + " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ " SQL: %s", \ role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ wsrep_thd_query_state_str(thd), \ - wsrep_thd_conflict_state_str(thd), wsrep_thd_trx_seqno(thd), \ + wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \ wsrep_thd_query(thd) \ ); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 53e3bbcfc79..597d0ea087d 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -164,10 +164,10 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; -bool wsrep_init_first() +bool wsrep_before_SE() { return (wsrep_provider != NULL - && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_provider, WSREP_NONE) && strcmp (wsrep_sst_method, WSREP_SST_SKIP) && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index b1bd6de07cf..daba0e4cab2 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -354,8 +354,9 @@ size_t guess_ip (char* buf, size_t buf_len) // try to find the address of the first one #if (TARGET_OS_LINUX == 1) const char cmd[] = "/sbin/ifconfig | " - "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +// "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "grep -E '^[[:space:]]+inet addr:' | grep -m1 -v 'inet addr:127' | " + "sed 's/:/ /' | awk '{ print $3 }'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3136f905109..36d73369c7d 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -24,21 +24,28 @@ #include #define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" +#define WSREP_CLUSTER_NAME "my_wsrep_cluster" -// trx history position to start with -const char* wsrep_start_position = WSREP_START_POSITION_ZERO; -const char* wsrep_provider = WSREP_NONE; -const char* wsrep_provider_options = (const char*)my_memdup("", 1, MYF(MY_WME)); -const char* wsrep_cluster_address = NULL; -const char* wsrep_cluster_name = "my_wsrep_cluster"; -const char* wsrep_node_name = glob_hostname; -static char node_address[256] = { 0, }; -const char* wsrep_node_address = node_address; +const char* wsrep_provider = 0; +const char* wsrep_provider_options = 0; +const char* wsrep_cluster_address = 0; +const char* wsrep_cluster_name = 0; +const char* wsrep_node_name = 0; +static char node_address[256] = { 0, }; +const char* wsrep_node_address = node_address; // ??? +const char* wsrep_start_position = 0; ulong wsrep_OSU_method_options; static int wsrep_thread_change = 0; int wsrep_init_vars() { + wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME)); + wsrep_provider_options= my_strdup("", MYF(MY_WME)); + wsrep_cluster_address = my_strdup("", MYF(MY_WME)); + wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME)); + wsrep_node_name = my_strdup("", MYF(MY_WME)); + wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME)); + global_system_variables.binlog_format=BINLOG_FORMAT_ROW; return 0; } @@ -152,13 +159,13 @@ void wsrep_start_position_init (const char* val) return; } - wsrep_start_position = my_strdup(val, MYF(0)); - wsrep_set_local_position (val); } static bool refresh_provider_options() { + WSREP_DEBUG("refresh_provider_options: %s", + (wsrep_provider_options) ? wsrep_provider_options : "null"); char* opts= wsrep->options_get(wsrep); if (opts) { @@ -225,6 +232,8 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_on_saved= thd->variables.wsrep_on; thd->variables.wsrep_on= false; + WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider); + wsrep_stop_replication(thd); wsrep_deinit(); @@ -250,12 +259,17 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_provider_init (const char* value) { + WSREP_DEBUG("wsrep_provider_init: %s -> %s", + (wsrep_provider) ? wsrep_provider : "null", + (value) ? value : "null"); if (NULL == value || wsrep_provider_verify (value)) { WSREP_ERROR("Bad initial value for wsrep_provider: %s", (value ? value : "")); return; } + + if (wsrep_provider) my_free((void *)wsrep_provider); wsrep_provider = my_strdup(value, MYF(0)); } @@ -327,9 +341,11 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_cluster_address_init (const char* value) { - if (wsrep_cluster_address && wsrep_cluster_address != value) - my_free ((void*)wsrep_cluster_address); + WSREP_DEBUG("wsrep_cluster_address_init: %s -> %s", + (wsrep_cluster_address) ? wsrep_cluster_address : "null", + (value) ? value : "null"); + if (wsrep_cluster_address) my_free ((void*)wsrep_cluster_address); wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ebcb5fdff6e..9070345e161 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7030,9 +7030,15 @@ wsrep_append_foreign_key( mutex_enter(&(dict_sys->mutex)); if (referenced) { +<<<<<<< TREE foreign->referenced_table = dict_table_check_if_in_cache_low( +======= + foreign->referenced_table = + dict_table_get_low( +>>>>>>> MERGE-SOURCE foreign->referenced_table_name_lookup); +<<<<<<< TREE foreign->referenced_index = wsrep_dict_foreign_find_index( foreign->referenced_table, @@ -7040,12 +7046,30 @@ wsrep_append_foreign_key( foreign->n_fields, foreign->foreign_index, TRUE, FALSE); +======= + if (foreign->referenced_table) + { + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } +>>>>>>> MERGE-SOURCE } else { +<<<<<<< TREE foreign->foreign_table = dict_table_check_if_in_cache_low( +======= + foreign->foreign_table = + dict_table_get_low( +>>>>>>> MERGE-SOURCE foreign->foreign_table_name_lookup); +<<<<<<< TREE foreign->foreign_index = wsrep_dict_foreign_find_index( foreign->foreign_table, @@ -7054,6 +7078,18 @@ wsrep_append_foreign_key( foreign->referenced_index, TRUE, FALSE); +======= + if (foreign->foreign_table) + { + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + } +>>>>>>> MERGE-SOURCE } mutex_exit(&(dict_sys->mutex)); } @@ -7072,7 +7108,7 @@ wsrep_append_foreign_key( ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; dict_index_t *idx_target = (referenced) ? - foreign->referenced_index : foreign->foreign_index; + foreign->referenced_index : index; dict_index_t *idx = (referenced) ? UT_LIST_GET_FIRST(foreign->referenced_table->indexes) : UT_LIST_GET_FIRST(foreign->foreign_table->indexes); @@ -7084,8 +7120,8 @@ wsrep_append_foreign_key( ut_a(idx); key[0] = (char)i; - rcode = wsrep_rec_get_primary_key( - &key[1], &len, rec, index, + rcode = wsrep_rec_get_foreign_key( + &key[1], &len, rec, index, idx, wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { WSREP_ERROR( @@ -11448,6 +11484,9 @@ innobase_xa_prepare( to the session variable take effect only in the next transaction */ if (!trx->support_xa) { +#ifdef WITH_WSREP + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); +#endif // WITH_WSREP return(0); } diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 30ef3048ff1..e2af5998899 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -833,11 +833,12 @@ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) #ifdef WITH_WSREP -int wsrep_rec_get_primary_key( +int wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index for foreign table */ + dict_index_t* index_ref, /* in: index for referenced table */ ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ #ifndef UNIV_NONINL diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 44249c3a87e..d921889aaef 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1777,11 +1777,12 @@ rec_print( #endif /* !UNIV_HOTBACKUP */ #ifdef WITH_WSREP int -wsrep_rec_get_primary_key( +wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index in foreign table */ + dict_index_t* index_ref, /* in: index in referenced table */ ibool new_protocol) /* in: protocol > 1 */ { const byte* data; @@ -1793,22 +1794,28 @@ wsrep_rec_get_primary_key( ulint offsets_[REC_OFFS_NORMAL_SIZE]; const ulint* offsets; - ut_ad(index); + ut_ad(index_for); + ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index_for, offsets_, + ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec); - key_parts = dict_index_get_n_unique_in_tree(index); + key_parts = dict_index_get_n_unique_in_tree(index_for); for (i = 0; - i < key_parts && (index->type & DICT_CLUSTERED || i < key_parts - 1); + i < key_parts && + (index_for->type & DICT_CLUSTERED || i < key_parts - 1); i++) { - - dict_field_t* field = dict_index_get_nth_field(index, i); - const dict_col_t* col = dict_field_get_col(field); + dict_field_t* field_f = + dict_index_get_nth_field(index_for, i); + const dict_col_t* col_f = dict_field_get_col(field_f); + dict_field_t* field_r = + dict_index_get_nth_field(index_ref, i); + const dict_col_t* col_r = dict_field_get_col(field_r); data = rec_get_nth_field(rec, offsets, i, &len); if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > @@ -1820,25 +1827,25 @@ wsrep_rec_get_primary_key( } if (len == UNIV_SQL_NULL) { - ut_a(!(col->prtype & DATA_NOT_NULL)); + ut_a(!(col_f->prtype & DATA_NOT_NULL)); *buf++ = 1; key_len++; } else if (!new_protocol) { - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col_f->prtype), buf, len); } else { /* new protocol */ - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } - switch (col->mtype) { + switch (col_f->mtype) { case DATA_INT: { byte* ptr = buf+len; for (;;) { @@ -1850,7 +1857,7 @@ wsrep_rec_get_primary_key( data++; } - if (!(col->prtype & DATA_UNSIGNED)) { + if (!(col_f->prtype & DATA_UNSIGNED)) { buf[len-1] = (byte) (buf[len-1] ^ 128); } @@ -1862,8 +1869,10 @@ wsrep_rec_get_primary_key( /* Copy the actual data */ ut_memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int) + (col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint) + dtype_get_charset_coll(col_f->prtype), buf, len); break; case DATA_BLOB: From d5dc568f9be19c5b3f0d003ec6a71a610fd32212 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 19:20:47 +0200 Subject: [PATCH 033/294] fixes for the merge with codership-mysql, revision 3839 --- BUILD/compile-amd64-wsrep | 0 sql/wsrep_hton.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 31 --------------------------- 3 files changed, 1 insertion(+), 32 deletions(-) mode change 100644 => 100755 BUILD/compile-amd64-wsrep diff --git a/BUILD/compile-amd64-wsrep b/BUILD/compile-amd64-wsrep old mode 100644 new mode 100755 diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 0d5a9fde7ca..0e013556f45 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -240,7 +240,7 @@ wsrep_run_wsrep_commit( while (wsrep_replaying > 0 && thd->wsrep_conflict_state == NO_CONFLICT && - thd->killed == THD::NOT_KILLED && + thd->killed == NOT_KILLED && !shutdown_in_progress) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9070345e161..8829f4e12a5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7030,23 +7030,9 @@ wsrep_append_foreign_key( mutex_enter(&(dict_sys->mutex)); if (referenced) { -<<<<<<< TREE - foreign->referenced_table = - dict_table_check_if_in_cache_low( -======= foreign->referenced_table = dict_table_get_low( ->>>>>>> MERGE-SOURCE foreign->referenced_table_name_lookup); -<<<<<<< TREE - foreign->referenced_index = - wsrep_dict_foreign_find_index( - foreign->referenced_table, - foreign->referenced_col_names, - foreign->n_fields, - foreign->foreign_index, - TRUE, FALSE); -======= if (foreign->referenced_table) { foreign->referenced_index = @@ -7057,28 +7043,12 @@ wsrep_append_foreign_key( foreign->foreign_index, TRUE, FALSE); } ->>>>>>> MERGE-SOURCE } else { -<<<<<<< TREE - foreign->foreign_table = - dict_table_check_if_in_cache_low( -======= foreign->foreign_table = dict_table_get_low( ->>>>>>> MERGE-SOURCE foreign->foreign_table_name_lookup); -<<<<<<< TREE - foreign->foreign_index = - wsrep_dict_foreign_find_index( - foreign->foreign_table, - foreign->foreign_col_names, - foreign->n_fields, - foreign->referenced_index, - TRUE, FALSE); - -======= if (foreign->foreign_table) { foreign->foreign_index = @@ -7089,7 +7059,6 @@ wsrep_append_foreign_key( foreign->referenced_index, TRUE, FALSE); } ->>>>>>> MERGE-SOURCE } mutex_exit(&(dict_sys->mutex)); } From e51a884e9c364a1c5276754871cf7267316c392c Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Feb 2013 22:48:40 +0200 Subject: [PATCH 034/294] References lp:1115708 - merged with wsrep branch, revision 3845 bzr merge -r3840..3845 lp:~codership/codership-mysql/5.5-23 --- cmake/wsrep.cmake | 2 +- sql/mysqld.cc | 9 ++ sql/sys_vars.cc | 4 +- sql/wsrep_mysqld.cc | 41 ++++-- sql/wsrep_mysqld.h | 4 +- sql/wsrep_var.cc | 6 +- storage/innobase/handler/ha_innodb.cc | 11 ++ storage/innobase/rem/rem0rec.c | 5 +- storage/innobase/row/row0upd.c | 179 ++++++++++++++++++++------ 9 files changed, 202 insertions(+), 59 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index c1dc5a54958..69a8c19ab1d 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7a") +SET(WSREP_PATCH_VERSION "7.1") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7d413fe737a..47082f6bb18 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2363,6 +2363,9 @@ static my_socket activate_tcp_port(uint port) socket_errno); unireg_abort(1); } +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) + (void) fcntl(ip_sock, F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ DBUG_RETURN(ip_sock); } @@ -2484,6 +2487,9 @@ static void network_init(void) if (listen(unix_sock,(int) back_log) < 0) sql_print_warning("listen() on Unix socket failed with error %d", socket_errno); +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) + (void) fcntl(unix_sock, F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ } #endif DBUG_PRINT("info",("server started")); @@ -6366,6 +6372,9 @@ void handle_connections_sockets() sleep(1); // Give other threads some time continue; } +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) + (void) fcntl(new_sock, F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ #ifdef HAVE_LIBWRAP { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e3df253f873..81ad091cca6 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3677,9 +3677,7 @@ static Sys_var_charptr Sys_wsrep_node_incoming_address( "wsrep_node_incoming_address", "Client connection address", GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), - NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(wsrep_node_name_check), - ON_UPDATE(wsrep_node_name_update)); + NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_ulong Sys_wsrep_slave_threads( "wsrep_slave_threads", "Number of slave appliers to launch", diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 62397c58a6e..9e1c84b897e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -30,9 +30,6 @@ my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface */ const char* wsrep_data_home_dir = NULL; - -#define WSREP_NODE_INCOMING_AUTO "AUTO" -const char* wsrep_node_incoming_address = WSREP_NODE_INCOMING_AUTO; const char* wsrep_dbug_option = ""; long wsrep_slave_threads = 1; // # of slave action appliers wanted @@ -463,9 +460,9 @@ int wsrep_init() wsrep_data_home_dir = mysql_real_data_home; 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 node_addr_max= sizeof(node_addr); size_t const ret= guess_ip(node_addr, node_addr_max); if (!(ret > 0 && ret < node_addr_max)) { @@ -476,11 +473,11 @@ int wsrep_init() } else { - strncpy(node_addr, wsrep_node_address, sizeof(node_addr) - 1); + strncpy(node_addr, wsrep_node_address, node_addr_max); } - static char inc_addr[512]= { 0, }; - + char inc_addr[512]= { 0, }; + size_t const inc_addr_max= sizeof (inc_addr); if ((!wsrep_node_incoming_address || !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { @@ -490,7 +487,6 @@ int wsrep_init() const char* const colon= strrchr(node_addr, ':'); if (strchr(node_addr, ':') == colon) // 1 or 0 ':' { - size_t const inc_addr_max= sizeof (inc_addr); size_t const ip_len= colon ? colon - node_addr : node_addr_len; if (ip_len + 7 /* :55555\0 */ < inc_addr_max) { @@ -512,22 +508,41 @@ int wsrep_init() } } - // this is to display detected address on SHOW VARIABLES... - wsrep_node_incoming_address = inc_addr; - - if (!strlen(wsrep_node_incoming_address)) + if (!strlen(inc_addr)) { WSREP_WARN("Guessing address for incoming client connections failed. " "Try setting wsrep_node_incoming_address explicitly."); } } + else if (!strchr(wsrep_node_incoming_address, ':')) // no port included + { + if ((int)inc_addr_max <= + snprintf(inc_addr, inc_addr_max, "%s:%u", + wsrep_node_incoming_address,(int)mysqld_port)) + { + WSREP_WARN("Guessing address for incoming client connections: " + "address too long."); + inc_addr[0]= '\0'; + } + } + else + { + size_t const need = strlen (wsrep_node_incoming_address); + if (need >= inc_addr_max) { + WSREP_WARN("wsrep_node_incoming_address too long: %zu", need); + inc_addr[0]= '\0'; + } + else { + memcpy (inc_addr, wsrep_node_incoming_address, need); + } + } struct wsrep_init_args wsrep_args; 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 = wsrep_node_incoming_address; + wsrep_args.node_incoming = inc_addr; wsrep_args.options = (wsrep_provider_options) ? wsrep_provider_options : ""; wsrep_args.proto_ver = wsrep_max_protocol_version; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index e9cd227efcf..0709a2c1f34 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -114,7 +114,9 @@ extern const char* wsrep_provider_vendor; extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); extern void wsrep_free_status(THD *thd); -#define WSREP_SST_ADDRESS_AUTO "AUTO" +#define WSREP_SST_ADDRESS_AUTO "AUTO" +#define WSREP_NODE_INCOMING_AUTO "AUTO" + // MySQL variables funcs #define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 36d73369c7d..c79c0a6a19f 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -31,8 +31,8 @@ const char* wsrep_provider_options = 0; const char* wsrep_cluster_address = 0; const char* wsrep_cluster_name = 0; const char* wsrep_node_name = 0; -static char node_address[256] = { 0, }; -const char* wsrep_node_address = node_address; // ??? +const char* wsrep_node_address = 0; +const char* wsrep_node_incoming_address = 0; const char* wsrep_start_position = 0; ulong wsrep_OSU_method_options; static int wsrep_thread_change = 0; @@ -44,6 +44,8 @@ int wsrep_init_vars() wsrep_cluster_address = my_strdup("", MYF(MY_WME)); wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME)); wsrep_node_name = my_strdup("", MYF(MY_WME)); + wsrep_node_address = my_strdup("", MYF(MY_WME)); + wsrep_node_incoming_address= my_strdup(WSREP_NODE_INCOMING_AUTO, MYF(MY_WME)); wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME)); global_system_variables.binlog_format=BINLOG_FORMAT_ROW; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 42150429078..f0f889cad86 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4978,6 +4978,7 @@ wsrep_store_key_val_for_row( /* Pad the unused space with spaces. */ +#ifdef REMOVED if (true_len < key_len) { ulint pad_len = key_len - true_len; ut_a(!(pad_len % cs->mbminlen)); @@ -4986,6 +4987,7 @@ wsrep_store_key_val_for_row( 0x20 /* space */); buff += pad_len; } +#endif /* REMOVED */ } } @@ -7281,6 +7283,15 @@ ha_innobase::wsrep_append_keys( DBUG_ENTER("wsrep_append_keys"); trx_t *trx = thd_to_trx(thd); + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { + WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", + wsrep_thd_thread_id(thd), + table_share->tmp_table, + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(0); + } + /* if no PK, calculate hash of full row, to be the key value */ if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { uchar digest[16]; diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index d921889aaef..0e8f606c311 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1865,7 +1865,8 @@ wsrep_rec_get_foreign_key( } case DATA_VARCHAR: case DATA_VARMYSQL: - case DATA_BINARY: + case DATA_CHAR: + case DATA_MYSQL: /* Copy the actual data */ ut_memcpy(buf, data, len); wsrep_innobase_mysql_sort( @@ -1876,7 +1877,7 @@ wsrep_rec_get_foreign_key( buf, len); break; case DATA_BLOB: - case DATA_MYSQL: + case DATA_BINARY: memcpy(buf, data, len); break; default: diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 8469d688c5c..c5c51d8283d 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -51,6 +51,9 @@ Created 12/27/1996 Heikki Tuuri #include "pars0sym.h" #include "eval0eval.h" #include "buf0lru.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* What kind of latch and lock can we assume when the control comes to @@ -178,36 +181,6 @@ ulint wsrep_append_foreign_key(trx_t *trx, ibool referenced, ibool shared); -static -void -wsrep_append_fk_reference( -/*=================================*/ - upd_node_t* node, /*!< in: row update node */ - dict_table_t* table, /*!< in: table in question */ - dict_index_t* index, /*!< in: index of the cursor */ - que_thr_t* thr, /*!< in: query thread */ - const rec_t* rec -) { - dict_foreign_t *foreign = UT_LIST_GET_FIRST(table->foreign_list); - - while (foreign) { - if (foreign->foreign_index == index - && node->is_delete) - { - if (DB_SUCCESS != wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - index, - TRUE, TRUE) - ) { - fprintf(stderr, - "WSREP: FK key append failed\n"); - } - } - foreign = UT_LIST_GET_NEXT(foreign_list, foreign); - } -} #endif /* WITH_WSREP */ /*********************************************************************//** @@ -332,6 +305,122 @@ func_exit: return(err); } +#ifdef WITH_WSREP +static +ulint +wsrep_row_upd_check_foreign_constraints( +/*=================================*/ + upd_node_t* node, /*!< in: row update node */ + btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the + cursor position is lost in this function! */ + dict_table_t* table, /*!< in: table in question */ + dict_index_t* index, /*!< in: index of the cursor */ + ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ + que_thr_t* thr, /*!< in: query thread */ + mtr_t* mtr) /*!< in: mtr */ +{ + dict_foreign_t* foreign; + mem_heap_t* heap; + dtuple_t* entry; + trx_t* trx; + const rec_t* rec; + ulint n_ext; + ulint err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); + + rec = btr_pcur_get_rec(pcur); + ut_ad(rec_offs_validate(rec, index, offsets)); + + heap = mem_heap_create(500); + + entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets, + &n_ext, heap); + + mtr_commit(mtr); + + mtr_start(mtr); + + if (trx->dict_operation_lock_mode == 0) { + got_s_lock = TRUE; + + row_mysql_freeze_data_dictionary(trx); + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + /* Note that we may have an update which updates the index + record, but does NOT update the first fields which are + referenced in a foreign key constraint. Then the update does + NOT break the constraint. */ + + if (foreign->foreign_index == index + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + + if (foreign->referenced_table == NULL) { + dict_table_get(foreign->referenced_table_name_lookup, + FALSE); + } + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + (foreign->referenced_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* NOTE that if the thread ends up waiting for a lock + we will release dict_operation_lock temporarily! + But the counter on the table protects 'foreign' from + being dropped while the check is running. */ + + err = row_ins_check_foreign_constraint( + TRUE, foreign, table, entry, thr); + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->referenced_table + ->n_foreign_key_checks_running > 0); + + (foreign->referenced_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + + if (err != DB_SUCCESS) { + + goto func_exit; + } + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + err = DB_SUCCESS; +func_exit: + if (got_s_lock) { + row_mysql_unfreeze_data_dictionary(trx); + } + + mem_heap_free(heap); + + return(err); +} +#endif /* WITH_WSREP */ /*********************************************************************//** Creates an update node for a query graph. @@ -1687,8 +1776,18 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + ulint* offsets = + rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + uint werr = wsrep_row_upd_check_foreign_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, + "WSREP: FK check fail: %u", + werr); } #endif /* WITH_WSREP */ } @@ -1934,8 +2033,12 @@ err_exit: } #ifdef WITH_WSREP if (!referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + uint werr = wsrep_row_upd_check_foreign_constraints( + node, pcur, table, index, offsets, thr, mtr); + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, + "WSREP: FK check fail: %u", + werr); } #endif /* WITH_WSREP */ } @@ -2173,13 +2276,15 @@ row_upd_del_mark_clust_rec( if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ - err = row_upd_check_references_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + uint werr = row_upd_check_references_constraints( + node, pcur, index->table, index, offsets, thr, mtr); + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, "WSREP: FK check fail: %u", werr); } #endif /* WITH_WSREP */ From 96baf431afdcebcab23733e22e99d04f27f17411 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 6 Feb 2013 00:10:54 +0200 Subject: [PATCH 035/294] References lp:1115708 - merged innodb wsrep changes to xtradb between revisions 3809...3845 --- storage/xtradb/handler/ha_innodb.cc | 63 ++++++---- storage/xtradb/include/rem0rec.h | 5 +- storage/xtradb/rem/rem0rec.c | 54 +++++---- storage/xtradb/row/row0upd.c | 179 ++++++++++++++++++++++------ 4 files changed, 218 insertions(+), 83 deletions(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 24e6ae0bb84..f931068404a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5609,6 +5609,7 @@ wsrep_store_key_val_for_row( /* Pad the unused space with spaces. */ +#ifdef REMOVED if (true_len < key_len) { ulint pad_len = key_len - true_len; ut_a(!(pad_len % cs->mbminlen)); @@ -5617,6 +5618,7 @@ wsrep_store_key_val_for_row( 0x20 /* space */); buff += pad_len; } +#endif /* REMOVED */ } } @@ -7988,30 +7990,35 @@ wsrep_append_foreign_key( mutex_enter(&(dict_sys->mutex)); if (referenced) { - foreign->referenced_table = - dict_table_check_if_in_cache_low( + foreign->referenced_table = + dict_table_get_low( foreign->referenced_table_name_lookup); - foreign->referenced_index = - wsrep_dict_foreign_find_index( - foreign->referenced_table, - foreign->referenced_col_names, - foreign->n_fields, - foreign->foreign_index, - TRUE, FALSE); + if (foreign->referenced_table) + { + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } } else { - foreign->foreign_table = - dict_table_check_if_in_cache_low( + foreign->foreign_table = + dict_table_get_low( foreign->foreign_table_name_lookup); - foreign->foreign_index = - wsrep_dict_foreign_find_index( - foreign->foreign_table, - foreign->foreign_col_names, - foreign->n_fields, - foreign->referenced_index, - TRUE, FALSE); - + if (foreign->foreign_table) + { + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + } } mutex_exit(&(dict_sys->mutex)); } @@ -8030,7 +8037,7 @@ wsrep_append_foreign_key( ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; dict_index_t *idx_target = (referenced) ? - foreign->referenced_index : foreign->foreign_index; + foreign->referenced_index : index; dict_index_t *idx = (referenced) ? UT_LIST_GET_FIRST(foreign->referenced_table->indexes) : UT_LIST_GET_FIRST(foreign->foreign_table->indexes); @@ -8042,8 +8049,8 @@ wsrep_append_foreign_key( ut_a(idx); key[0] = (char)i; - rcode = wsrep_rec_get_primary_key( - &key[1], &len, rec, index, + rcode = wsrep_rec_get_foreign_key( + &key[1], &len, rec, index, idx, wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { WSREP_ERROR( @@ -8192,6 +8199,15 @@ ha_innobase::wsrep_append_keys( DBUG_ENTER("wsrep_append_keys"); trx_t *trx = thd_to_trx(thd); + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { + WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", + wsrep_thd_thread_id(thd), + table_share->tmp_table, + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(0); + } + /* if no PK, calculate hash of full row, to be the key value */ if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { uchar digest[16]; @@ -12516,6 +12532,9 @@ innobase_xa_prepare( to the session variable take effect only in the next transaction */ if (!trx->support_xa) { +#ifdef WITH_WSREP + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); +#endif // WITH_WSREP return(0); } diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h index 30ef3048ff1..e2af5998899 100644 --- a/storage/xtradb/include/rem0rec.h +++ b/storage/xtradb/include/rem0rec.h @@ -833,11 +833,12 @@ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) #ifdef WITH_WSREP -int wsrep_rec_get_primary_key( +int wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index for foreign table */ + dict_index_t* index_ref, /* in: index for referenced table */ ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ #ifndef UNIV_NONINL diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index 0cee1ffb3c8..0e8f606c311 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -1777,11 +1777,12 @@ rec_print( #endif /* !UNIV_HOTBACKUP */ #ifdef WITH_WSREP int -wsrep_rec_get_primary_key( +wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index in foreign table */ + dict_index_t* index_ref, /* in: index in referenced table */ ibool new_protocol) /* in: protocol > 1 */ { const byte* data; @@ -1793,26 +1794,32 @@ wsrep_rec_get_primary_key( ulint offsets_[REC_OFFS_NORMAL_SIZE]; const ulint* offsets; - ut_ad(index); + ut_ad(index_for); + ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index_for, offsets_, + ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec); - key_parts = dict_index_get_n_unique_in_tree(index); + key_parts = dict_index_get_n_unique_in_tree(index_for); for (i = 0; - i < key_parts && (index->type & DICT_CLUSTERED || i < key_parts - 1); + i < key_parts && + (index_for->type & DICT_CLUSTERED || i < key_parts - 1); i++) { - - dict_field_t* field = dict_index_get_nth_field(index, i); - const dict_col_t* col = dict_field_get_col(field); + dict_field_t* field_f = + dict_index_get_nth_field(index_for, i); + const dict_col_t* col_f = dict_field_get_col(field_f); + dict_field_t* field_r = + dict_index_get_nth_field(index_ref, i); + const dict_col_t* col_r = dict_field_get_col(field_r); data = rec_get_nth_field(rec, offsets, i, &len); - if (key_len + len > ((col->prtype & DATA_NOT_NULL) ? - *buf_len : *buf_len - 1)) { + if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > + *buf_len) { fprintf (stderr, "WSREP: FK key len exceeded %lu %lu %lu\n", key_len, len, *buf_len); @@ -1820,25 +1827,25 @@ wsrep_rec_get_primary_key( } if (len == UNIV_SQL_NULL) { - ut_a(!(col->prtype & DATA_NOT_NULL)); + ut_a(!(col_f->prtype & DATA_NOT_NULL)); *buf++ = 1; key_len++; } else if (!new_protocol) { - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col_f->prtype), buf, len); } else { /* new protocol */ - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } - switch (col->mtype) { + switch (col_f->mtype) { case DATA_INT: { byte* ptr = buf+len; for (;;) { @@ -1850,7 +1857,7 @@ wsrep_rec_get_primary_key( data++; } - if (!(col->prtype & DATA_UNSIGNED)) { + if (!(col_f->prtype & DATA_UNSIGNED)) { buf[len-1] = (byte) (buf[len-1] ^ 128); } @@ -1858,16 +1865,19 @@ wsrep_rec_get_primary_key( } case DATA_VARCHAR: case DATA_VARMYSQL: - case DATA_BINARY: + case DATA_CHAR: + case DATA_MYSQL: /* Copy the actual data */ ut_memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int) + (col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint) + dtype_get_charset_coll(col_f->prtype), buf, len); break; case DATA_BLOB: - case DATA_MYSQL: + case DATA_BINARY: memcpy(buf, data, len); break; default: diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 2dc1430d5b9..27861adf8a3 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -51,6 +51,9 @@ Created 12/27/1996 Heikki Tuuri #include "pars0sym.h" #include "eval0eval.h" #include "buf0lru.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* What kind of latch and lock can we assume when the control comes to @@ -178,36 +181,6 @@ ulint wsrep_append_foreign_key(trx_t *trx, ibool referenced, ibool shared); -static -void -wsrep_append_fk_reference( -/*=================================*/ - upd_node_t* node, /*!< in: row update node */ - dict_table_t* table, /*!< in: table in question */ - dict_index_t* index, /*!< in: index of the cursor */ - que_thr_t* thr, /*!< in: query thread */ - const rec_t* rec -) { - dict_foreign_t *foreign = UT_LIST_GET_FIRST(table->foreign_list); - - while (foreign) { - if (foreign->foreign_index == index - && node->is_delete) - { - if (DB_SUCCESS != wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - rec, - index, - TRUE, TRUE) - ) { - fprintf(stderr, - "WSREP: FK key append failed\n"); - } - } - foreign = UT_LIST_GET_NEXT(foreign_list, foreign); - } -} #endif /* WITH_WSREP */ /*********************************************************************//** @@ -332,6 +305,122 @@ func_exit: return(err); } +#ifdef WITH_WSREP +static +ulint +wsrep_row_upd_check_foreign_constraints( +/*=================================*/ + upd_node_t* node, /*!< in: row update node */ + btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the + cursor position is lost in this function! */ + dict_table_t* table, /*!< in: table in question */ + dict_index_t* index, /*!< in: index of the cursor */ + ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ + que_thr_t* thr, /*!< in: query thread */ + mtr_t* mtr) /*!< in: mtr */ +{ + dict_foreign_t* foreign; + mem_heap_t* heap; + dtuple_t* entry; + trx_t* trx; + const rec_t* rec; + ulint n_ext; + ulint err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); + + rec = btr_pcur_get_rec(pcur); + ut_ad(rec_offs_validate(rec, index, offsets)); + + heap = mem_heap_create(500); + + entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets, + &n_ext, heap); + + mtr_commit(mtr); + + mtr_start(mtr); + + if (trx->dict_operation_lock_mode == 0) { + got_s_lock = TRUE; + + row_mysql_freeze_data_dictionary(trx); + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + /* Note that we may have an update which updates the index + record, but does NOT update the first fields which are + referenced in a foreign key constraint. Then the update does + NOT break the constraint. */ + + if (foreign->foreign_index == index + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + + if (foreign->referenced_table == NULL) { + dict_table_get(foreign->referenced_table_name_lookup, + FALSE); + } + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + (foreign->referenced_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* NOTE that if the thread ends up waiting for a lock + we will release dict_operation_lock temporarily! + But the counter on the table protects 'foreign' from + being dropped while the check is running. */ + + err = row_ins_check_foreign_constraint( + TRUE, foreign, table, entry, thr); + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->referenced_table + ->n_foreign_key_checks_running > 0); + + (foreign->referenced_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + + if (err != DB_SUCCESS) { + + goto func_exit; + } + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + err = DB_SUCCESS; +func_exit: + if (got_s_lock) { + row_mysql_unfreeze_data_dictionary(trx); + } + + mem_heap_free(heap); + + return(err); +} +#endif /* WITH_WSREP */ /*********************************************************************//** Creates an update node for a query graph. @@ -1706,8 +1795,18 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + ulint* offsets = + rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + uint werr = wsrep_row_upd_check_foreign_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, + "WSREP: FK check fail: %u", + werr); } #endif /* WITH_WSREP */ } @@ -1955,8 +2054,12 @@ err_exit: } #ifdef WITH_WSREP if (!referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + uint werr = wsrep_row_upd_check_foreign_constraints( + node, pcur, table, index, offsets, thr, mtr); + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, + "WSREP: FK check fail: %u", + werr); } #endif /* WITH_WSREP */ } @@ -2199,13 +2302,15 @@ row_upd_del_mark_clust_rec( if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ - err = row_upd_check_references_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - wsrep_append_fk_reference(node, index->table, - index, thr, rec); + uint werr = row_upd_check_references_constraints( + node, pcur, index->table, index, offsets, thr, mtr); + if (wsrep_debug && werr != DB_SUCCESS) + fprintf (stderr, "WSREP: FK check fail: %u", werr); } #endif /* WITH_WSREP */ From f64a2c9970e4db2ab0880b8eb58d2329bd1bb81a Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 6 Feb 2013 00:46:10 +0200 Subject: [PATCH 036/294] wsrep build scripts --- BUILD/compile-amd64-debug-wsrep | 0 BUILD/compile-pentium-debug-wsrep | 0 BUILD/compile-pentium-wsrep | 0 BUILD/compile-pentium64-wsrep | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 BUILD/compile-amd64-debug-wsrep mode change 100644 => 100755 BUILD/compile-pentium-debug-wsrep mode change 100644 => 100755 BUILD/compile-pentium-wsrep mode change 100644 => 100755 BUILD/compile-pentium64-wsrep diff --git a/BUILD/compile-amd64-debug-wsrep b/BUILD/compile-amd64-debug-wsrep old mode 100644 new mode 100755 diff --git a/BUILD/compile-pentium-debug-wsrep b/BUILD/compile-pentium-debug-wsrep old mode 100644 new mode 100755 diff --git a/BUILD/compile-pentium-wsrep b/BUILD/compile-pentium-wsrep old mode 100644 new mode 100755 diff --git a/BUILD/compile-pentium64-wsrep b/BUILD/compile-pentium64-wsrep old mode 100644 new mode 100755 From 3f847afe4c7b1a26b73a4c9e38362278ea003640 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 7 Feb 2013 17:40:32 +0200 Subject: [PATCH 037/294] References: MDEV-4142 Merged revision 3846 from lp:codership-mysql/5.5-23 --- storage/innobase/row/row0upd.c | 4 ++-- storage/xtradb/row/row0upd.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index c5c51d8283d..91a215b636b 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -2276,12 +2276,12 @@ row_upd_del_mark_clust_rec( if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ - err = wsrep_row_upd_check_foreign_constraints( + err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - uint werr = row_upd_check_references_constraints( + uint werr = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); if (wsrep_debug && werr != DB_SUCCESS) fprintf (stderr, "WSREP: FK check fail: %u", werr); diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 27861adf8a3..89e70d1030a 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -2302,12 +2302,12 @@ row_upd_del_mark_clust_rec( if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ - err = wsrep_row_upd_check_foreign_constraints( + err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - uint werr = row_upd_check_references_constraints( + uint werr = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); if (wsrep_debug && werr != DB_SUCCESS) fprintf (stderr, "WSREP: FK check fail: %u", werr); From 53f5ea24313909f0aebaa5640a16edce4bbe1390 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 7 Feb 2013 19:01:19 +0100 Subject: [PATCH 038/294] restore changes that were lost in the merge --- cmake/wsrep.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 69a8c19ab1d..902ba8d5c30 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -47,13 +47,13 @@ SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" ) -OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" OFF) +OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ON) IF (WITH_WSREP) SET(WSREP_C_FLAGS "-DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WSREP_C_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WSREP_C_FLAGS}") SET(COMPILATION_COMMENT "${COMPILATION_COMMENT}, wsrep_${WSREP_VERSION}") - SET(WITH_EMBEDDED_SERVER OFF) + SET(WITH_EMBEDDED_SERVER OFF CACHE INTERNAL "" FORCE) ENDIF() # From 2a6aa0a312ed44f0806d878a8f5b315b71ab1cfd Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Fri, 15 Feb 2013 15:51:02 +0200 Subject: [PATCH 039/294] References https://mariadb.atlassian.net/browse/MDEV-4136 Fixes to stop wsrep replicator when thread pool scheduler is in use --- sql/mysqld.cc | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 47082f6bb18..a9090316864 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4853,6 +4853,14 @@ pthread_handler_t start_wsrep_THD(void *arg) // 'Error in my_thread_global_end(): 2 threads didn't exit' // at server shutdown } + + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_lock(&LOCK_thread_count); + delete thd; + thread_count--; + mysql_mutex_unlock(&LOCK_thread_count); + } return(NULL); } @@ -5175,7 +5183,14 @@ void wsrep_wait_appliers_close(THD *thd) // This gotta be fixed in a more elegant manner if we gonna have arbitrary // number of non-applier wsrep threads. { - mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_unlock(&LOCK_thread_count); + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); DBUG_PRINT("quit",("One applier died (count=%u)",thread_count)); } mysql_mutex_unlock(&LOCK_thread_count); @@ -5185,7 +5200,14 @@ void wsrep_wait_appliers_close(THD *thd) mysql_mutex_lock(&LOCK_thread_count); while (have_wsrep_appliers(thd) > 0) { - mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_unlock(&LOCK_thread_count); + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); } mysql_mutex_unlock(&LOCK_thread_count); From 7144f7f2d17bdf03fbd28dfdd6b4d6bf689e7aaa Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sun, 17 Feb 2013 00:22:40 +0200 Subject: [PATCH 040/294] References https://mariadb.atlassian.net/browse/MDEV-4176 Avoiding ha_kill_query for aborts initiated by replicator --- sql/sql_class.cc | 11 ++++++++--- sql/sql_class.h | 1 + sql/sql_parse.cc | 4 ++++ sql/wsrep_mysqld.h | 2 +- storage/innobase/handler/ha_innodb.cc | 10 +++++----- storage/innobase/handler/ha_innodb.h | 2 +- storage/xtradb/handler/ha_innodb.cc | 10 +++++----- storage/xtradb/handler/ha_innodb.h | 2 +- 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0cc3732806e..974ad8a2632 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -893,10 +893,11 @@ extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) { thd->wsrep_last_query_id= id; } -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal) { if (signal) { + thd->wsrep_bf_thd = bf_thd; mysql_mutex_lock(&thd->LOCK_thd_data); thd->awake(KILL_QUERY); mysql_mutex_unlock(&thd->LOCK_thd_data); @@ -1114,7 +1115,7 @@ THD::THD() wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_status_vars = 0; wsrep_mysql_replicated = 0; - + wsrep_bf_thd = NULL; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1469,6 +1470,7 @@ void THD::init(void) wsrep_seqno_changed= false; wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_mysql_replicated = 0; + wsrep_bf_thd = NULL; #endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; @@ -1836,8 +1838,11 @@ void THD::awake(killed_state state_to_set) /* Interrupt target waiting inside a storage engine. */ if (state_to_set != NOT_KILLED) +#ifdef WITH_WSREP + if (!wsrep_bf_thd || wsrep_bf_thd->wsrep_exec_mode == LOCAL_STATE) +#else ha_kill_query(this, thd_kill_level(this)); - +#endif /* WITH_WSREP */ /* Broadcast a condition to kick the target if it is waiting on it. */ if (mysys_var) { diff --git a/sql/sql_class.h b/sql/sql_class.h index a216c2146fd..fc3d3087f2c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2376,6 +2376,7 @@ public: wsrep_consistency_check; wsrep_stats_var* wsrep_status_vars; int wsrep_mysql_replicated; + THD* wsrep_bf_thd; #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 27f68698ef5..b21826d735f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -786,6 +786,7 @@ bool do_command(THD *thd) else if (thd->wsrep_conflict_state == ABORTED) { thd->store_globals(); + thd->wsrep_bf_thd = NULL; } thd->wsrep_query_state= QUERY_EXEC; @@ -1059,6 +1060,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->mysys_var->abort = 0; thd->wsrep_conflict_state = NO_CONFLICT; thd->wsrep_retry_counter = 0; + thd->wsrep_bf_thd = NULL; /* Increment threads running to compensate dec_thread_running() called after dispatch_end label. @@ -6131,6 +6133,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); } thd->wsrep_conflict_state= ABORTED; + thd->wsrep_bf_thd = NULL; wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); break; default: @@ -7992,6 +7995,7 @@ static void wsrep_client_rollback(THD *thd) } mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_conflict_state= ABORTED; + thd->wsrep_bf_thd = NULL; } static enum wsrep_status wsrep_apply_sql( diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 0709a2c1f34..bb1695563cf 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -205,7 +205,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" char * wsrep_thd_query(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f0f889cad86..9c663dd5a33 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12376,7 +12376,7 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, WSREP_DEBUG("victim %llu in MUST ABORT state", victim_trx->id); wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); DBUG_RETURN(0); break; case ABORTED: @@ -12395,7 +12395,7 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, WSREP_DEBUG("kill query for: %ld", wsrep_thd_thread_id(thd)); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", victim_trx->id); @@ -12448,14 +12448,14 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, lock_cancel_waiting_and_release(wait_lock); } - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); } else { /* abort currently executing query */ DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", wsrep_thd_thread_id(thd))); WSREP_DEBUG("kill query for: %ld", wsrep_thd_thread_id(thd)); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); /* for BF thd, we need to prevent him from committing */ if (wsrep_thd_exec_mode(thd) == REPL_RECV) { @@ -12546,7 +12546,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, 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_awake(bf_thd, victim_thd, signal); } DBUG_RETURN(-1); } diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 052e215deca..6777221ff13 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -328,7 +328,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" char * wsrep_thd_query(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); #endif typedef struct trx_struct trx_t; /********************************************************************//** diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index f931068404a..e0dbfcca737 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13502,7 +13502,7 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) WSREP_DEBUG("victim %llu in MUST ABORT state", victim_trx->id); wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); DBUG_RETURN(0); break; case ABORTED: @@ -13521,7 +13521,7 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) WSREP_DEBUG("kill query for: %ld", wsrep_thd_thread_id(thd)); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", victim_trx->id); @@ -13574,14 +13574,14 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) lock_cancel_waiting_and_release(wait_lock); } - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); } else { /* abort currently executing query */ DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", wsrep_thd_thread_id(thd))); WSREP_DEBUG("kill query for: %ld", wsrep_thd_thread_id(thd)); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(bf_thd, thd, signal); /* for BF thd, we need to prevent him from committing */ if (wsrep_thd_exec_mode(thd) == REPL_RECV) { @@ -13672,7 +13672,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, 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_awake(bf_thd, victim_thd, signal); } DBUG_RETURN(-1); } diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index fc10b0ca338..851fbb828e4 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -404,7 +404,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" char * wsrep_thd_query(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); #endif typedef struct trx_struct trx_t; /********************************************************************//** From 91cd73104f0755a8c91becc3300aaa8311752e3d Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 21 Feb 2013 10:16:47 +0200 Subject: [PATCH 041/294] References https://mariadb.atlassian.net/browse/MDEV-4185 - thread terminate was blocked for non-wsrep threads --- sql/sql_class.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 974ad8a2632..319f8b15ae1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1840,9 +1840,9 @@ void THD::awake(killed_state state_to_set) if (state_to_set != NOT_KILLED) #ifdef WITH_WSREP if (!wsrep_bf_thd || wsrep_bf_thd->wsrep_exec_mode == LOCAL_STATE) -#else - ha_kill_query(this, thd_kill_level(this)); #endif /* WITH_WSREP */ + ha_kill_query(this, thd_kill_level(this)); + /* Broadcast a condition to kick the target if it is waiting on it. */ if (mysys_var) { From 68154e62b1b3d0ff2552b8503523d81459c30327 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 25 Feb 2013 23:05:31 +0400 Subject: [PATCH 042/294] MDEV-4202: innodb.innodb-autoinc fails due to missing wsrep-specific variable in the result file --- mysql-test/suite/innodb/r/innodb-autoinc.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index 55548c40752..778fb3ce913 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -1295,6 +1295,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (2147483648, 'a'); SHOW CREATE TABLE t1; From 2b0f16c577130c5085c94d99273570fd583af7d1 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 26 Feb 2013 01:03:21 +0200 Subject: [PATCH 043/294] References: https://mariadb.atlassian.net/browse/MDEV-4179 https://bugs.launchpad.net/codership-mysql/+bug/1130888 https://bugs.launchpad.net/codership-mysql/+bug/1019473 Merged revisions 3847-3850 from lp:~codership/codership-mysql/5.5-23 --- cmake/wsrep.cmake | 2 +- sql/mysqld.cc | 15 ++--- storage/innobase/handler/ha_innodb.cc | 83 ++++++++++++++++++++++++++- storage/innobase/lock/lock0lock.c | 20 +++++-- storage/innobase/row/row0upd.c | 62 ++++++++++++++++---- storage/xtradb/handler/ha_innodb.cc | 83 ++++++++++++++++++++++++++- storage/xtradb/lock/lock0lock.c | 20 +++++-- storage/xtradb/row/row0upd.c | 62 ++++++++++++++++---- 8 files changed, 299 insertions(+), 48 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 902ba8d5c30..3337a2a93df 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7.1") +SET(WSREP_PATCH_VERSION "7.3") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a9090316864..0d4b1168bf6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5590,6 +5590,14 @@ int mysqld_main(int argc, char **argv) my_str_malloc= &my_str_malloc_mysqld; my_str_free= &my_str_free_mysqld; +#ifdef WITH_WSREP /* WSREP AFTER SE */ + if (wsrep_recovery) + { + select_thread_in_use= 0; + wsrep_recover(); + unireg_abort(0); + } +#endif /* WITH_WSREP */ /* init signals & alarm After this we can't quit by a simple unireg_abort @@ -5662,13 +5670,6 @@ int mysqld_main(int argc, char **argv) unireg_abort(1); #ifdef WITH_WSREP /* WSREP AFTER SE */ - if (wsrep_recovery) - { - select_thread_in_use= 0; - wsrep_recover(); - unireg_abort(0); - } - if (opt_bootstrap) { /*! bootstrap wsrep init was taken care of above */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9c663dd5a33..9c639410fef 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6040,7 +6040,84 @@ calc_row_difference( return(0); } +#ifdef WITH_WSREP +static +int +wsrep_calc_row_hash( +/*================*/ + byte* digest, /*!< in/out: md5 sum */ + const uchar* row, /*!< in: row in MySQL format */ + TABLE* table, /*!< in: table in MySQL data + dictionary */ + row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */ + THD* thd) /*!< in: user thread */ +{ + Field* field; + enum_field_types field_mysql_type; + uint n_fields; + ulint len; + const byte* ptr; + ulint col_type; + uint i; + my_MD5Context ctx; + my_MD5Init (&ctx); + + n_fields = table->s->fields; + + for (i = 0; i < n_fields; i++) { + byte null_byte=0; + byte true_byte=1; + + field = table->field[i]; + + ptr = (const byte*) row + get_field_offset(table, field); + len = field->pack_length(); + + field_mysql_type = field->type(); + + col_type = prebuilt->table->cols[i].mtype; + + switch (col_type) { + + case DATA_BLOB: + ptr = row_mysql_read_blob_ref(&len, ptr, len); + + break; + + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_VARMYSQL: + if (field_mysql_type == MYSQL_TYPE_VARCHAR) { + /* This is a >= 5.0.3 type true VARCHAR where + the real payload data length is stored in + 1 or 2 bytes */ + + ptr = row_mysql_read_true_varchar( + &len, ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); + + } + + break; + default: + ; + } + + if (field->null_ptr && + field_in_record_is_null(table, field, (char*) row)) { + my_MD5Update (&ctx, &null_byte, 1); + } else { + my_MD5Update (&ctx, &true_byte, 1); + my_MD5Update (&ctx, ptr, len); + } + } + my_MD5Final (digest, &ctx); + + return(0); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Updates a row given as a parameter to a new value. Note that we are given whole rows, not just the fields which are updated: this incurs some @@ -7297,14 +7374,15 @@ ha_innobase::wsrep_append_keys( uchar digest[16]; int rcode; - MY_MD5_HASH(digest, (uchar *)record0, table->s->reclength); + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); if ((rcode = wsrep_append_key(thd, trx, table_share, table, (const char*) digest, 16, shared))) { DBUG_RETURN(rcode); } + if (record1) { - MY_MD5_HASH(digest, (uchar *)record1, table->s->reclength); + wsrep_calc_row_hash(digest, record1, table, prebuilt, thd); if ((rcode = wsrep_append_key(thd, trx, table_share, table, (const char*) digest, @@ -7312,6 +7390,7 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(rcode); } } + DBUG_RETURN(0); } if (wsrep_protocol_version == 0) { uint len; diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index bb864937751..1b31d43e2b9 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1827,22 +1827,30 @@ lock_rec_create( */ if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + + if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + lock_rec_print(stderr, c_lock); + lock_rec_print(stderr, c_lock->trx->wait_lock); + } + trx->que_state = TRX_QUE_LOCK_WAIT; lock_set_lock_and_trx_wait(lock, trx); lock_cancel_waiting_and_release(c_lock->trx->wait_lock); - /* trx might not wait for c_lock, but some other lock */ - if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { - fprintf(stderr, "WSREP: c_lock != wait lock\n"); - } + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ if (c_lock->trx->wait_lock == c_lock) { lock_reset_lock_and_trx_wait(lock); } - if (wsrep_debug) - fprintf(stderr, "WSREP: c_lock canceled %llu\n", + if (wsrep_debug) fprintf( + stderr, + "WSREP: c_lock canceled %llu\n", (ulonglong) c_lock->trx->id); + /* have to bail out here to avoid lock_set_lock... */ return(lock); } diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 91a215b636b..0368fd68d78 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -1780,14 +1780,25 @@ row_upd_sec_index_entry( rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, &heap); - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); - - if (wsrep_debug && werr != DB_SUCCESS) + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) + fprintf (stderr, + "WSREP: sec index FK check fail for deadlock"); + break; + default: fprintf (stderr, - "WSREP: FK check fail: %u", - werr); + "WSREP: referenced FK check fail: %lu", + err); + break; + } } #endif /* WITH_WSREP */ } @@ -2033,12 +2044,26 @@ err_exit: } #ifdef WITH_WSREP if (!referenced) { - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); - if (wsrep_debug && werr != DB_SUCCESS) + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: insert FK check fail for deadlock"); + break; + default: fprintf (stderr, - "WSREP: FK check fail: %u", - werr); + "WSREP: referenced FK check fail: %lu", + err); + break; + } + if (err != DB_SUCCESS) { + goto err_exit; + } } #endif /* WITH_WSREP */ } @@ -2281,10 +2306,23 @@ row_upd_del_mark_clust_rec( } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); - if (wsrep_debug && werr != DB_SUCCESS) - fprintf (stderr, "WSREP: FK check fail: %u", werr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: clust rec FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: clust rec referenced FK check fail: %lu", + err); + break; + } } #endif /* WITH_WSREP */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index e0dbfcca737..4d69cf585fe 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6896,7 +6896,84 @@ calc_row_difference( return(0); } +#ifdef WITH_WSREP +static +int +wsrep_calc_row_hash( +/*================*/ + byte* digest, /*!< in/out: md5 sum */ + const uchar* row, /*!< in: row in MySQL format */ + TABLE* table, /*!< in: table in MySQL data + dictionary */ + row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */ + THD* thd) /*!< in: user thread */ +{ + Field* field; + enum_field_types field_mysql_type; + uint n_fields; + ulint len; + const byte* ptr; + ulint col_type; + uint i; + my_MD5Context ctx; + my_MD5Init (&ctx); + + n_fields = table->s->fields; + + for (i = 0; i < n_fields; i++) { + byte null_byte=0; + byte true_byte=1; + + field = table->field[i]; + + ptr = (const byte*) row + get_field_offset(table, field); + len = field->pack_length(); + + field_mysql_type = field->type(); + + col_type = prebuilt->table->cols[i].mtype; + + switch (col_type) { + + case DATA_BLOB: + ptr = row_mysql_read_blob_ref(&len, ptr, len); + + break; + + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_VARMYSQL: + if (field_mysql_type == MYSQL_TYPE_VARCHAR) { + /* This is a >= 5.0.3 type true VARCHAR where + the real payload data length is stored in + 1 or 2 bytes */ + + ptr = row_mysql_read_true_varchar( + &len, ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); + + } + + break; + default: + ; + } + + if (field->null_ptr && + field_in_record_is_null(table, field, (char*) row)) { + my_MD5Update (&ctx, &null_byte, 1); + } else { + my_MD5Update (&ctx, &true_byte, 1); + my_MD5Update (&ctx, ptr, len); + } + } + my_MD5Final (digest, &ctx); + + return(0); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Updates a row given as a parameter to a new value. Note that we are given whole rows, not just the fields which are updated: this incurs some @@ -8213,14 +8290,15 @@ ha_innobase::wsrep_append_keys( uchar digest[16]; int rcode; - MY_MD5_HASH(digest, (uchar *)record0, table->s->reclength); + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); if ((rcode = wsrep_append_key(thd, trx, table_share, table, (const char*) digest, 16, shared))) { DBUG_RETURN(rcode); } + if (record1) { - MY_MD5_HASH(digest, (uchar *)record1, table->s->reclength); + wsrep_calc_row_hash(digest, record1, table, prebuilt, thd); if ((rcode = wsrep_append_key(thd, trx, table_share, table, (const char*) digest, @@ -8228,6 +8306,7 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(rcode); } } + DBUG_RETURN(0); } if (wsrep_protocol_version == 0) { uint len; diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index f3586b40dc8..1dea0acdf59 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -1800,22 +1800,30 @@ lock_rec_create( */ if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + + if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + lock_rec_print(stderr, c_lock); + lock_rec_print(stderr, c_lock->trx->wait_lock); + } + trx->que_state = TRX_QUE_LOCK_WAIT; lock_set_lock_and_trx_wait(lock, trx); lock_cancel_waiting_and_release(c_lock->trx->wait_lock); - /* trx might not wait for c_lock, but some other lock */ - if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { - fprintf(stderr, "WSREP: c_lock != wait lock\n"); - } + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ if (c_lock->trx->wait_lock == c_lock) { lock_reset_lock_and_trx_wait(lock); } - if (wsrep_debug) - fprintf(stderr, "WSREP: c_lock canceled %llu\n", + if (wsrep_debug) fprintf( + stderr, + "WSREP: c_lock canceled %llu\n", (ulonglong) c_lock->trx->id); + /* have to bail out here to avoid lock_set_lock... */ return(lock); } diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 89e70d1030a..7d8e63f0058 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -1799,14 +1799,25 @@ row_upd_sec_index_entry( rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, &heap); - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); - - if (wsrep_debug && werr != DB_SUCCESS) + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) + fprintf (stderr, + "WSREP: sec index FK check fail for deadlock"); + break; + default: fprintf (stderr, - "WSREP: FK check fail: %u", - werr); + "WSREP: referenced FK check fail: %lu", + err); + break; + } } #endif /* WITH_WSREP */ } @@ -2054,12 +2065,26 @@ err_exit: } #ifdef WITH_WSREP if (!referenced) { - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); - if (wsrep_debug && werr != DB_SUCCESS) + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: insert FK check fail for deadlock"); + break; + default: fprintf (stderr, - "WSREP: FK check fail: %u", - werr); + "WSREP: referenced FK check fail: %lu", + err); + break; + } + if (err != DB_SUCCESS) { + goto err_exit; + } } #endif /* WITH_WSREP */ } @@ -2307,10 +2332,23 @@ row_upd_del_mark_clust_rec( } #ifdef WITH_WSREP if (err == DB_SUCCESS && !referenced) { - uint werr = wsrep_row_upd_check_foreign_constraints( + err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); - if (wsrep_debug && werr != DB_SUCCESS) - fprintf (stderr, "WSREP: FK check fail: %u", werr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: clust rec FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: clust rec referenced FK check fail: %lu", + err); + break; + } } #endif /* WITH_WSREP */ From 518ced3a78e027eadb92c66c9f100c0ce16b5851 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 26 Feb 2013 22:19:54 +0200 Subject: [PATCH 044/294] References: https://bugs.launchpad.net/codership-mysql/+bug/1084702 https://bugs.launchpad.net/percona-xtradb-cluster/+bug/1019473 Merged revisions 3851-3852 from lp:~codership/codership-mysql/5.5-23 --- sql/sql_parse.cc | 5 ++- storage/innobase/handler/ha_innodb.cc | 53 +++++++++++++++------------ storage/xtradb/handler/ha_innodb.cc | 53 +++++++++++++++------------ 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b21826d735f..866d45ff701 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3452,8 +3452,9 @@ end_with_restore_list: #ifdef WITH_WSREP for (TABLE_LIST *table= all_tables; table; table= table->next_global) { - if (!thd->is_current_stmt_binlog_format_row() || - !find_temporary_table(thd, table)) + if (!lex->drop_temporary && + (!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, table))) { WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables); break; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9c639410fef..1b211ab4226 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7358,6 +7358,8 @@ ha_innobase::wsrep_append_keys( const uchar* record1) /* in: row in MySQL format */ { DBUG_ENTER("wsrep_append_keys"); + + bool key_appended = false; trx_t *trx = thd_to_trx(thd); if (table_share && table_share->tmp_table != NO_TMP_TABLE) { @@ -7369,29 +7371,6 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(0); } - /* if no PK, calculate hash of full row, to be the key value */ - if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { - uchar digest[16]; - int rcode; - - wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); - if ((rcode = wsrep_append_key(thd, trx, table_share, table, - (const char*) digest, 16, - shared))) { - DBUG_RETURN(rcode); - } - - if (record1) { - wsrep_calc_row_hash(digest, record1, table, prebuilt, thd); - if ((rcode = wsrep_append_key(thd, trx, table_share, - table, - (const char*) digest, - 16, shared))) { - DBUG_RETURN(rcode); - } - } - DBUG_RETURN(0); - } if (wsrep_protocol_version == 0) { uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -7430,6 +7409,8 @@ ha_innobase::wsrep_append_keys( if (key_info->flags & HA_NOSAME || referenced_by_foreign_key()) { + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, @@ -7460,6 +7441,32 @@ ha_innobase::wsrep_append_keys( } } } + + /* if no PK, calculate hash of full row, to be the key value */ + if (!key_appended && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + + if (record1) { + wsrep_calc_row_hash( + digest, record1, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + DBUG_RETURN(0); + } + DBUG_RETURN(0); } #endif diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4d69cf585fe..fc68878d860 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8274,6 +8274,8 @@ ha_innobase::wsrep_append_keys( const uchar* record1) /* in: row in MySQL format */ { DBUG_ENTER("wsrep_append_keys"); + + bool key_appended = false; trx_t *trx = thd_to_trx(thd); if (table_share && table_share->tmp_table != NO_TMP_TABLE) { @@ -8285,29 +8287,6 @@ ha_innobase::wsrep_append_keys( DBUG_RETURN(0); } - /* if no PK, calculate hash of full row, to be the key value */ - if (prebuilt->clust_index_was_generated && wsrep_certify_nonPK) { - uchar digest[16]; - int rcode; - - wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); - if ((rcode = wsrep_append_key(thd, trx, table_share, table, - (const char*) digest, 16, - shared))) { - DBUG_RETURN(rcode); - } - - if (record1) { - wsrep_calc_row_hash(digest, record1, table, prebuilt, thd); - if ((rcode = wsrep_append_key(thd, trx, table_share, - table, - (const char*) digest, - 16, shared))) { - DBUG_RETURN(rcode); - } - } - DBUG_RETURN(0); - } if (wsrep_protocol_version == 0) { uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -8346,6 +8325,8 @@ ha_innobase::wsrep_append_keys( if (key_info->flags & HA_NOSAME || referenced_by_foreign_key()) { + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, @@ -8376,6 +8357,32 @@ ha_innobase::wsrep_append_keys( } } } + + /* if no PK, calculate hash of full row, to be the key value */ + if (!key_appended && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + + if (record1) { + wsrep_calc_row_hash( + digest, record1, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + DBUG_RETURN(0); + } + DBUG_RETURN(0); } #endif From 797482cc54f2fb696a104f882056feefa179e810 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Thu, 28 Feb 2013 21:25:04 -0500 Subject: [PATCH 045/294] Added a MariaDB Galera Cluster section to the beginning of the README. --- README | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/README b/README index 7daeec0495f..d6b9ebee5f4 100644 --- a/README +++ b/README @@ -1,4 +1,57 @@ -This is a release of MariaDB. +This is a release of MariaDB Galera Cluster. + + * https://kb.askmonty.org/en/galera/ + * https://kb.askmonty.org/en/what-is-mariadb-galera-cluster/ + +MariaDB Galera Cluster is a synchronous multi-master cluster for MariaDB. + +Features: + + * Synchronous replication + * Active-active multi-master topology + * Read and write to any cluster node + * Automatic membership control, failed nodes drop from the cluster + * Automatic node joining + * True parallel replication, on row level + * Direct client connections, native MySQL look & feel + +Benefits: + +The above features yield several benefits for a DBMS clustering solution, +including: + +* No slave lag +* No lost transactions +* Both read and write scalability +* Smaller client latencies +* Technology + +MariaDB Galera Cluster uses the Galera library for the replication +implementation. To interface with Galera replication, we have enhanced MariaDB +to support the replication API definition in the wsrep API project. + + * http://codership.com/products/galera_replication + * https://launchpad.net/wsrep + +The implementation of the replication API in MariaDB happens in the open source +MySQL-wsrep project. + + * http://www.codership.com/products/mysql-write-set-replication-project + +See Also: + +* About Galera Replication: + https://kb.askmonty.org/en/about-galera-replication/ +* Codership: Using Galera Cluster: + http://codership.com/content/using-galera-cluster +* Galera Use Cases: + https://kb.askmonty.org/en/galera-use-cases/ +* Getting Started with MariaDB Galera Cluster: + https://kb.askmonty.org/en/getting-started-with-mariadb-galera-cluster/ + +*************************************************************************** + +About MariaDB MariaDB is designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. From 3af84bb4732b1fc998f9fd36e89bc9d2589ce8e6 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Thu, 28 Feb 2013 21:25:56 -0500 Subject: [PATCH 046/294] Removed the obsolete instructions from the MySQL 5.1 manual. Instead provide a link to https://kb.askmonty.org/en/compiling-mariadb-from-source/ --- INSTALL-SOURCE | 8255 +----------------------------------------------- 1 file changed, 2 insertions(+), 8253 deletions(-) diff --git a/INSTALL-SOURCE b/INSTALL-SOURCE index b6f4fe546c7..32cfa9792a7 100644 --- a/INSTALL-SOURCE +++ b/INSTALL-SOURCE @@ -1,8254 +1,3 @@ -Installing and Upgrading MariaDB +Instructions for building MariaDB can be found at: +https://kb.askmonty.org/en/compiling-mariadb-from-source/ -This file contains chapter two of the MySQL manual and describes how -to obtain and install MySQL. The instructions below are generally -applicable to both MySQL and MariaDB, but differ in some particulars -(like, for example, the GPG signing key we use is different). - -Detailed, MariaDB-specific instructions are available at: -http://kb.askmonty.org/en/getting-installing-and-upgrading-mariadb/ - -- - - - - -Chapter 2. Installing and Upgrading MySQL - - This chapter describes how to obtain and install MySQL. A summary - of the procedure follows and later sections provide the details. - If you plan to upgrade an existing version of MySQL to a newer - version rather than install MySQL for the first time, see Section - 2.4.1, "Upgrading MySQL," for information about upgrade procedures - and about issues that you should consider before upgrading. - - If you are interested in migrating to MySQL from another database - system, you may wish to read Section A.8, "MySQL 5.1 FAQ --- - Migration," which contains answers to some common questions - concerning migration issues. - - 1. Determine whether MySQL runs and is supported on your - platform. - Please note that not all platforms are equally suitable for - running MySQL, and that not all platforms on which MySQL is - known to run are officially supported by Oracle Corporation: - - 2. Choose which distribution to install. - Several versions of MySQL are available, and most are - available in several distribution formats. You can choose from - pre-packaged distributions containing binary (precompiled) - programs or source code. When in doubt, use a binary - distribution. We also provide public access to our current - source tree for those who want to see our most recent - developments and help us test new code. To determine which - version and type of distribution you should use, see Section - 2.1.2, "Choosing Which MySQL Distribution to Install." - - 3. Download the distribution that you want to install. - For instructions, see Section 2.1.3, "How to Get MySQL." To - verify the integrity of the distribution, use the instructions - in Section 2.1.4, "Verifying Package Integrity Using MD5 - Checksums or GnuPG." - - 4. Install the distribution. - To install MySQL from a binary distribution, use the - instructions in Section 2.2, "Installing MySQL from Generic - Binaries on Unix/Linux." - To install MySQL from a source distribution or from the - current development source tree, use the instructions in - Section 2.3, "MySQL Installation Using a Source Distribution." - - 5. Perform any necessary post-installation setup. - After installing MySQL, read Section 2.13, "Post-Installation - Setup and Testing." This section contains important - information about making sure the MySQL server is working - properly. It also describes how to secure the initial MySQL - user accounts, which have no passwords until you assign - passwords. The section applies whether you install MySQL using - a binary or source distribution. - - 6. If you want to run the MySQL benchmark scripts, Perl support - for MySQL must be available. See Section 2.15, "Perl - Installation Notes." - -2.1. General Installation Guidance - - The immediately following sections contain the information - necessary to choose, download, and verify your distribution. The - instructions in later sections of the chapter describe how to - install the distribution that you choose. For binary - distributions, see the instructions at Section 2.2, "Installing - MySQL from Generic Binaries on Unix/Linux" or the corresponding - section for your platform if available. To build MySQL from - source, use the instructions in Section 2.3, "MySQL Installation - Using a Source Distribution." - -2.1.1. Operating Systems Supported by MySQL Community Server - - This section lists the operating systems on which MySQL Community - Server is known to run. - -Important - - Oracle Corporation does not necessarily provide official support - for all the platforms listed in this section. For information - about those platforms that are officially supported, see - http://www.mysql.com/support/supportedplatforms.html on the MySQL - Web site. - - We use GNU Autoconf, so it is possible to port MySQL to all modern - systems that have a C++ compiler and a working implementation of - POSIX threads. (Thread support is needed for the server. To - compile only the client code, the only requirement is a C++ - compiler.) - - MySQL has been reported to compile successfully on the following - combinations of operating system and thread package. - - * AIX 4.x, 5.x with native threads. See Section 2.12, - "Installing MySQL on AIX." AIX 5.3 should be upgraded to - technology level 7 (5300-07). - - * FreeBSD 5.x and up with native threads. See Section 2.10, - "Installing MySQL on FreeBSD." - - * HP-UX 11.x with the native threads. See Section 2.11, - "Installing MySQL on HP-UX." - - * Linux, builds on all fairly recent Linux distributions with - glibc 2.3. See Section 2.6, "Installing MySQL on Linux." - - * Mac OS X. See Section 2.7, "Installing MySQL on Mac OS X." - - * Solaris 2.8 on SPARC and x86, including support for native - threads. See Section 2.8.1, "Solaris Notes." - - * Windows 2000, Windows XP, Windows Vista, Windows Server 2003, - and Windows Server 2008. See Section 2.5, "Installing MySQL on - Windows." - - MySQL has also been known to run on other systems in the past. See - Section 2.1, "General Installation Guidance." Some porting effort - might be required for current versions of MySQL on these systems. - - Not all platforms are equally well-suited for running MySQL. How - well a certain platform is suited for a high-load mission-critical - MySQL server is determined by the following factors: - - * General stability of the thread library. A platform may have - an excellent reputation otherwise, but MySQL is only as stable - as the thread library it calls, even if everything else is - perfect. - - * The capability of the kernel and the thread library to take - advantage of symmetric multi-processor (SMP) systems. In other - words, when a process creates a thread, it should be possible - for that thread to run on a CPU different from the original - process. - - * The capability of the kernel and the thread library to run - many threads that acquire and release a mutex over a short - critical region frequently without excessive context switches. - If the implementation of pthread_mutex_lock() is too anxious - to yield CPU time, this hurts MySQL tremendously. If this - issue is not taken care of, adding extra CPUs actually makes - MySQL slower. - - * General file system stability and performance. - - * Table size. If your tables are large, performance is affected - by the ability of the file system to deal with large files and - dealing with them efficiently. - - * Our level of expertise here at Oracle Corporation with the - platform. If we know a platform well, we enable - platform-specific optimizations and fixes at compile time. We - can also provide advice on configuring your system optimally - for MySQL. - - * The amount of testing we have done internally for similar - configurations. - - * The number of users that have run MySQL successfully on the - platform in similar configurations. If this number is high, - the likelihood of encountering platform-specific surprises is - much smaller. - -2.1.2. Choosing Which MySQL Distribution to Install - - When preparing to install MySQL, you should decide which version - to use. MySQL development occurs in several release series, and - you can pick the one that best fits your needs. After deciding - which version to install, you can choose a distribution format. - Releases are available in binary or source format. - -2.1.2.1. Choosing Which Version of MySQL to Install - - The first decision to make is whether you want to use a production - (stable) release or a development release. In the MySQL - development process, multiple release series co-exist, each at a - different stage of maturity: - - * MySQL 5.5 is the current development release series. - - * MySQL 5.1 is the current General Availability (Production) - release series. New releases are issued for bugfixes only; no - new features are being added that could affect stability. - - * MySQL 5.0 is the previous stable (production-quality) release - series. MySQL 5.0 is now at the end of the product lifecycle. - Active development and support for this version has ended. - Extended support for MySQL 5.0 remains available. According to - the http://www.mysql.com/about/legal/lifecycle/, only Security - and Severity Level 1 issues are still being fixed for MySQL - 5.0. - - * MySQL 4.1, 4.0, and 3.23 are old stable (production-quality) - release series. Active development and support for these - versions has ended. - - We do not believe in a complete code freeze because this prevents - us from making bugfixes and other fixes that must be done. By - "somewhat frozen" we mean that we may add small things that should - not affect anything that currently works in a production release. - Naturally, relevant bugfixes from an earlier series propagate to - later series. - - Normally, if you are beginning to use MySQL for the first time or - trying to port it to some system for which there is no binary - distribution, go with the General Availability release series. - Currently, this is MySQL 5.1. All MySQL releases, even those from - development series, are checked with the MySQL benchmarks and an - extensive test suite before being issued. - - If you are running an older system and want to upgrade, but do not - want to take the chance of having a nonseamless upgrade, you - should upgrade to the latest version in the same release series - you are using (where only the last part of the version number is - newer than yours). We have tried to fix only fatal bugs and make - only small, relatively "safe" changes to that version. - - If you want to use new features not present in the production - release series, you can use a version from a development series. - Note that development releases are not as stable as production - releases. - - If you want to use the very latest sources containing all current - patches and bugfixes, you can use one of our Bazaar repositories. - These are not "releases" as such, but are available as previews of - the code on which future releases are to be based. - - The MySQL naming scheme uses release names that consist of three - numbers and a suffix; for example, mysql-5.0.14-rc. The numbers - within the release name are interpreted as follows: - - * The first number (5) is the major version and describes the - file format. All MySQL 5 releases have the same file format. - - * The second number (0) is the release level. Taken together, - the major version and release level constitute the release - series number. - - * The third number (14) is the version number within the release - series. This is incremented for each new release. Usually you - want the latest version for the series you have chosen. - - For each minor update, the last number in the version string is - incremented. When there are major new features or minor - incompatibilities with previous versions, the second number in the - version string is incremented. When the file format changes, the - first number is increased. - - Release names also include a suffix to indicates the stability - level of the release. Releases within a series progress through a - set of suffixes to indicate how the stability level improves. The - possible suffixes are: - - * alpha indicates that the release is for preview purposes only. - Known bugs should be documented in the News section (see - Appendix C, "MySQL Change History"). Most alpha releases - implement new commands and extensions. Active development that - may involve major code changes can occur in an alpha release. - However, we do conduct testing before issuing a release. - - * beta indicates that the release is appropriate for use with - new development. Within beta releases, the features and - compatibility should remain consistent. However, beta releases - may contain numerous and major unaddressed bugs. - All APIs, externally visible structures, and columns for SQL - statements will not change during future beta, release - candidate, or production releases. - - * rc indicates a Release Candidate. Release candidates are - believed to be stable, having passed all of MySQL's internal - testing, and with all known fatal runtime bugs fixed. However, - the release has not been in widespread use long enough to know - for sure that all bugs have been identified. Only minor fixes - are added. (A release candidate is what formerly was known as - a gamma release.) - - * If there is no suffix, it indicates that the release is a - General Availability (GA) or Production release. GA releases - are stable, having successfully passed through all earlier - release stages and are believed to be reliable, free of - serious bugs, and suitable for use in production systems. Only - critical bugfixes are applied to the release. - - MySQL uses a naming scheme that is slightly different from most - other products. In general, it is usually safe to use any version - that has been out for a couple of weeks without being replaced by - a new version within the same release series. - - All releases of MySQL are run through our standard tests and - benchmarks to ensure that they are relatively safe to use. Because - the standard tests are extended over time to check for all - previously found bugs, the test suite keeps getting better. - - All releases have been tested at least with these tools: - - * An internal test suite - The mysql-test directory contains an extensive set of test - cases. We run these tests for every server binary. See Section - 22.1.2, "MySQL Test Suite," for more information about this - test suite. - - * The MySQL benchmark suite - This suite runs a range of common queries. It is also a test - to determine whether the latest batch of optimizations - actually made the code faster. See Section 7.1.3, "The MySQL - Benchmark Suite." - - We also test the newest MySQL version in our internal production - environment, on at least one machine. We have more than 100GB of - data to work with. - -2.1.2.2. Choosing a Distribution Format - - After choosing which version of MySQL to install, you should - decide whether to use a binary distribution or a source - distribution. In most cases, you should probably use a binary - distribution, if one exists for your platform. Binary - distributions are available in native format for many platforms, - such as RPM files for Linux or PKG package installers for Mac OS X - or Solaris. Distributions also are available as Zip archives or - compressed tar files. - - Reasons to choose a binary distribution include the following: - - * Binary distributions generally are easier to install than - source distributions. - - * To satisfy different user requirements, we provide several - servers in binary distributions. mysqld is an optimized server - that is a smaller, faster binary. mysqld-debug is compiled - with debugging support. - Each of these servers is compiled from the same source - distribution, though with different configuration options. All - native MySQL clients can connect to servers from either MySQL - version. - - Under some circumstances, you may be better off installing MySQL - from a source distribution: - - * You want to install MySQL at some explicit location. The - standard binary distributions are ready to run at any - installation location, but you might require even more - flexibility to place MySQL components where you want. - - * You want to configure mysqld to ensure that features are - available that might not be included in the standard binary - distributions. Here is a list of the most common extra options - that you may want to use to ensure feature availability: - - + --with-libwrap - - + --with-named-z-libs (this is done for some of the - binaries) - - + --with-debug[=full] - - * You want to configure mysqld without some features that are - included in the standard binary distributions. For example, - distributions normally are compiled with support for all - character sets. If you want a smaller MySQL server, you can - recompile it with support for only the character sets you - need. - - * You have a special compiler (such as pgcc) or want to use - compiler options that are better optimized for your processor. - Binary distributions are compiled with options that should - work on a variety of processors from the same processor - family. - - * You want to use the latest sources from one of the Bazaar - repositories to have access to all current bugfixes. For - example, if you have found a bug and reported it to the MySQL - development team, the bugfix is committed to the source - repository and you can access it there. The bugfix does not - appear in a release until a release actually is issued. - - * You want to read (or modify) the C and C++ code that makes up - MySQL. For this purpose, you should get a source distribution, - because the source code is always the ultimate manual. - - * Source distributions contain more tests and examples than - binary distributions. - -2.1.2.3. How and When Updates Are Released - - MySQL is evolving quite rapidly and we want to share new - developments with other MySQL users. We try to produce a new - release whenever we have new and useful features that others also - seem to have a need for. - - We also try to help users who request features that are easy to - implement. We take note of what our licensed users want, and we - especially take note of what our support customers want and try to - help them in this regard. - - No one is required to download a new release. The News section - helps you determine whether the new release has something you - really want. See Appendix C, "MySQL Change History." - - We use the following policy when updating MySQL: - - * Enterprise Server releases are meant to appear every 18 - months, supplemented by quarterly service packs and monthly - rapid updates. Community Server releases are meant to appear - 2-3 times per year. - - * Releases are issued within each series. For each release, the - last number in the version is one more than the previous - release within the same series. - - * Binary distributions for some platforms are made by us for - major releases. Other people may make binary distributions for - other systems, but probably less frequently. - - * We make fixes available as soon as we have identified and - corrected small or noncritical but annoying bugs. The fixes - are available in source form immediately from our public - Bazaar repositories, and are included in the next release. - - * If by any chance a security vulnerability or critical bug is - found in a release, our policy is to fix it in a new release - as soon as possible. (We would like other companies to do - this, too!) - -2.1.3. How to Get MySQL - - Check our downloads page at http://dev.mysql.com/downloads/ for - information about the current version of MySQL and for downloading - instructions. For a complete up-to-date list of MySQL download - mirror sites, see http://dev.mysql.com/downloads/mirrors.html. You - can also find information there about becoming a MySQL mirror site - and how to report a bad or out-of-date mirror. - - Our main mirror is located at http://mirrors.sunsite.dk/mysql/. - -2.1.4. Verifying Package Integrity Using MD5 Checksums or GnuPG - - After you have downloaded the MySQL package that suits your needs - and before you attempt to install it, you should make sure that it - is intact and has not been tampered with. There are three means of - integrity checking: - - * MD5 checksums - - * Cryptographic signatures using GnuPG, the GNU Privacy Guard - - * For RPM packages, the built-in RPM integrity verification - mechanism - - The following sections describe how to use these methods. - - If you notice that the MD5 checksum or GPG signatures do not - match, first try to download the respective package one more time, - perhaps from another mirror site. If you repeatedly cannot - successfully verify the integrity of the package, please notify us - about such incidents, including the full package name and the - download site you have been using, at webmaster@mysql.com or - build@mysql.com. Do not report downloading problems using the - bug-reporting system. - -2.1.4.1. Verifying the MD5 Checksum - - After you have downloaded a MySQL package, you should make sure - that its MD5 checksum matches the one provided on the MySQL - download pages. Each package has an individual checksum that you - can verify with the following command, where package_name is the - name of the package you downloaded: -shell> md5sum package_name - - Example: -shell> md5sum mysql-standard-5.1.46-linux-i686.tar.gz -aaab65abbec64d5e907dcd41b8699945 mysql-standard-5.1.46-linux-i686.ta -r.gz - - You should verify that the resulting checksum (the string of - hexadecimal digits) matches the one displayed on the download page - immediately below the respective package. - -Note - - Make sure to verify the checksum of the archive file (for example, - the .zip or .tar.gz file) and not of the files that are contained - inside of the archive. - - Note that not all operating systems support the md5sum command. On - some, it is simply called md5, and others do not ship it at all. - On Linux, it is part of the GNU Text Utilities package, which is - available for a wide range of platforms. You can download the - source code from http://www.gnu.org/software/textutils/ as well. - If you have OpenSSL installed, you can use the command openssl md5 - package_name instead. A Windows implementation of the md5 command - line utility is available from http://www.fourmilab.ch/md5/. - winMd5Sum is a graphical MD5 checking tool that can be obtained - from http://www.nullriver.com/index/products/winmd5sum. - -2.1.4.2. Signature Checking Using GnuPG - - Another method of verifying the integrity and authenticity of a - package is to use cryptographic signatures. This is more reliable - than using MD5 checksums, but requires more work. - - We sign MySQL downloadable packages with GnuPG (GNU Privacy - Guard). GnuPG is an Open Source alternative to the well-known - Pretty Good Privacy (PGP) by Phil Zimmermann. See - http://www.gnupg.org/ for more information about GnuPG and how to - obtain and install it on your system. Most Linux distributions - ship with GnuPG installed by default. For more information about - GnuPG, see http://www.openpgp.org/. - - To verify the signature for a specific package, you first need to - obtain a copy of our public GPG build key, which you can download - from http://keyserver.pgp.com/. The key that you want to obtain is - named build@mysql.com. Alternatively, you can cut and paste the - key directly from the following text: ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.5 (GNU/Linux) - -mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3 -RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ -fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3 -BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW -hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV -K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE -kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI -QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep -rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFj -a2FnZSBzaWduaW5nIGtleSAod3d3Lm15c3FsLmNvbSkgPGJ1aWxkQG15c3FsLmNv -bT6IXQQTEQIAHQULBwoDBAMVAwIDFgIBAheABQJLcC5lBQkQ8/JZAAoJEIxxjTtQ -cuH1oD4AoIcOQ4EoGsZvy06D0Ei5vcsWEy8dAJ4g46i3WEcdSWxMhcBSsPz65sh5 -lohMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAn1mxHijft00bKXvu -cSo/pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJ -YiKJAAoJELb1zU3GuiQ/lpEAoIhpp6BozKI8p6eaabzF5MlJH58pAKCu/ROofK8J -Eg2aLos+5zEYrB/LsrkCDQQ+PqMdEAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/l -xaZoJYc3a6M02WCnHl6ahT2/tBK2w1QI4YFteR47gCvtgb6O1JHffOo2HfLmRDRi -Rjd1DTCHqeyX7CHhcghj/dNRlW2Z0l5QFEcmV9U0Vhp3aFfWC4Ujfs3LU+hkAWzE -7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iM1BzELqX1DY7LwoPEb/O9Rkbf4fm -Le11EzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p -/1oIDznkg/p8kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqq -a8CGrRfsOAJxim63CHfty5mUc5rUSnTslGYEIOCR1BeQauyPZbPDsDD9MZ1ZaSaf -anFvwFG6Llx9xkU7tzq+vKLoWkm4u5xf3vn55VjnSd1aQ9eQnUcXiL4cnBGoTbOW -I39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0Ec8bsM8b3Ev42Lmu -QT5NdKHGwHsXTPtl0klk4bQk4OajHsiy1BMahpT27jWjJlMiJc+IWJ0mghkKHt92 -6s/ymfdf5HkdQ1cyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZ -Whe70YGNPw1yjWJT1IhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4A -n3r1QpVC9yhnW2cSAjq+kr72GX0eAJ4295kl6NxYEuFApmr1+0uUq/SlsQ== -=Mski - ------END PGP PUBLIC KEY BLOCK----- - - To import the build key into your personal public GPG keyring, use - gpg --import. For example, if you have saved the key in a file - named mysql_pubkey.asc, the import command looks like this: -shell> gpg --import mysql_pubkey.asc -gpg: key 5072E1F5: public key "MySQL Package signing key (www.mysql.c -om) " imported -gpg: Total number processed: 1 -gpg: imported: 1 -gpg: no ultimately trusted keys found - - You can also download the key from the public keyserver using the - public key id, 5072E1F5: -shell> gpg --recv-keys 5072E1F5 -gpg: requesting key 5072E1F5 from hkp server subkeys.pgp.net -gpg: key 5072E1F5: "MySQL Package signing key (www.mysql.com) " 2 new signatures -gpg: no ultimately trusted keys found -gpg: Total number processed: 1 -gpg: new signatures: 2 - - If you want to import the key into your RPM configuration to - validate RPM install packages, you should be able to import the - key directly: -shell> rpm --import mysql_pubkey.asc - - If you experience problems, try exporting the key from gpg and - importing: -shell> gpg --export -a 5072e1f5 > 5072e1f5.asc -shell> rpm --import 5072e1f5.asc - - Alternatively, rpm also supports loading the key directly from a - URL, and you cas use this manual page: -shell> rpm --import http://dev.mysql.com/doc/refman/5.1/en/checking-g -pg-signature.html - - After you have downloaded and imported the public build key, - download your desired MySQL package and the corresponding - signature, which also is available from the download page. The - signature file has the same name as the distribution file with an - .asc extension, as shown by the examples in the following table. - Distribution file mysql-standard-5.1.46-linux-i686.tar.gz - Signature file mysql-standard-5.1.46-linux-i686.tar.gz.asc - - Make sure that both files are stored in the same directory and - then run the following command to verify the signature for the - distribution file: -shell> gpg --verify package_name.asc - - Example: -shell> gpg --verify mysql-standard-5.1.46-linux-i686.tar.gz.asc -gpg: Signature made Tue 12 Jul 2005 23:35:41 EST using DSA key ID 507 -2E1F5 -gpg: Good signature from "MySQL Package signing key (www.mysql.com) < -build@mysql.com>" - - The Good signature message indicates that everything is all right. - You can ignore any insecure memory warning you might obtain. - - See the GPG documentation for more information on how to work with - public keys. - -2.1.4.3. Signature Checking Using RPM - - For RPM packages, there is no separate signature. RPM packages - have a built-in GPG signature and MD5 checksum. You can verify a - package by running the following command: -shell> rpm --checksig package_name.rpm - - Example: -shell> rpm --checksig MySQL-server-5.1.46-0.glibc23.i386.rpm -MySQL-server-5.1.46-0.glibc23.i386.rpm: md5 gpg OK - -Note - - If you are using RPM 4.1 and it complains about (GPG) NOT OK - (MISSING KEYS: GPG#5072e1f5), even though you have imported the - MySQL public build key into your own GPG keyring, you need to - import the key into the RPM keyring first. RPM 4.1 no longer uses - your personal GPG keyring (or GPG itself). Rather, it maintains - its own keyring because it is a system-wide application and a - user's GPG public keyring is a user-specific file. To import the - MySQL public key into the RPM keyring, first obtain the key as - described in Section 2.1.4.2, "Signature Checking Using GnuPG." - Then use rpm --import to import the key. For example, if you have - saved the public key in a file named mysql_pubkey.asc, import it - using this command: -shell> rpm --import mysql_pubkey.asc - - If you need to obtain the MySQL public key, see Section 2.1.4.2, - "Signature Checking Using GnuPG." - -2.1.5. Installation Layouts - - This section describes the default layout of the directories - created by installing binary or source distributions provided by - Oracle Corporation. A distribution provided by another vendor - might use a layout different from those shown here. - - Installations created from our Linux RPM distributions result in - files under the following system directories. - Directory Contents of Directory - /usr/bin Client programs and scripts - /usr/sbin The mysqld server - /var/lib/mysql Log files, databases - /usr/share/info Manual in Info format - /usr/share/man Unix manual pages - /usr/include/mysql Include (header) files - /usr/lib/mysql Libraries - /usr/share/mysql Error message and character set files - /usr/share/sql-bench Benchmarks - - On Unix, a tar file binary distribution is installed by unpacking - it at the installation location you choose (typically - /usr/local/mysql) and creates the following directories in that - location. - Directory Contents of Directory - bin Client programs and the mysqld server - data Log files, databases - docs Manual in Info format - man Unix manual pages - include Include (header) files - lib Libraries - scripts mysql_install_db - share/mysql Error message files - sql-bench Benchmarks - - A source distribution is installed after you configure and compile - it. By default, the installation step installs files under - /usr/local, in the following subdirectories. - Directory Contents of Directory - bin Client programs and scripts - include/mysql Include (header) files - Docs Manual in Info, CHM formats - man Unix manual pages - lib/mysql Libraries - libexec The mysqld server - share/mysql Error message files - sql-bench Benchmarks and crash-me test - var Databases and log files - - Within its installation directory, the layout of a source - installation differs from that of a binary installation in the - following ways: - - * The mysqld server is installed in the libexec directory rather - than in the bin directory. - - * The data directory is var rather than data. - - * mysql_install_db is installed in the bin directory rather than - in the scripts directory. - - * The header file and library directories are include/mysql and - lib/mysql rather than include and lib. - - You can create your own binary installation from a compiled source - distribution by executing the scripts/make_binary_distribution - script from the top directory of the source distribution. - -2.2. Installing MySQL from Generic Binaries on Unix/Linux - - This section covers the installation of MySQL binary distributions - that are provided for various platforms in the form of compressed - tar files (files with a .tar.gz extension). - - To obtain MySQL, see Section 2.1.3, "How to Get MySQL." - - Sun Microsystems, Inc. provides a set of binary distributions of - MySQL. In addition to binaries provided in platform-specific - package formats, we offer binary distributions for a number of - platforms in the form of compressed tar files (.tar.gz files). For - Windows distributions, see Section 2.5, "Installing MySQL on - Windows." - - If you want to compile a debug version of MySQL from a source - distribution, you should add --with-debug or --with-debug=full to - the configure command used to configure the distribution and - remove any -fomit-frame-pointer options. - - MySQL tar file binary distributions have names of the form - mysql-VERSION-OS.tar.gz, where VERSION is a number (for example, - 5.1.46), and OS indicates the type of operating system for which - the distribution is intended (for example, pc-linux-i686). - - In addition to these generic packages, we also offer binaries in - platform-specific package formats for selected platforms. See the - platform specific sections for more information, for more - information on how to install these. - - You need the following tools to install a MySQL tar file binary - distribution: - - * GNU gunzip to uncompress the distribution. - - * A reasonable tar to unpack the distribution. GNU tar is known - to work. Some operating systems come with a preinstalled - version of tar that is known to have problems. For example, - the tar provided with early versions of Mac OS X, SunOS 4.x, - Solaris 8, Solaris 9, Solaris 10 and OpenSolaris, and HP-UX - are known to have problems with long file names. On Mac OS X, - you can use the preinstalled gnutar program. On Solaris 10 and - OpenSolaris you can use the preinstalled gtar. On other - systems with a deficient tar, you should install GNU tar - first. - - If you run into problems and need to file a bug report, please use - the instructions in Section 1.7, "How to Report Bugs or Problems." - - The basic commands that you must execute to install and use a - MySQL binary distribution are: -shell> groupadd mysql -shell> useradd -g mysql mysql -shell> cd /usr/local -shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf - -shell> ln -s full-path-to-mysql-VERSION-OS mysql -shell> cd mysql -shell> chown -R mysql . -shell> chgrp -R mysql . -shell> scripts/mysql_install_db --user=mysql -shell> chown -R root . -shell> chown -R mysql data -shell> bin/mysqld_safe --user=mysql & - -Note - - This procedure does not set up any passwords for MySQL accounts. - After following the procedure, proceed to Section 2.13, - "Post-Installation Setup and Testing." - - A more detailed version of the preceding description for - installing a binary distribution follows: - - 1. Add a login user and group for mysqld to run as: -shell> groupadd mysql -shell> useradd -g mysql mysql - These commands add the mysql group and the mysql user. The - syntax for useradd and groupadd may differ slightly on - different versions of Unix, or they may have different names - such as adduser and addgroup. - You might want to call the user and group something else - instead of mysql. If so, substitute the appropriate name in - the following steps. - - 2. Pick the directory under which you want to unpack the - distribution and change location into it. In the following - example, we unpack the distribution under /usr/local. (The - instructions, therefore, assume that you have permission to - create files and directories in /usr/local. If that directory - is protected, you must perform the installation as root.) -shell> cd /usr/local - - 3. Obtain a distribution file using the instructions in Section - 2.1.3, "How to Get MySQL." For a given release, binary - distributions for all platforms are built from the same MySQL - source distribution. - - 4. Unpack the distribution, which creates the installation - directory. Then create a symbolic link to that directory: -shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf - -shell> ln -s full-path-to-mysql-VERSION-OS mysql - The tar command creates a directory named mysql-VERSION-OS. - The ln command makes a symbolic link to that directory. This - lets you refer more easily to the installation directory as - /usr/local/mysql. - With GNU tar, no separate invocation of gunzip is necessary. - You can replace the first line with the following alternative - command to uncompress and extract the distribution: -shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz - - 5. Change location into the installation directory: -shell> cd mysql - You will find several files and subdirectories in the mysql - directory. The most important for installation purposes are - the bin and scripts subdirectories: - - + The bin directory contains client programs and the - server. You should add the full path name of this - directory to your PATH environment variable so that your - shell finds the MySQL programs properly. See Section - 2.14, "Environment Variables." - - + The scripts directory contains the mysql_install_db - script used to initialize the mysql database containing - the grant tables that store the server access - permissions. - - 6. Ensure that the distribution contents are accessible to mysql. - If you unpacked the distribution as mysql, no further action - is required. If you unpacked the distribution as root, its - contents will be owned by root. Change its ownership to mysql - by executing the following commands as root in the - installation directory: -shell> chown -R mysql . -shell> chgrp -R mysql . - The first command changes the owner attribute of the files to - the mysql user. The second changes the group attribute to the - mysql group. - - 7. If you have not installed MySQL before, you must create the - MySQL data directory and initialize the grant tables: -shell> scripts/mysql_install_db --user=mysql - If you run the command as root, include the --user option as - shown. If you run the command while logged in as that user, - you can omit the --user option. - The command should create the data directory and its contents - with mysql as the owner. - After creating or updating the grant tables, you need to - restart the server manually. - - 8. Most of the MySQL installation can be owned by root if you - like. The exception is that the data directory must be owned - by mysql. To accomplish this, run the following commands as - root in the installation directory: -shell> chown -R root . -shell> chown -R mysql data - - 9. If you want MySQL to start automatically when you boot your - machine, you can copy support-files/mysql.server to the - location where your system has its startup files. More - information can be found in the support-files/mysql.server - script itself and in Section 2.13.1.2, "Starting and Stopping - MySQL Automatically." - 10. You can set up new accounts using the bin/mysql_setpermission - script if you install the DBI and DBD::mysql Perl modules. See - Section 4.6.14, "mysql_setpermission --- Interactively Set - Permissions in Grant Tables." For Perl module installation - instructions, see Section 2.15, "Perl Installation Notes." - 11. If you would like to use mysqlaccess and have the MySQL - distribution in some nonstandard location, you must change the - location where mysqlaccess expects to find the mysql client. - Edit the bin/mysqlaccess script at approximately line 18. - Search for a line that looks like this: -$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable - Change the path to reflect the location where mysql actually - is stored on your system. If you do not do this, a Broken pipe - error will occur when you run mysqlaccess. - - After everything has been unpacked and installed, you should test - your distribution. To start the MySQL server, use the following - command: -shell> bin/mysqld_safe --user=mysql & - - If you run the command as root, you must use the --user option as - shown. The value of the option is the name of the login account - that you created in the first step to use for running the server. - If you run the command while logged in as mysql, you can omit the - --user option. - - If the command fails immediately and prints mysqld ended, you can - find some information in the host_name.err file in the data - directory. - - More information about mysqld_safe is given in Section 4.3.2, - "mysqld_safe --- MySQL Server Startup Script." - -Note - - The accounts that are listed in the MySQL grant tables initially - have no passwords. After starting the server, you should set up - passwords for them using the instructions in Section 2.13, - "Post-Installation Setup and Testing." - -2.3. MySQL Installation Using a Source Distribution - - Before you proceed with an installation from source, first check - whether our binary is available for your platform and whether it - works for you. We put a great deal of effort into ensuring that - our binaries are built with the best possible options. - - To obtain a source distribution for MySQL, Section 2.1.3, "How to - Get MySQL." If you want to build MySQL from source on Windows, see - Section 2.5.10, "Installing MySQL from Source on Windows." - - MySQL source distributions are provided as compressed tar archives - and have names of the form mysql-VERSION.tar.gz, where VERSION is - a number like 5.1.46. - - You need the following tools to build and install MySQL from - source: - - * GNU gunzip to uncompress the distribution. - - * A reasonable tar to unpack the distribution. GNU tar is known - to work. Some operating systems come with a preinstalled - version of tar that is known to have problems. For example, - the tar provided with early versions of Mac OS X, SunOS 4.x, - Solaris 8, Solaris 9, Solaris 10 and OpenSolaris, and HP-UX - are known to have problems with long file names. On Mac OS X, - you can use the preinstalled gnutar program. On Solaris 10 and - OpenSolaris you can use the preinstalled gtar. On other - systems with a deficient tar, you should install GNU tar - first. - - * A working ANSI C++ compiler. GCC 3.2 or later, Sun Studio 10 - or later, Visual Studio 2005 or later, and many current - vendor-supplied compilers are known to work. - - * A good make program. GNU make is always recommended and is - sometimes required. (BSD make fails, and vendor-provided make - implementations may fail as well.) If you have problems, use - GNU make 3.75 or newer. - - * libtool 1.5.24 or later is also recommended. - - If you are using a version of gcc recent enough to understand the - -fno-exceptions option, it is very important that you use this - option. Otherwise, you may compile a binary that crashes randomly. - Also use -felide-constructors and -fno-rtti along with - -fno-exceptions. When in doubt, do the following: -CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors \ - -fno-exceptions -fno-rtti" ./configure \ - --prefix=/usr/local/mysql --enable-assembler \ - --with-mysqld-ldflags=-all-static - - On most systems, this gives you a fast and stable binary. - - If you run into problems and need to file a bug report, please use - the instructions in Section 1.7, "How to Report Bugs or Problems." - -2.3.1. Source Installation Overview - - The basic commands that you must execute to install a MySQL source - distribution are: -shell> groupadd mysql -shell> useradd -g mysql mysql -shell> gunzip < mysql-VERSION.tar.gz | tar -xvf - -shell> cd mysql-VERSION -shell> ./configure --prefix=/usr/local/mysql -shell> make -shell> make install -shell> cp support-files/my-medium.cnf /etc/my.cnf -shell> cd /usr/local/mysql -shell> chown -R mysql . -shell> chgrp -R mysql . -shell> bin/mysql_install_db --user=mysql -shell> chown -R root . -shell> chown -R mysql var -shell> bin/mysqld_safe --user=mysql & - - If you start from a source RPM, do the following: -shell> rpmbuild --rebuild --clean MySQL-VERSION.src.rpm - - This makes a binary RPM that you can install. For older versions - of RPM, you may have to replace the command rpmbuild with rpm - instead. - -Note - - This procedure does not set up any passwords for MySQL accounts. - After following the procedure, proceed to Section 2.13, - "Post-Installation Setup and Testing," for post-installation setup - and testing. - - A more detailed version of the preceding description for - installing MySQL from a source distribution follows: - - 1. Add a login user and group for mysqld to run as: -shell> groupadd mysql -shell> useradd -g mysql mysql - These commands add the mysql group and the mysql user. The - syntax for useradd and groupadd may differ slightly on - different versions of Unix, or they may have different names - such as adduser and addgroup. - You might want to call the user and group something else - instead of mysql. If so, substitute the appropriate name in - the following steps. - - 2. Perform the following steps as the mysql user, except as - noted. - - 3. Pick the directory under which you want to unpack the - distribution and change location into it. - - 4. Obtain a distribution file using the instructions in Section - 2.1.3, "How to Get MySQL." - - 5. Unpack the distribution into the current directory: -shell> gunzip < /path/to/mysql-VERSION.tar.gz | tar xvf - - This command creates a directory named mysql-VERSION. - With GNU tar, no separate invocation of gunzip is necessary. - You can use the following alternative command to uncompress - and extract the distribution: -shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz - - 6. Change location into the top-level directory of the unpacked - distribution: -shell> cd mysql-VERSION - Note that currently you must configure and build MySQL from - this top-level directory. You cannot build it in a different - directory. - - 7. Configure the release and compile everything: -shell> ./configure --prefix=/usr/local/mysql -shell> make - When you run configure, you might want to specify other - options. Run ./configure --help for a list of options. Section - 2.3.2, "Typical configure Options," discusses some of the more - useful options. - If configure fails and you are going to send mail to a MySQL - mailing list to ask for assistance, please include any lines - from config.log that you think can help solve the problem. - Also include the last couple of lines of output from - configure. To file a bug report, please use the instructions - in Section 1.7, "How to Report Bugs or Problems." - If the compile fails, see Section 2.3.4, "Dealing with - Problems Compiling MySQL," for help. - - 8. Install the distribution: -shell> make install - You might need to run this command as root. - If you want to set up an option file, use one of those present - in the support-files directory as a template. For example: -shell> cp support-files/my-medium.cnf /etc/my.cnf - You might need to run this command as root. - If you want to configure support for InnoDB tables, you should - edit the /etc/my.cnf file, remove the # character before the - option lines that start with innodb_..., and modify the option - values to be what you want. See Section 4.2.3.3, "Using Option - Files," and Section 13.6.2, "InnoDB Configuration." - - 9. Change location into the installation directory: -shell> cd /usr/local/mysql - 10. If you ran the make install command as root, the installed - files will be owned by root. Ensure that the installation is - accessible to mysql by executing the following commands as - root in the installation directory: -shell> chown -R mysql . -shell> chgrp -R mysql . - The first command changes the owner attribute of the files to - the mysql user. The second changes the group attribute to the - mysql group. - 11. If you have not installed MySQL before, you must create the - MySQL data directory and initialize the grant tables: -shell> bin/mysql_install_db --user=mysql - If you run the command as root, include the --user option as - shown. If you run the command while logged in as mysql, you - can omit the --user option. - The command should create the data directory and its contents - with mysql as the owner. - After using mysql_install_db to create the grant tables for - MySQL, you must restart the server manually. The mysqld_safe - command to do this is shown in a later step. - 12. Most of the MySQL installation can be owned by root if you - like. The exception is that the data directory must be owned - by mysql. To accomplish this, run the following commands as - root in the installation directory: -shell> chown -R root . -shell> chown -R mysql var - 13. If you want MySQL to start automatically when you boot your - machine, you can copy support-files/mysql.server to the - location where your system has its startup files. More - information can be found in the support-files/mysql.server - script itself; see also Section 2.13.1.2, "Starting and - Stopping MySQL Automatically." - 14. You can set up new accounts using the bin/mysql_setpermission - script if you install the DBI and DBD::mysql Perl modules. See - Section 4.6.14, "mysql_setpermission --- Interactively Set - Permissions in Grant Tables." For Perl module installation - instructions, see Section 2.15, "Perl Installation Notes." - - After everything has been installed, you should test your - distribution. To start the MySQL server, use the following - command: -shell> /usr/local/mysql/bin/mysqld_safe --user=mysql & - - If you run the command as root, you should use the --user option - as shown. The value of the option is the name of the login account - that you created in the first step to use for running the server. - If you run the command while logged in as that user, you can omit - the --user option. - - If the command fails immediately and prints mysqld ended, you can - find some information in the host_name.err file in the data - directory. - - More information about mysqld_safe is given in Section 4.3.2, - "mysqld_safe --- MySQL Server Startup Script." - -Note - - The accounts that are listed in the MySQL grant tables initially - have no passwords. After starting the server, you should set up - passwords for them using the instructions in Section 2.13, - "Post-Installation Setup and Testing." - -2.3.2. Typical configure Options - - The configure script gives you a great deal of control over how - you configure a MySQL source distribution. Typically you do this - using options on the configure command line. You can also affect - configure using certain environment variables. See Section 2.14, - "Environment Variables." For a full list of options supported by - configure, run this command: -shell> ./configure --help - - A list of the available configure options is provided in the table - below. - - Table 2.1. Build (configure) Reference - Formats Description Default Introduced Removed - --bindir=DIR User executables EPREFIX/bin - --build=BUILD Configure for building on BUILD guessed - --cache-file=FILE Cache test results in FILE disabled - -C Alias for `--cache-file=config.cache' - --config-cache - --datadir=DIR Read-only architecture-independent data PREFIX/share - - --disable-FEATURE Do not include FEATURE - --disable-dependency-tracking Disable dependency tracking - --disable-grant-options Disable GRANT options - --disable-largefile Omit support for large files - --disable-libtool-lock Disable libtool lock - --disable-thread-safe-client Compile the client without threads - 5.1.7 - --enable-FEATURE Enable FEATURE - --enable-assembler Use assembler versions of some string functions - if available - --enable-debug-sync Compile in Debug Sync facility 5.1.41 - --enable-dependency-tracking Do not reject slow dependency - extractors - --enable-fast-install Optimize for fast installation yes - --enable-local-infile Enable LOAD DATA LOCAL INFILE disabled - --enable-shared Build shared libraries yes - --enable-static Build static libraries yes - --enable-thread-safe-client Compile the client with threads - --exec-prefix=EPREFIX Install architecture-dependent files in - EPREFIX - -h Display this help and exit - --help - --help=short Display options specific to this package - --help=recursive Display the short help of all the included - packages - --host=HOST Cross-compile to build programs to run on HOST - --includedir=DIR C header files PREFIX/include - --infodir=DIR Info documentation PREFIX/info - --libdir=DIR Object code libraries EPREFIX/lib - --libexecdir=DIR Program executables EPREFIX/libexec - --localstatedir=DIR Modifiable single-machine data PREFIX/var - --mandir=DIR man documentation PREFIX/man - -n Do not create output files - --no-create - --oldincludedir=DIR C header files for non-gcc /usr/include - --prefix=PREFIX Install architecture-independent files in PREFIX - - --program-prefix=PREFIX Prepend PREFIX to installed program names - - --program-suffix=SUFFIX Append SUFFIX to installed program names - - --program-transform-name=PROGRAM run sed PROGRAM on installed - program names - -q Do not print `checking...' messages - --quiet - --sbindir=DIR System admin executables EPREFIX/sbin - --sharedstatedir=DIR Modifiable architecture-independent data - PREFIX/com - --srcdir=DIR Find the sources in DIR configure directory or .. - --sysconfdir=DIR Read-only single-machine data PREFIX/etc - --target=TARGET Configure for building compilers for TARGET - -V Display version information and exit - --version - --with-PACKAGE Use PACKAGE - --with-archive-storage-engine Enable the Archive Storage Engine no - - --with-atomic-ops Implement atomic operations using pthread - rwlocks or atomic CPU instructions for multi-processor 5.1.12 - --with-berkeley-db Use BerkeleyDB located in DIR no - --with-berkeley-db-includes Find Berkeley DB headers in DIR - --with-berkeley-db-libs Find Berkeley DB libraries in DIR - --with-big-tables Support tables with more than 4 G rows even on - 32 bit platforms - --with-blackhole-storage-engine Enable the Blackhole Storage - Engine no - --with-charset Default character set - --with-client-ldflags Extra linking arguments for clients - --with-collation Default collation - --with-comment Comment about compilation environment - --with-csv-storage-engine Enable the CSV Storage Engine yes - --with-darwin-mwcc Use Metrowerks CodeWarrior wrappers on OS - X/Darwin - --with-debug Add debug code 5.1.7 - --with-debug=full Add debug code (adds memory checker, very slow) - - --with-embedded-privilege-control Build parts to check user's - privileges (only affects embedded library) - --with-embedded-server Build the embedded server - --with-error-inject Enable error injection in MySQL Server - 5.1.11 - --with-example-storage-engine Enable the Example Storage Engine no - - --with-extra-charsets Use charsets in addition to default - --with-fast-mutexes Compile with fast mutexes enabled 5.1.5 - --with-federated-storage-engine Enable federated storage engine no - 5.1.3 5.1.9 - --with-gnu-ld Assume the C compiler uses GNU ld no - --with-innodb Enable innobase storage engine no 5.1.3 5.1.9 - --with-lib-ccflags Extra CC options for libraries - --with-libwrap=DIR Compile in libwrap (tcp_wrappers) support - --with-low-memory Try to use less memory to compile to avoid - memory limitations - --with-machine-type Set the machine type, like "powerpc" - --with-max-indexes=N Sets the maximum number of indexes per table - 64 - --with-mysqld-ldflags Extra linking arguments for mysqld - --with-mysqld-libs Extra libraries to link with for mysqld - --with-mysqld-user What user the mysqld daemon shall be run as - - --with-mysqlmanager Build the mysqlmanager binary Build if server - is built - --with-named-curses-libs Use specified curses libraries - --with-named-thread-libs Use specified thread libraries - --with-ndb-ccflags Extra CC options for ndb compile - --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi - documentation - --with-ndb-port Port for NDB Cluster management server - --with-ndb-port-base Port for NDB Cluster management server - --with-ndb-sci=DIR Provide MySQL with a custom location of sci - library - --with-ndb-test Include the NDB Cluster ndbapi test programs - --with-ndbcluster Include the NDB Cluster table handler no - --with-openssl=DIR Include the OpenSSL support - --with-openssl-includes Find OpenSSL headers in DIR - --with-openssl-libs Find OpenSSL libraries in DIR - --with-other-libc=DIR Link against libc and other standard - libraries installed in the specified nonstandard location - --with-pic Try to use only PIC/non-PIC objects Use both - --with-plugin-PLUGIN Forces the named plugin to be linked into - mysqld statically 5.1.11 - --with-plugins Plugins to include in mysqld none 5.1.11 - --with-pstack Use the pstack backtrace library - --with-pthread Force use of pthread library - --with-row-based-replication Include row-based replication 5.1.5 - 5.1.6 - --with-server-suffix Append value to the version string - --with-ssl=DIR Include SSL support 5.1.11 - --with-system-type Set the system type, like "sun-solaris10" - --with-tags Include additional configurations automatic - --with-tcp-port Which port to use for MySQL services 3306 - --with-unix-socket-path Where to put the unix-domain socket - --with-yassl Include the yaSSL support - --with-zlib-dir=no|bundled|DIR Provide MySQL with a custom - location of compression library - --without-PACKAGE Do not use PACKAGE - --without-bench Skip building of the benchmark suite - --without-debug Build a production version without debugging code - - --without-docs Skip building of the documentation - --without-extra-tools Skip building utilities in the tools - directory - --without-geometry Do not build geometry-related parts - --without-libedit Use system libedit instead of bundled copy - --without-man Skip building of the man pages - --without-ndb-binlog Disable ndb binlog 5.1.6 - --without-ndb-debug Disable special ndb debug features - --without-plugin-PLUGIN Exclude PLUGIN 5.1.11 - --without-query-cache Do not build query cache - --without-readline Use system readline instead of bundled copy - - --without-row-based-replication Don't include row-based - replication 5.1.7 5.1.14 - --without-server Only build the client - --without-uca Skip building of the national Unicode collations - - Some of the configure options available are described here. For - options that may be of use if you have difficulties building - MySQL, see Section 2.3.4, "Dealing with Problems Compiling MySQL." - - * To compile just the MySQL client libraries and client programs - and not the server, use the --without-server option: -shell> ./configure --without-server - If you have no C++ compiler, some client programs such as - mysql cannot be compiled because they require C++.. In this - case, you can remove the code in configure that tests for the - C++ compiler and then run ./configure with the - --without-server option. The compile step should still try to - build all clients, but you can ignore any warnings about files - such as mysql.cc. (If make stops, try make -k to tell it to - continue with the rest of the build even if errors occur.) - - * If you want to build the embedded MySQL library (libmysqld.a), - use the --with-embedded-server option. - - * If you don't want your log files and database directories - located under /usr/local/var, use a configure command - something like one of these: -shell> ./configure --prefix=/usr/local/mysql -shell> ./configure --prefix=/usr/local \ - --localstatedir=/usr/local/mysql/data - The first command changes the installation prefix so that - everything is installed under /usr/local/mysql rather than the - default of /usr/local. The second command preserves the - default installation prefix, but overrides the default - location for database directories (normally /usr/local/var) - and changes it to /usr/local/mysql/data. - You can also specify the installation directory and data - directory locations at server startup time by using the - --basedir and --datadir options. These can be given on the - command line or in an MySQL option file, although it is more - common to use an option file. See Section 4.2.3.3, "Using - Option Files." - - * This option specifies the port number on which the server - listens for TCP/IP connections. The default is port 3306. To - listen on a different port, use a configure command like this: -shell> ./configure --with-tcp-port=3307 - - * If you are using Unix and you want the MySQL socket file - location to be somewhere other than the default location - (normally in the directory /tmp or /var/run), use a configure - command like this: -shell> ./configure \ - --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock - The socket file name must be an absolute path name. You can - also change the location of mysql.sock at server startup by - using a MySQL option file. See Section B.5.4.5, "How to - Protect or Change the MySQL Unix Socket File." - - * If you want to compile statically linked programs (for - example, to make a binary distribution, to get better - performance, or to work around problems with some Red Hat - Linux distributions), run configure like this: -shell> ./configure --with-client-ldflags=-all-static \ - --with-mysqld-ldflags=-all-static - - * If you are using gcc and don't have libg++ or libstdc++ - installed, you can tell configure to use gcc as your C++ - compiler: -shell> CC=gcc CXX=gcc ./configure - When you use gcc as your C++ compiler, it does not attempt to - link in libg++ or libstdc++. This may be a good thing to do - even if you have those libraries installed. Some versions of - them have caused strange problems for MySQL users in the past. - The following list indicates some compilers and environment - variable settings that are commonly used with each one. - - + gcc 2.7.2: -CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" - - + gcc 2.95.2: -CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ --felide-constructors -fno-exceptions -fno-rtti" - - + pgcc 2.90.29 or newer: -CFLAGS="-O3 -mpentiumpro -mstack-align-double" CXX=gcc \ -CXXFLAGS="-O3 -mpentiumpro -mstack-align-double \ --felide-constructors -fno-exceptions -fno-rtti" - In most cases, you can get a reasonably optimized MySQL binary - by using the options from the preceding list and adding the - following options to the configure line: ---prefix=/usr/local/mysql --enable-assembler \ ---with-mysqld-ldflags=-all-static - The full configure line would, in other words, be something - like the following for all recent gcc versions: -CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ --felide-constructors -fno-exceptions -fno-rtti" ./configure \ ---prefix=/usr/local/mysql --enable-assembler \ ---with-mysqld-ldflags=-all-static - The binaries we provide on the MySQL Web site at - http://dev.mysql.com/downloads/ are all compiled with full - optimization and should be perfect for most users. See Section - 2.2, "Installing MySQL from Generic Binaries on Unix/Linux." - There are some configuration settings you can tweak to build - an even faster binary, but these are only for advanced users. - See Section 7.5.1, "How Compiling and Linking Affects the - Speed of MySQL." - If the build fails and produces errors about your compiler or - linker not being able to create the shared library - libmysqlclient.so.N (where N is a version number), you can - work around this problem by giving the --disable-shared option - to configure. In this case, configure does not build a shared - libmysqlclient.so.N library. - - * By default, MySQL uses the latin1 (cp1252 West European) - character set. To change the default set, use the - --with-charset option: -shell> ./configure --with-charset=CHARSET - CHARSET may be one of binary, armscii8, ascii, big5, cp1250, - cp1251, cp1256, cp1257, cp850, cp852, cp866, cp932, dec8, - eucjpms, euckr, gb2312, gbk, geostd8, greek, hebrew, hp8, - keybcs2, koi8r, koi8u, latin1, latin2, latin5, latin7, macce, - macroman, sjis, swe7, tis620, ucs2, ujis, utf8. (Additional - character sets might be available. Check the output from - ./configure --help for the current list.) - The default collation may also be specified. MySQL uses the - latin1_swedish_ci collation by default. To change this, use - the --with-collation option: -shell> ./configure --with-collation=COLLATION - To change both the character set and the collation, use both - the --with-charset and --with-collation options. The collation - must be a legal collation for the character set. (Use the SHOW - COLLATION statement to determine which collations are - available for each character set.) - With the configure option --with-extra-charsets=LIST, you can - define which additional character sets should be compiled into - the server. LIST is one of the following: - - + A list of character set names separated by spaces - - + complex to include all character sets that can't be - dynamically loaded - - + all to include all character sets into the binaries - Clients that want to convert characters between the server and - the client should use the SET NAMES statement. See Section - 5.1.5, "Session System Variables," and Section 9.1.4, - "Connection Character Sets and Collations." - - * To configure MySQL with debugging code, use the --with-debug - option: -shell> ./configure --with-debug - This causes a safe memory allocator to be included that can - find some errors and that provides output about what is - happening. See MySQL Internals: Porting - (http://forge.mysql.com/wiki/MySQL_Internals_Porting). - As of MySQL 5.1.12, using --with-debug to configure MySQL with - debugging support enables you to use the - --debug-dbug="d,parser_debug" option when you start the server. - This causes the Bison parser that is used to process SQL - statements to dump a parser trace to the server's standard - error output. Typically, this output is written to the error - log. - - * To cause the Debug Sync facility to be compiled into the - server, use the --enable-debug-sync option. This facility is - used for testing and debugging. When compiled in, Debug Sync - is disabled by default. To enable it, start mysqld with the - --debug-sync-timeout=N option, where N is a timeout value - greater than 0. (The default value is 0, which disables Debug - Sync.) N becomes the default timeout for individual - synchronization points. - Debug Sync is also compiled in if you configure with the - --with-debug option (which implies --enable-debug-sync), - unless you also use the --disable-debug-sync option. - For a description of the Debug Sync facility and how to use - synchronization points, see MySQL Internals: Test - Synchronization - (http://forge.mysql.com/wiki/MySQL_Internals_Test_Synchronizat - ion). - The --enable-debug-sync and --disable-debug-sync options were - added in MySQL 5.1.41. - - * If your client programs are using threads, you must compile a - thread-safe version of the MySQL client library with the - --enable-thread-safe-client configure option. This creates a - libmysqlclient_r library with which you should link your - threaded applications. See Section 21.9.16.2, "How to Make a - Threaded Client." - - * Some features require that the server be built with - compression library support, such as the COMPRESS() and - UNCOMPRESS() functions, and compression of the client/server - protocol. The --with-zlib-dir=no|bundled|DIR option provides - control over compression library support. The value no - explicitly disables compression support. bundled causes the - zlib library bundled in the MySQL sources to be used. A DIR - path name specifies the directory in which to find the - compression library sources. - - * It is possible to build MySQL with large table support using - the --with-big-tables option. - This option causes the variables that store table row counts - to be declared as unsigned long long rather than unsigned - long. This enables tables to hold up to approximately - 1.844E+19 ((2^32)^2) rows rather than 2^32 (~4.295E+09) rows. - Previously it was necessary to pass -DBIG_TABLES to the - compiler manually in order to enable this feature. - - * Run configure with the --disable-grant-options option to cause - the --bootstrap, --skip-grant-tables, and --init-file options - for mysqld to be disabled. For Windows, the configure.js - script recognizes the DISABLE_GRANT_OPTIONS flag, which has - the same effect. The capability is available as of MySQL - 5.1.15. - - * This option allows MySQL Community Server features to be - enabled. Additional options may be required for individual - features, such as --enable-profiling to enable statement - profiling. This option was added in MySQL 5.1.24. It is - enabled by default as of MySQL 5.1.28; to disable it, use - --disable-community-features. - - * When given with --enable-community-features, the - --enable-profiling option enables the statement profiling - capability exposed by the SHOW PROFILE and SHOW PROFILES - statements. (See Section 12.4.5.33, "SHOW PROFILES Syntax.") - This option was added in MySQL 5.1.24. It is enabled by - default as of MySQL 5.1.28; to disable it, use - --disable-profiling. - - * See Section 2.1, "General Installation Guidance," for options - that pertain to particular operating systems. - - * See Section 5.5.6.2, "Using SSL Connections," for options that - pertain to configuring MySQL to support secure (encrypted) - connections. - - * Several configure options apply to plugin selection and - building: ---with-plugins=PLUGIN[,PLUGIN]... ---with-plugins=GROUP ---with-plugin-PLUGIN ---without-plugin-PLUGIN - PLUGIN is an individual plugin name such as csv or archive. - As shorthand, GROUP is a configuration group name such as none - (select no plugins) or all (select all plugins). - You can build a plugin as static (compiled into the server) or - dynamic (built as a dynamic library that must be installed - using the INSTALL PLUGIN statement before it can be used). - Some plugins might not support static or dynamic build. - configure --help shows the following information pertaining to - plugins: - - + The plugin-related options - - + The names of all available plugins - - + For each plugin, a description of its purpose, which - build types it supports (static or dynamic), and which - plugin groups it is a part of. - --with-plugins can take a list of one or more plugin names - separated by commas, or a plugin group name. The named plugins - are configured to be built as static plugins. - --with-plugin-PLUGIN configures the given plugin to be built - as a static plugin. - --without-plugin-PLUGIN disables the given plugin from being - built. - If a plugin is named both with a --with and --without option, - the result is undefined. - For any plugin that is not explicitly selected or disabled, it - is selected to be built dynamically if it supports dynamic - build, and not built if it does not support dynamic build. - (Thus, in the case that no plugin options are given, all - plugins that support dynamic build are selected to be built as - dynamic plugins. Plugins that do not support dynamic build are - not built.) - -2.3.3. Installing from the Development Source Tree - -Caution - - You should read this section only if you are interested in helping - us test our new code. If you just want to get MySQL up and running - on your system, you should use a standard release distribution - (either a binary or source distribution). - - To obtain the most recent development source tree, you must have - Bazaar installed. You can obtain Bazaar from the Bazaar VCS Web - site (http://bazaar-vcs.org). Bazaar is supported by any platform - that supports Python, and is therefore compatible with any Linux, - Unix, Windows or Mac OS X host. Instructions for downloading and - installing Bazaar on the different platforms are available on the - Bazaar Web site. - - All MySQL projects are hosted on Launchpad - (http://launchpad.net/). MySQL projects, including MySQL server, - MySQL Workbench, and others are available from the Sun/MySQL - Engineering (http://launchpad.net/~mysql) page. For the - repositories related only to MySQL server, see the MySQL Server - (http://launchpad.net/mysql-server) page. - - To build under Unix/Linux, you must have the following tools - installed: - - * GNU make, available from http://www.gnu.org/software/make/. - Although some platforms come with their own make - implementations, it is highly recommended that you use GNU - make. It may already be available on your system as gmake. - - * autoconf 2.58 (or newer), available from - http://www.gnu.org/software/autoconf/. - - * automake 1.8.1, available from - http://www.gnu.org/software/automake/. - - * libtool 1.5, available from - http://www.gnu.org/software/libtool/. - - * m4, available from http://www.gnu.org/software/m4/. - - * bison, available from http://www.gnu.org/software/bison/. You - should use the latest version of bison where possible. Version - 1.75 and version 2.1 are known to work. There have been - reported problems with bison 1.875. If you experience - problems, upgrade to a later, rather than earlier, version. - Versions of bison older than 1.75 may report this error: -sql_yacc.yy:#####: fatal error: maximum table size (32767) exceeded - The maximum table size is not actually exceeded; the error is - caused by bugs in older versions of bison. - - To build under Windows you must have Microsoft Visual C++ 2005 - Express Edition, Visual Studio .Net 2003 (7.1), or Visual Studio - 2005 (8.0) compiler system. - - Once the necessary tools are installed, you must create a local - branch of the MySQL source code on your machine: - - 1. To obtain a copy of the MySQL source code, you must create a - new Bazaar branch. If you do not already have a Bazaar - repository directory set up, you need to initialize a new - directory: -shell> mkdir mysql-server -shell> bzr init-repo --trees mysql-server - - 2. Once you have an initialized directory, you can branch from - the public MySQL server repositories to create a local source - tree. To create a branch of a specific version: -shell> cd mysql-server -shell> bzr branch lp:mysql-server/5.1 mysql-5.1 - - 3. The initial download will take some time to complete, - depending on the speed of your connection. Please be patient. - Once you have downloaded the first tree, additional trees - should take significantly less time to download. - - 4. When building from the Bazaar branch, you may want to create a - copy of your active branch so that you can make configuration - and other changes without affecting the original branch - contents. You can achieve this by branching from the original - branch: -shell> bzr branch mysql-5.1 mysql-5.1-build - - 5. To obtain changes made after you have set up the branch - initially, update it using the pull option periodically. Use - this command in the top-level directory of the local copy: -shell> bzr pull - You can examine the changeset comments for the tree by using - the log option to bzr: -shell> bzr log - You can also browse changesets, comments, and source code - online. To browse this information for MySQL 5.1, go to the - Launchpad MySQL Server (http://launchpad.net/mysql-server) - page. - If you see diffs (changes) or code that you have a question - about, do not hesitate to send email to the MySQL internals - mailing list. See Section 1.6.1, "MySQL Mailing Lists." Also, - if you think you have a better idea on how to do something, - send an email message to the list with a patch. - - After you have the local branch, you can build MySQL server from - the source code. On Windows, the build process is different from - Unix/Linux: see Section 2.5.10, "Installing MySQL from Source on - Windows." - - On Unix/Linux, use the autoconf system to create the configure - script so that you can configure the build environment before - building. The following example shows the typical commands - required to build MySQL from a source tree. - - 1. Change location to the top-level directory of the source tree; - replace mysql-5.1 with the appropriate directory name. -shell> cd mysql-5.1 - - 2. Prepare the source tree for configuration. - Prior to MySQL 5.1.12, you must separately configure the - InnoDB storage engine. Run the following command from the main - source directory: -shell> (cd storage/innobase; autoreconf --force --install) - You can omit the previous command for MySQL 5.1.12 and later, - or if you do not require InnoDB support. - Prepare the remainder of the source tree: -shell> autoreconf --force --install - As an alternative to the preceding autoreconf command, you can - use BUILD/autorun.sh, which acts as a shortcut for the - following sequence of commands: -shell> aclocal; autoheader -shell> libtoolize --automake --force -shell> automake --force --add-missing; autoconf - If you get some strange errors during this stage, verify that - you have the correct version of libtool installed. - - 3. Configure the source tree and compile MySQL: -shell> ./configure # Add your favorite options here -shell> make - For a description of some configure options, see Section - 2.3.2, "Typical configure Options." - A collection of our standard configuration scripts is located - in the BUILD/ subdirectory. For example, you may find it more - convenient to use the BUILD/compile-pentium-debug script than - the preceding set of shell commands. To compile on a different - architecture, modify the script by removing flags that are - Pentium-specific, or use another script that may be more - appropriate. These scripts are provided on an "as-is" basis. - They are not officially maintained and their contents may - change from release to release. - - 4. When the build is done, run make install. Be careful with this - on a production machine; the command may overwrite your live - release installation. If you already have MySQL installed and - do not want to overwrite it, run ./configure with values for - the --prefix, --with-tcp-port, and --with-unix-socket-path - options different from those used for your production server. - - 5. Play hard with your new installation and try to make the new - features crash. Start by running make test. See Section - 22.1.2, "MySQL Test Suite." - - 6. If you have gotten to the make stage, but the distribution - does not compile, please enter the problem into our bugs - database using the instructions given in Section 1.7, "How to - Report Bugs or Problems." If you have installed the latest - versions of the required GNU tools, and they crash trying to - process our configuration files, please report that also. - However, if you get a command not found error or a similar - problem for aclocal, configure, or other required tools, do - not report it. Instead, make sure that all the required tools - are installed and that your PATH variable is set correctly so - that your shell can find them. - -2.3.4. Dealing with Problems Compiling MySQL - - All MySQL programs compile cleanly for us with no warnings on - Solaris or Linux using gcc. On other systems, warnings may occur - due to differences in system include files. See Section 2.3.5, - "MIT-pthreads Notes," for warnings that may occur when using - MIT-pthreads. For other problems, check the following list. - - The solution to many problems involves reconfiguring. If you do - need to reconfigure, take note of the following: - - * If configure is run after it has previously been run, it may - use information that was gathered during its previous - invocation. This information is stored in config.cache. When - configure starts up, it looks for that file and reads its - contents if it exists, on the assumption that the information - is still correct. That assumption is invalid when you - reconfigure. - - * Each time you run configure, you must run make again to - recompile. However, you may want to remove old object files - from previous builds first because they were compiled using - different configuration options. - - To prevent old configuration information or object files from - being used, run these commands before re-running configure: -shell> rm config.cache -shell> make clean - - Alternatively, you can run make distclean. - - The following list describes some of the problems when compiling - MySQL that have been found to occur most often: - - * If you get errors such as the ones shown here when compiling - sql_yacc.cc, you probably have run out of memory or swap - space: -Internal compiler error: program cc1plus got fatal signal 11 -Out of virtual memory -Virtual memory exhausted - The problem is that gcc requires a huge amount of memory to - compile sql_yacc.cc with inline functions. Try running - configure with the --with-low-memory option: -shell> ./configure --with-low-memory - This option causes -fno-inline to be added to the compile line - if you are using gcc and -O0 if you are using something else. - You should try the --with-low-memory option even if you have - so much memory and swap space that you think you can't - possibly have run out. This problem has been observed to occur - even on systems with generous hardware configurations, and the - --with-low-memory option usually fixes it. - - * By default, configure picks c++ as the compiler name and GNU - c++ links with -lg++. If you are using gcc, that behavior can - cause problems during configuration such as this: -configure: error: installation or configuration problem: -C++ compiler cannot create executables. - You might also observe problems during compilation related to - g++, libg++, or libstdc++. - One cause of these problems is that you may not have g++, or - you may have g++ but not libg++, or libstdc++. Take a look at - the config.log file. It should contain the exact reason why - your C++ compiler didn't work. To work around these problems, - you can use gcc as your C++ compiler. Try setting the - environment variable CXX to "gcc -O3". For example: -shell> CXX="gcc -O3" ./configure - This works because gcc compiles C++ source files as well as - g++ does, but does not link in libg++ or libstdc++ by default. - Another way to fix these problems is to install g++, libg++, - and libstdc++. However, do not use libg++ or libstdc++ with - MySQL because this only increases the binary size of mysqld - without providing any benefits. Some versions of these - libraries have also caused strange problems for MySQL users in - the past. - - * If your compile fails with errors such as any of the - following, you must upgrade your version of make to GNU make: -making all in mit-pthreads -make: Fatal error in reader: Makefile, line 18: -Badly formed macro assignment - Or: -make: file `Makefile' line 18: Must be a separator (: - Or: -pthread.h: No such file or directory - Solaris and FreeBSD are known to have troublesome make - programs. - GNU make 3.75 is known to work. - - * If you want to define flags to be used by your C or C++ - compilers, do so by adding the flags to the CFLAGS and - CXXFLAGS environment variables. You can also specify the - compiler names this way using CC and CXX. For example: -shell> CC=gcc -shell> CFLAGS=-O3 -shell> CXX=gcc -shell> CXXFLAGS=-O3 -shell> export CC CFLAGS CXX CXXFLAGS - See Section 2.2, "Installing MySQL from Generic Binaries on - Unix/Linux," for a list of flag definitions that have been - found to be useful on various systems. - - * If you get errors such as those shown here when compiling - mysqld, configure did not correctly detect the type of the - last argument to accept(), getsockname(), or getpeername(): -cxx: Error: mysqld.cc, line 645: In this statement, the referenced - type of the pointer value ''length'' is ''unsigned long'', - which is not compatible with ''int''. -new_sock = accept(sock, (struct sockaddr *)&cAddr, &length); - To fix this, edit the config.h file (which is generated by - configure). Look for these lines: -/* Define as the base type of the last arg to accept */ -#define SOCKET_SIZE_TYPE XXX - Change XXX to size_t or int, depending on your operating - system. (You must do this each time you run configure because - configure regenerates config.h.) - - * The sql_yacc.cc file is generated from sql_yacc.yy. Normally, - the build process does not need to create sql_yacc.cc because - MySQL comes with a pre-generated copy. However, if you do need - to re-create it, you might encounter this error: -"sql_yacc.yy", line xxx fatal: default action causes potential... - This is a sign that your version of yacc is deficient. You - probably need to install bison (the GNU version of yacc) and - use that instead. - - * On Debian Linux 3.0, you need to install gawk instead of the - default mawk. - - * If you need to debug mysqld or a MySQL client, run configure - with the --with-debug option, and then recompile and link your - clients with the new client library. See MySQL Internals: - Porting (http://forge.mysql.com/wiki/MySQL_Internals_Porting). - - * If you get a compilation error on Linux (for example, SuSE - Linux 8.1 or Red Hat Linux 7.3) similar to the following one, - you probably do not have g++ installed: -libmysql.c:1329: warning: passing arg 5 of `gethostbyname_r' from -incompatible pointer type -libmysql.c:1329: too few arguments to function `gethostbyname_r' -libmysql.c:1329: warning: assignment makes pointer from integer -without a cast -make[2]: *** [libmysql.lo] Error 1 - By default, the configure script attempts to determine the - correct number of arguments by using g++ (the GNU C++ - compiler). This test yields incorrect results if g++ is not - installed. There are two ways to work around this problem: - - + Make sure that the GNU C++ g++ is installed. On some - Linux distributions, the required package is called gpp; - on others, it is named gcc-c++. - - + Use gcc as your C++ compiler by setting the CXX - environment variable to gcc: -export CXX="gcc" - You must run configure again after making either of those - changes. - -2.3.5. MIT-pthreads Notes - - This section describes some of the issues involved in using - MIT-pthreads. - - On Linux, you should not use MIT-pthreads. Use the installed - LinuxThreads implementation instead. See Section 2.6, "Installing - MySQL on Linux." - - If your system does not provide native thread support, you should - build MySQL using the MIT-pthreads package. This includes older - FreeBSD systems, SunOS 4.x, Solaris 2.4 and earlier, and some - others. See Section 2.1, "General Installation Guidance." - - MIT-pthreads is not part of the MySQL 5.1 source distribution. If - you require this package, you need to download it separately from - http://dev.mysql.com/Downloads/Contrib/pthreads-1_60_beta6-mysql.t - ar.gz - - After downloading, extract this source archive into the top level - of the MySQL source directory. It creates a new subdirectory named - mit-pthreads. - - * On most systems, you can force MIT-pthreads to be used by - running configure with the --with-mit-threads option: -shell> ./configure --with-mit-threads - Building in a nonsource directory is not supported when using - MIT-pthreads because we want to minimize our changes to this - code. - - * The checks that determine whether to use MIT-pthreads occur - only during the part of the configuration process that deals - with the server code. If you have configured the distribution - using --without-server to build only the client code, clients - do not know whether MIT-pthreads is being used and use Unix - socket file connections by default. Because Unix socket files - do not work under MIT-pthreads on some platforms, this means - you need to use -h or --host with a value other than localhost - when you run client programs. - - * When MySQL is compiled using MIT-pthreads, system locking is - disabled by default for performance reasons. You can tell the - server to use system locking with the --external-locking - option. This is needed only if you want to be able to run two - MySQL servers against the same data files, but that is not - recommended, anyway. - - * Sometimes the pthread bind() command fails to bind to a socket - without any error message (at least on Solaris). The result is - that all connections to the server fail. For example: -shell> mysqladmin version -mysqladmin: connect to server at '' failed; -error: 'Can't connect to mysql server on localhost (146)' - The solution to this problem is to kill the mysqld server and - restart it. This has happened to us only when we have forcibly - stopped the server and restarted it immediately. - - * With MIT-pthreads, the sleep() system call isn't interruptible - with SIGINT (break). This is noticeable only when you run - mysqladmin --sleep. You must wait for the sleep() call to - terminate before the interrupt is served and the process - stops. - - * When linking, you might receive warning messages like these - (at least on Solaris); they can be ignored: -ld: warning: symbol `_iob' has differing sizes: - (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; -file /usr/lib/libc.so value=0x140); - /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken -ld: warning: symbol `__iob' has differing sizes: - (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; -file /usr/lib/libc.so value=0x140); - /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken - - * Some other warnings also can be ignored: -implicit declaration of function `int strtoll(...)' -implicit declaration of function `int strtoul(...)' - - * We have not been able to make readline work with MIT-pthreads. - (This is not necessary, but may be of interest to some.) - -2.4. Upgrading or Downgrading MySQL - -2.4.1. Upgrading MySQL - - As a general rule, to upgrade from one release series to another, - you should go to the next series rather than skipping a series. To - upgrade from a release series previous to MySQL 5.0, upgrade to - each successive release series in turn until you have reached - MySQL 5.0, and then proceed with the upgrade to MySQL 5.1. For - example, if you currently are running MySQL 4.0 and wish to - upgrade to a newer series, upgrade to MySQL 4.1 first before - upgrading to 5.0, and so forth. For information on upgrading to - MySQL 5.0, see the MySQL 5.0 Reference Manual; for earlier - releases, see the MySQL 3.23, 4.0, 4.1 Reference Manual. - - If you perform a binary (in-place) upgrade without dumping and - reloading tables, you cannot upgrade directly from MySQL 4.1 to - 5.1. This occurs due to an incompatible change in the MyISAM table - index format in MySQL 5.0. Upgrade from MySQL 4.1 to 5.0 and - repair all MyISAM tables (see Section 2.4.4, "Rebuilding or - Repairing Tables or Indexes"). Then upgrade from MySQL 5.0 to 5.1 - and check and repair your tables. - - To upgrade from MySQL 5.0 to 5.1, use the items in the following - checklist as a guide: - - * Before any upgrade, back up your databases, including the - mysql database that contains the grant tables. See Section - 6.2, "Database Backup Methods." - - * Read all the notes in Section 2.4.1.1, "Upgrading from MySQL - 5.0 to 5.1." These notes enable you to identify upgrade issues - that apply to your current MySQL installation. Some - incompatibilities discussed in that section require your - attention before upgrading. Others should be dealt with after - upgrading. - - * Read Appendix C, "MySQL Change History" as well, which - provides information about features that are new in MySQL 5.1 - or differ from those found in MySQL 5.0. - - * After you upgrade to a new version of MySQL, run mysql_upgrade - (see Section 4.4.8, "mysql_upgrade --- Check Tables for MySQL - Upgrade"). This program checks your tables, and attempts to - repair them if necessary. It also updates your grant tables to - make sure that they have the current structure so that you can - take advantage of any new capabilities. (Some releases of - MySQL introduce changes to the structure of the grant tables - to add new privileges or features.) - - * If you are running MySQL Server on Windows, see Section 2.5.7, - "Upgrading MySQL on Windows." - - * If you are using replication, see Section 16.4.3, "Upgrading a - Replication Setup," for information on upgrading your - replication setup. - - * If you are upgrading an installation originally produced by - installing multiple RPM packages, it is best to upgrade all - the packages, not just some. For example, if you previously - installed the server and client RPMs, do not upgrade just the - server RPM. - - * As of MySQL 5.1.9, the mysqld-max server is included in binary - distributions. There is no separate MySQL-Max distribution. As - of MySQL 5.1.12, there is no mysqld-max server at all in - binary distributions. They contain a server that includes the - features previously included in mysqld-max. - - * If you have created a user-defined function (UDF) with a given - name and upgrade MySQL to a version that implements a new - built-in function with the same name, the UDF becomes - inaccessible. To correct this, use DROP FUNCTION to drop the - UDF, and then use CREATE FUNCTION to re-create the UDF with a - different nonconflicting name. The same is true if the new - version of MySQL implements a built-in function with the same - name as an existing stored function. See Section 8.2.4, - "Function Name Parsing and Resolution," for the rules - describing how the server interprets references to different - kinds of functions. - - You can always move the MySQL format files and data files between - different versions on systems with the same architecture as long - as you stay within versions for the same release series of MySQL. - - If you are cautious about using new versions, you can always - rename your old mysqld before installing a newer one. For example, - if you are using MySQL 5.0.13 and want to upgrade to 5.1.10, - rename your current server from mysqld to mysqld-5.0.13. If your - new mysqld then does something unexpected, you can simply shut it - down and restart with your old mysqld. - - If, after an upgrade, you experience problems with recompiled - client programs, such as Commands out of sync or unexpected core - dumps, you probably have used old header or library files when - compiling your programs. In this case, you should check the date - for your mysql.h file and libmysqlclient.a library to verify that - they are from the new MySQL distribution. If not, recompile your - programs with the new headers and libraries. - - If problems occur, such as that the new mysqld server does not - start or that you cannot connect without a password, verify that - you do not have an old my.cnf file from your previous - installation. You can check this with the --print-defaults option - (for example, mysqld --print-defaults). If this command displays - anything other than the program name, you have an active my.cnf - file that affects server or client operation. - - If your MySQL installation contains a large amount of data that - might take a long time to convert after an in-place upgrade, you - might find it useful to create a "dummy" database instance for - assessing what conversions might be needed and the work involved - to perform them. Make a copy of your MySQL instance that contains - a full copy of the mysql database, plus all other databases - without data. Run your upgrade procedure on this dummy instance to - see what actions might be needed so that you can better evaluate - the work involved when performing actual data conversion on your - original database instance. - - It is a good idea to rebuild and reinstall the Perl DBD::mysql - module whenever you install a new release of MySQL. The same - applies to other MySQL interfaces as well, such as PHP mysql - extensions and the Python MySQLdb module. - -2.4.1.1. Upgrading from MySQL 5.0 to 5.1 - - After upgrading a 5.0 installation to 5.0.10 or above, it is - necessary to upgrade your grant tables. Otherwise, creating stored - procedures and functions might not work. To perform this upgrade, - run mysql_upgrade. - -Note - - It is good practice to back up your data before installing any new - version of software. Although MySQL works very hard to ensure a - high level of quality, you should protect your data by making a - backup. - - To upgrade to 5.1 from any previous version, MySQL recommends that - you dump your tables with mysqldump before upgrading and reload - the dump file after upgrading. - - If you perform a binary (in-place) upgrade without dumping and - reloading tables, you cannot upgrade directly from MySQL 4.1 to - 5.1. This occurs due to an incompatible change in the MyISAM table - index format in MySQL 5.0. Upgrade from MySQL 4.1 to 5.0 and - repair all MyISAM tables (see Section 2.4.4, "Rebuilding or - Repairing Tables or Indexes"). Then upgrade from MySQL 5.0 to 5.1 - and check and repair your tables. - - In general, you should do the following when upgrading from MySQL - 5.0 to 5.1: - - * Read all the items in the following sections to see whether - any of them might affect your applications: - - + Section 2.4.1, "Upgrading MySQL," has general update - information. - - + The items in the change lists found later in this section - enable you to identify upgrade issues that apply to your - current MySQL installation. - - + The MySQL 5.1 change history describes significant new - features you can use in 5.1 or that differ from those - found in MySQL 5.0. Some of these changes may result in - incompatibilities. See Section C.1, "Changes in Release - 5.1.x (Production)." - - * Note particularly any changes that are marked Known issue or - Incompatible change. These incompatibilities with earlier - versions of MySQL may require your attention before you - upgrade. - Our aim is to avoid these changes, but occasionally they are - necessary to correct problems that would be worse than an - incompatibility between releases. If any upgrade issue - applicable to your installation involves an incompatibility - that requires special handling, follow the instructions given - in the incompatibility description. Often this will involve a - dump and reload, or use of a statement such as CHECK TABLE or - REPAIR TABLE. - For dump and reload instructions, see Section 2.4.4, - "Rebuilding or Repairing Tables or Indexes." Any procedure - that involves REPAIR TABLE with the USE_FRM option must be - done before upgrading. Use of this statement with a version of - MySQL different from the one used to create the table (that - is, using it after upgrading) may damage the table. See - Section 12.4.2.6, "REPAIR TABLE Syntax." - - * After you upgrade to a new version of MySQL, run mysql_upgrade - (see Section 4.4.8, "mysql_upgrade --- Check Tables for MySQL - Upgrade"). This program checks your tables, and attempts to - repair them if necessary. It also updates your grant tables to - make sure that they have the current structure so that you can - take advantage of any new capabilities. (Some releases of - MySQL introduce changes to the structure of the grant tables - to add new privileges or features.) - - * Check Section 2.4.3, "Checking Whether Tables or Indexes Must - Be Rebuilt," to see whether changes to table formats or to - character sets or collations were made between your current - version of MySQL and the version to which you are upgrading. - If so and these changes result in an incompatibility between - MySQL versions, you will need to upgrade the affected tables - using the instructions in Section 2.4.4, "Rebuilding or - Repairing Tables or Indexes." - - * If you are running MySQL Server on Windows, see Section 2.5.7, - "Upgrading MySQL on Windows." - - * If you are using replication, see Section 16.4.3, "Upgrading a - Replication Setup," for information on upgrading your - replication setup. - - If your MySQL installation contains a large amount of data that - might take a long time to convert after an in-place upgrade, you - might find it useful to create a "dummy" database instance for - assessing what conversions might be needed and the work involved - to perform them. Make a copy of your MySQL instance that contains - a full copy of the mysql database, plus all other databases - without data. Run your upgrade procedure on this dummy instance to - see what actions might be needed so that you can better evaluate - the work involved when performing actual data conversion on your - original database instance. - - MySQL Enterprise MySQL Enterprise subscribers will find more - information about upgrading in the Knowledge Base articles found - at Upgrading - (https://kb.mysql.com/search.php?cat=search&category=41). Access - to the MySQL Knowledge Base collection of articles is one of the - advantages of subscribing to MySQL Enterprise. For more - information, see - http://www.mysql.com/products/enterprise/advisors.html. - - The following lists describe changes that may affect applications - and that you should watch out for when upgrading to MySQL 5.1. - - Configuration Changes: - - * Before MySQL 5.1.11, to build MySQL from source with SSL - support enabled, you would invoke configure with either the - --with-openssl or --with-yassl option. In MySQL 5.1.11, those - options both have been replaced by the --with-ssl option. By - default, --with-ssl causes the bundled yaSSL library to be - used. To select OpenSSL instead, give the option as - --with-ssl=path, where path is the directory where the OpenSSL - header files and libraries are located. - - Server Changes: - - * Known issue: After a binary upgrade to MySQL 5.1 from a MySQL - 5.0 installation that contains ARCHIVE tables, accessing those - tables will cause the server to crash, even if you have run - mysql_upgrade or CHECK TABLE ... FOR UPGRADE. To work around - this problem, use mysqldump to dump all ARCHIVE tables before - upgrading, and reload them into MySQL 5.1 after upgrading. - - * Known issue: The fix for - Bug#23491: http://bugs.mysql.com/bug.php?id=23491 introduced a - problem with SHOW CREATE VIEW, which is used by mysqldump. - This causes an incompatibility when upgrading from versions - affected by that bug fix (MySQL 5.0.40 through 5.0.43, MySQL - 5.1.18 through 5.1.19): If you use mysqldump before upgrading - from an affected version and reload the data after upgrading - to a higher version, you must drop and recreate your views. - - * Known issue: Dumps performed by using mysqldump to generate a - dump file before the upgrade and reloading the file after - upgrading are subject to the following problem: - Before MySQL 5.0.40, mysqldump displays SPATIAL index - definitions using prefix lengths for the indexed columns. - These prefix lengths are accepted in MySQL 5.0, but not as of - MySQL 5.1. If you use mysqldump from versions of MySQL older - than 5.0.40, any table containing SPATIAL indexes will cause - an error when the dump file is reloaded into MySQL 5.1 or - higher. - For example, a table definition might look like this when - dumped in MySQL 5.0: -CREATE TABLE `t` ( - `g` geometry NOT NULL, - SPATIAL KEY `g` (`g`(32)) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 - The SPATIAL index definition will not be accepted in MySQL - 5.1. To work around this, edit the dump file to remove the - prefix: -CREATE TABLE `t` ( - `g` geometry NOT NULL, - SPATIAL KEY `g` (`g`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 - Dump files can be large, so it may be preferable to dump table - definitions and data separately to make it easier to edit the - definitions: -shell> mysqldump --no-data other_args > definitions.sql -shell> mysqldump --no-create-info other_args > data.sql - Then edit definitions.sql before reloading definitions.sql and - data.sql, in that order. - If you upgrade to a version of MySQL 5.0 higher than 5.0.40 - before upgrading to MySQL 5.1, this problem does not occur. - - * Known issue: Before MySQL 5.1.30, the CHECK TABLE ... FOR - UPGRADE statement did not check for incompatible collation - changes made in MySQL 5.1.24. (This also affects mysqlcheck - and mysql_upgrade, which cause that statement to be executed.) - Prior to the fix made in 5.1.30, a binary upgrade (performed - without dumping tables with mysqldump before the upgrade and - reloading the dump file after the upgrade) would corrupt - tables. After the fix, CHECK TABLE ... FOR UPGRADE properly - detects the problem and warns about tables that need repair. - However, the fix is not backward compatible and can result in - a downgrading problem under these circumstances: - - 1. Perform a binary upgrade to a version of MySQL that - includes the fix. - - 2. Run CHECK TABLE ... FOR UPGRADE (or mysqlcheck or - mysql_upgrade) to upgrade tables. - - 3. Perform a binary downgrade to a version of MySQL that - does not include the fix. - The solution is to dump tables with mysqldump before the - downgrade and reload the dump file after the downgrade. - Alternatively, drop and recreate affected indexes. - - * Known issue: MySQL introduces encoding for table names that - have non-ASCII characters (see Section 8.2.3, "Mapping of - Identifiers to File Names"). After a binary upgrade from MySQL - 5.0 to 5.1 or higher, the server recognizes names that have - non-ASCII characters and adds a #mysql50# prefix to them. - As of MySQL 5.1.31, mysql_upgrade encodes these names by - executing the following command: -mysqlcheck --all-databases --check-upgrade --fix-db-names --fix-table --names - Prior to MySQL 5.1.31, mysql_upgrade does not execute this - command, so you should execute it manually if you have - database or table names that contain nonalphanumeric - characters. - Prior to MySQL 5.1.23, the mysqlcheck command does not perform - the name encoding for views. To work around this problem, drop - each affected view and recreate it. - mysqlcheck cannot fix names that contain literal instances of - the @ character that is used for encoding special characters. - If you have databases or tables that contain this character, - use mysqldump to dump them before upgrading to MySQL 5.1, and - then reload the dump file after upgrading. - - * Known issue: When upgrading from MySQL 5.0 to versions of 5.1 - prior to 5.1.23, running mysqlcheck (or mysql_upgrade, which - runs mysqlcheck) to upgrade tables fails for names that must - be written as quoted identifiers. To work around this problem, - rename each affected table to a name that does not require - quoting: -RENAME TABLE `tab``le_a` TO table_a; -RENAME TABLE `table b` TO table_b; - After renaming the tables, run the mysql_upgrade program. Then - rename the tables back to their original names: -RENAME TABLE table_a TO `tab``le_a`; -RENAME TABLE table_b TO `table b`; - - * Known issue: In connection with view creation, the server - created arc directories inside database directories and - maintained useless copies of .frm files there. Creation and - renaming procedures of those copies as well as creation of arc - directories has been discontinued in MySQL 5.1.29. - This change does cause a problem when downgrading to older - server versions which manifests itself under these - circumstances: - - 1. Create a view v_orig in MySQL 5.1.29 or higher. - - 2. Rename the view to v_new and then back to v_orig. - - 3. Downgrade to an older 5.1.x server and run mysql_upgrade. - - 4. Try to rename v_orig to v_new again. This operation - fails. - As a workaround to avoid this problem, use either of these - approaches: - - + Dump your data using mysqldump before downgrading and - reload the dump file after downgrading. - - + Instead of renaming a view after the downgrade, drop it - and recreate it. - - * Incompatible change: Character set or collation changes were - made in MySQL 5.1.21, 5.1.23, and 5.1.24 that may require - table indexes to be rebuilt. For details, see Section 2.4.3, - "Checking Whether Tables or Indexes Must Be Rebuilt." - - * Incompatible change: MySQL 5.1 implements support for a plugin - API that allows the loading and unloading of components at - runtime, without restarting the server. Section 22.2, "The - MySQL Plugin API." The plugin API requires the mysql.plugin - table. After upgrading from an older version of MySQL, you - should run the mysql_upgrade command to create this table. See - Section 4.4.8, "mysql_upgrade --- Check Tables for MySQL - Upgrade." - Plugins are installed in the directory named by the plugin_dir - system variable. This variable also controls the location from - which the server loads user-defined functions (UDFs), which is - a change from earlier versions of MySQL. That is, all UDF - library files now must be installed in the plugin directory. - When upgrading from an older version of MySQL, you must - migrate your UDF files to the plugin directory. - - * Incompatible change: The table_cache system variable has been - renamed to table_open_cache. Any scripts that refer to - table_cache must be updated to use the new name. - - * Incompatible change: In MySQL 5.1.36, options for loading - plugins such as pluggable storage engines were changed from - boolean to tristate format. The implementations overlap, but - if you previously used options of the form --plugin_name=0 or - --plugin_name=1, you should instead use --plugin_name=OFF or - --plugin_name=ON, respectively. For details, see Section - 5.1.3, "Server Options for Loading Plugins." - - * Incompatible change: From MySQL 5.1.24 to 5.1.31, the UPDATE - statement was changed such that assigning NULL to a NOT NULL - column caused an error even when strict SQL mode was not - enabled. The original behavior before MySQL 5.1.24 was that - such assignments caused an error only in strict SQL mode, and - otherwise set the column to the implicit default value for the - column data type and generated a warning. (For information - about implicit default values, see Section 10.1.4, "Data Type - Default Values.") - The change caused compatibility problems for applications that - relied on the original behavior. It also caused replication - problems between servers that had the original behavior and - those that did not, for applications that assigned NULL to NOT - NULL columns in UPDATE statements without strict SQL mode - enabled. The change was reverted in MySQL 5.1.32 so that - UPDATE again had the original behavior. Problems can still - occur if you replicate between servers that have the modified - UPDATE behavior and those that do not. - - * Incompatible change: As of MySQL 5.1.29, the default binary - logging mode has been changed from MIXED to STATEMENT for - compatibility with MySQL 5.0. - - * Incompatible change: In MySQL 5.1.25, a change was made to the - way that the server handles prepared statements. This affects - prepared statements processed at the SQL level (using the - PREPARE statement) and those processed using the binary - client-server protocol (using the mysql_stmt_prepare() C API - function). - Previously, changes to metadata of tables or views referred to - in a prepared statement could cause a server crash when the - statement was next executed, or perhaps an error at execute - time with a crash occurring later. For example, this could - happen after dropping a table and recreating it with a - different definition. - Now metadata changes to tables or views referred to by - prepared statements are detected and cause automatic - repreparation of the statement when it is next executed. - Metadata changes occur for DDL statements such as those that - create, drop, alter, rename, or truncate tables, or that - analyze, optimize, or repair tables. Repreparation also occurs - after referenced tables or views are flushed from the table - definition cache, either implicitly to make room for new - entries in the cache, or explicitly due to FLUSH TABLES. - Repreparation is automatic, but to the extent that it occurs, - performance of prepared statements is diminished. - Table content changes (for example, with INSERT or UPDATE) do - not cause repreparation, nor do SELECT statements. - An incompatibility with previous versions of MySQL is that a - prepared statement may now return a different set of columns - or different column types from one execution to the next. For - example, if the prepared statement is SELECT * FROM t1, - altering t1 to contain a different number of columns causes - the next execution to return a number of columns different - from the previous execution. - Older versions of the client library cannot handle this change - in behavior. For applications that use prepared statements - with the new server, an upgrade to the new client library is - strongly recommended. - Along with this change to statement repreparation, the default - value of the table_definition_cache system variable has been - increased from 128 to 256. The purpose of this increase is to - lessen the chance that prepared statements will need - repreparation due to referred-to tables/views having been - flushed from the cache to make room for new entries. - A new status variable, Com_stmt_reprepare, has been introduced - to track the number of repreparations. - - * Incompatible change: As of MySQL 5.1.23, within a stored - routine, it is no longer allowable to declare a cursor for a - SHOW or DESCRIBE statement. This happened to work in some - instances, but is no longer supported. In many cases, a - workaround for this change is to use the cursor with a SELECT - query to read from an INFORMATION_SCHEMA table that produces - the same information as the SHOW statement. - - * Incompatible change: SHOW CREATE VIEW displays view - definitions using an AS alias_name clause for each column. If - a column is created from an expression, the default alias is - the expression text, which can be quite long. As of MySQL - 5.1.23, aliases for column names in CREATE VIEW statements are - checked against the maximum column length of 64 characters - (not the maximum alias length of 256 characters). As a result, - views created from the output of SHOW CREATE VIEW fail if any - column alias exceeds 64 characters. This can cause problems - for replication or loading dump files. For additional - information and workarounds, see Section D.4, "Restrictions on - Views." - - * Incompatible change: Several issues were identified for stored - programs (stored procedures and functions, triggers, and - events) and views containing non-ASCII symbols. These issues - involved conversion errors due to incomplete character set - information when translating these objects to and from stored - format. - To address these problems, the representation for these - objects was changed in MySQL 5.1.21. However, the fixes affect - all stored programs and views. (For example, you will see - warnings about "no creation context.") To avoid warnings from - the server about the use of old definitions from any release - prior to 5.1.21, you should dump stored programs and views - with mysqldump after upgrading to 5.1.21 or higher, and then - reload them to recreate them with new definitions. Invoke - mysqldump with a --default-character-set option that names the - non-ASCII character set that was used for the definitions when - the objects were originally defined. - - * Incompatible change: As of MySQL 5.1.20, mysqld_safe supports - error logging to syslog on systems that support the logger - command. The new --syslog and --skip-syslog options can be - used instead of the --log-error option to control logging - behavior, as described in Section 4.3.2, "mysqld_safe --- - MySQL Server Startup Script." - In 5.1.21 and up, the default is --skip-syslog, which is - compatible with the default behavior of writing an error log - file for releases prior to 5.1.20. - In 5.1.20 only, the following conditions apply: 1) The default - is to use syslog, which is not compatible with releases prior - to 5.1.20. 2) Logging to syslog may fail to operate correctly - in some cases. For these reasons, avoid using MySQL 5.1.20. - - * Incompatible change: As of MySQL 5.1.18, the plugin interface - and its handling of system variables was changed. Command-line - options such as --skip-innodb now cause an error if InnoDB is - not built-in or plugin-loaded. You should use - --loose-skip-innodb if you do not want any error even if - InnoDB is not available. The --loose prefix modifier should be - used for all command-line options where you are uncertain - whether the plugin exists and when you want the operation to - proceed even if the option is necessarily ignored due to the - absence of the plugin. (For a desecription of how --loose - works, see Section 4.2.3.1, "Using Options on the Command - Line.") - - * Incompatible change: As of MySQL 5.1.15, InnoDB rolls back - only the last statement on a transaction timeout. A new - option, --innodb_rollback_on_timeout, causes InnoDB to abort - and roll back the entire transaction if a transaction timeout - occurs (the same behavior as in MySQL 4.1). - - * Incompatible change: As of MySQL 5.1.15, the following - conditions apply to enabling the read_only system variable: - - + If you attempt to enable read_only while you have any - explicit locks (acquired with LOCK TABLES or have a - pending transaction, an error will occur. - - + If other clients hold explicit table locks or have - pending transactions, the attempt to enable read_only - blocks until the locks are released and the transactions - end. While the attempt to enable read_only is pending, - requests by other clients for table locks or to begin - transactions also block until read_only has been set. - - + read_only can be enabled while you hold a global read - lock (acquired with FLUSH TABLES WITH READ LOCK) because - that does not involve table locks. - Previously, the attempt to enable read_only would return - immediately even if explicit locks or transactions were - pending, so some data changes could occur for statements - executing in the server at the same time. - - * Incompatible change: The number of function names affected by - IGNORE_SPACE was reduced significantly in MySQL 5.1.13, from - about 200 to about 30. (For details about IGNORE_SPACE, see - Section 8.2.4, "Function Name Parsing and Resolution.") This - change improves the consistency of parser operation. However, - it also introduces the possibility of incompatibility for old - SQL code that relies on the following conditions: - - + IGNORE_SPACE is disabled. - - + The presence or absence of whitespace following a - function name is used to distinguish between a built-in - function and stored function that have the same name (for - example, PI() versus PI ()). - For functions that are no longer affected by IGNORE_SPACE as - of MySQL 5.1.13, that strategy no longer works. Either of the - following approaches can be used if you have code that is - subject to the preceding incompatibility: - - + If a stored function has a name that conflicts with a - built-in function, refer to the stored function with a - schema name qualifier, regardless of whether whitespace - is present. For example, write schema_name.PI() or - schema_name.PI (). - - + Alternatively, rename the stored function to use a - nonconflicting name and change invocations of the - function to use the new name. - - * Incompatible change: For utf8 columns, the full-text parser - incorrectly considered several nonword punctuation and - whitespace characters as word characters, causing some - searches to return incorrect results. The fix involves a - change to the full-text parser in MySQL 5.1.12, so as of - 5.1.12, any tables that have FULLTEXT indexes on utf8 columns - must be repaired with REPAIR TABLE: -REPAIR TABLE tbl_name QUICK; - - * Incompatible change: Storage engines can be pluggable at - runtime, so the distinction between disabled and invalid - storage engines no longer applies. As of MySQL 5.1.12, this - affects the NO_ENGINE_SUBSTITUTION SQL mode, as described in - Section 5.1.8, "Server SQL Modes." - - * Incompatible change: The structure of FULLTEXT indexes has - been changed in MySQL 5.1.6. After upgrading to MySQL 5.1.6 or - greater, any tables that have FULLTEXT indexes must be - repaired with REPAIR TABLE: -REPAIR TABLE tbl_name QUICK; - - * Incompatible change: In MySQL 5.1.6, when log tables were - implemented, the default log destination for the general query - and slow query log was TABLE. As of MySQL 5.1.21, this default - has been changed to FILE, which is compatible with MySQL 5.0, - but incompatible with earlier releases of MySQL 5.1. If you - are upgrading from MySQL 5.0 to 5.1.21 or higher, no logging - option changes should be necessary. However, if you are - upgrading from 5.1.6 through 5.1.20 to 5.1.21 or higher and - were using TABLE logging, use the --log-output=TABLE option - explicitly to preserve your server's table-logging behavior. - - * Incompatible change: For ENUM columns that had enumeration - values containing commas, the commas were mapped to 0xff - internally. However, this rendered the commas - indistinguishable from true 0xff characters in the values. - This no longer occurs. However, the fix requires that you dump - and reload any tables that have ENUM columns containing true - 0xff in their values: Dump the tables using mysqldump with the - current server before upgrading from a version of MySQL 5.1 - older than 5.1.15 to version 5.1.15 or newer. - - * As of MySQL 5.1.12, the lc_time_names system variable - specifies the locale that controls the language used to - display day and month names and abbreviations. This variable - affects the output from the DATE_FORMAT(), DAYNAME() and - MONTHNAME() functions. See Section 9.7, "MySQL Server Locale - Support." - - * As of MySQL 5.1.9, mysqld_safe no longer implicitly invokes - mysqld-max if it exists. Instead, it invokes mysqld unless a - --mysqld or --mysqld-version option is given to specify - another server explicitly. If you previously relied on the - implicit invocation of mysqld-max, you should use an - appropriate option now. As of MySQL 5.1.12, there is no longer - any separate mysqld-max server, so no change should be - necessary. - - SQL Changes: - - * Known issue: Prior to MySQL 5.1.17, the parser accepted - invalid code in SQL condition handlers, leading to server - crashes or unexpected execution behavior in stored programs. - Specifically, the parser allowed a condition handler to refer - to labels for blocks that enclose the handler declaration. - This was incorrect because block label scope does not include - the code for handlers declared within the labeled block. - As of 5.1.17, the parser rejects this invalid construct, but - if you perform a binary upgrade (without dumping and reloading - your databases), existing handlers that contain the construct - still are invalid and should be rewritten even if they appear - to function as you expect. - To find affected handlers, use mysqldump to dump all stored - procedures and functions, triggers, and events. Then attempt - to reload them into an upgraded server. Handlers that contain - illegal label references will be rejected. - For more information about condition handlers and writing them - to avoid invalid jumps, see Section 12.7.4.2, "DECLARE for - Handlers." - - * Incompatible change: The parser accepted statements that - contained /* ... */ that were not properly closed with */, - such as SELECT 1 /* + 2. As of MySQL 5.1.23, statements that - contain unclosed /*-comments now are rejected with a syntax - error. - This fix has the potential to cause incompatibilities. Because - of Bug#26302: http://bugs.mysql.com/bug.php?id=26302, which - caused the trailing */ to be truncated from comments in views, - stored routines, triggers, and events, it is possible that - objects of those types may have been stored with definitions - that now will be rejected as syntactically invalid. Such - objects should be dropped and re-created so that their - definitions do not contain truncated comments. - - * Incompatible change: Multiple-table DELETE statements - containing ambiguous aliases could have unintended side - effects such as deleting rows from the wrong table. Example: -DELETE FROM t1 AS a2 USING t1 AS a1 INNER JOIN t2 AS a2; - As of MySQL 5.1.23, alias declarations can be declared only in - the table_references part. Elsewhere in the statement, alias - references are allowed but not alias declarations. Statements - containing aliases that are no longer allowed must be - rewritten. - - * Incompatible change: As of MySQL 5.1.8, TYPE = engine_name is - still accepted as a synonym for the ENGINE = engine_name table - option but generates a warning. You should note that this - option is not available in MySQL 5.1.7, and is removed - altogether as of MySQL 5.4 and produces a syntax error. - TYPE has been deprecated since MySQL 4.0. - - * Incompatible change: The namespace for triggers changed in - MySQL 5.0.10. Previously, trigger names had to be unique per - table. Now they must be unique within the schema (database). - An implication of this change is that DROP TRIGGER syntax now - uses a schema name instead of a table name (schema name is - optional and, if omitted, the current schema will be used). - When upgrading from a version of MySQL 5 older than 5.0.10 to - MySQL 5.0.10 or newer, you must drop all triggers and - re-create them or DROP TRIGGER will not work after the - upgrade. Here is a suggested procedure for doing this: - - 1. Upgrade to MySQL 5.0.10 or later to be able to access - trigger information in the INFORMATION_SCHEMA.TRIGGERS - table. (This should work even for pre-5.0.10 triggers.) - - 2. Dump all trigger definitions using the following SELECT - statement: -SELECT CONCAT('CREATE TRIGGER ', t.TRIGGER_SCHEMA, '.', t.TRIGGER_NAM -E, - ' ', t.ACTION_TIMING, ' ', t.EVENT_MANIPULATION, ' ON ' -, - t.EVENT_OBJECT_SCHEMA, '.', t.EVENT_OBJECT_TABLE, - ' FOR EACH ROW ', t.ACTION_STATEMENT, '//' ) -INTO OUTFILE '/tmp/triggers.sql' -FROM INFORMATION_SCHEMA.TRIGGERS AS t; - The statement uses INTO OUTFILE, so you must have the - FILE privilege. The file will be created on the server - host. Use a different file name if you like. To be 100% - safe, inspect the trigger definitions in the triggers.sql - file, and perhaps make a backup of the file. - - 3. Stop the server and drop all triggers by removing all - .TRG files in your database directories. Change location - to your data directory and issue this command: -shell> rm */*.TRG - - 4. Start the server and re-create all triggers using the - triggers.sql file: -mysql> delimiter // ; -mysql> source /tmp/triggers.sql // - - 5. Check that all triggers were successfully created using - the SHOW TRIGGERS statement. - - * Incompatible change: MySQL 5.1.6 introduces the TRIGGER - privilege. Previously, the SUPER privilege was needed to - create or drop triggers. Now those operations require the - TRIGGER privilege. This is a security improvement because you - no longer need to grant users the SUPER privilege to enable - them to create triggers. However, the requirement that the - account named in a trigger's DEFINER clause must have the - SUPER privilege has changed to a requirement for the TRIGGER - privilege. When upgrading from a previous version of MySQL 5.0 - or 5.1 to MySQL 5.1.6 or newer, be sure to update your grant - tables by running mysql_upgrade. This will assign the TRIGGER - privilege to all accounts that had the SUPER privilege. If you - fail to update the grant tables, triggers may fail when - activated. After updating the grant tables, you can revoke the - SUPER privilege from those accounts that no longer otherwise - require it. - - * Some keywords may be reserved in MySQL 5.1 that were not - reserved in MySQL 5.0. See Section 8.3, "Reserved Words." - - * The BACKUP TABLE, and RESTORE TABLE statements are deprecated. - mysqldump or mysqlhotcopy can be used as alternatives. - - * The LOAD DATA FROM MASTER and LOAD TABLE FROM MASTER - statements are deprecated. See Section 12.5.2.2, "LOAD DATA - FROM MASTER Syntax," for recommended alternatives. - - * The INSTALL PLUGIN and UNINSTALL PLUGIN statements that are - used for the plugin API are new. So is the WITH PARSER clause - for FULLTEXT index creation that associates a parser plugin - with a full-text index. Section 22.2, "The MySQL Plugin API." - - C API Changes: - - * Incompatible change: As of MySQL 5.1.7, the - mysql_stmt_attr_get() C API function returns a boolean rather - than an unsigned int for STMT_ATTR_UPDATE_MAX_LENGTH. - (Bug#16144: http://bugs.mysql.com/bug.php?id=16144) - -2.4.2. Downgrading MySQL - - This section describes what you should do to downgrade to an older - MySQL version in the unlikely case that the previous version - worked better than the new one. - - If you are downgrading within the same release series (for - example, from 5.0.13 to 5.0.12) the general rule is that you just - have to install the new binaries on top of the old ones. There is - no need to do anything with the databases. As always, however, it - is always a good idea to make a backup. - - The following items form a checklist of things you should do - whenever you perform a downgrade: - - * Read the upgrading section for the release series from which - you are downgrading to be sure that it does not have any - features you really need. See Section 2.4.1, "Upgrading - MySQL." - - * If there is a downgrading section for that version, you should - read that as well. - - * To see which new features were added between the version to - which you are downgrading and your current version, see the - change logs (Appendix C, "MySQL Change History"). - - * Check Section 2.4.3, "Checking Whether Tables or Indexes Must - Be Rebuilt," to see whether changes to table formats or to - character sets or collations were made between your current - version of MySQL and the version to which you are downgrading. - If so and these changes result in an incompatibility between - MySQL versions, you will need to downgrade the affected tables - using the instructions in Section 2.4.4, "Rebuilding or - Repairing Tables or Indexes." - - In most cases, you can move the MySQL format files and data files - between different versions on the same architecture as long as you - stay within versions for the same release series of MySQL. - - If you downgrade from one release series to another, there may be - incompatibilities in table storage formats. In this case, use - mysqldump to dump your tables before downgrading. After - downgrading, reload the dump file using mysql or mysqlimport to - re-create your tables. For examples, see Section 2.4.5, "Copying - MySQL Databases to Another Machine." - - A typical symptom of a downward-incompatible table format change - when you downgrade is that you cannot open tables. In that case, - use the following procedure: - - 1. Stop the older MySQL server that you are downgrading to. - - 2. Restart the newer MySQL server you are downgrading from. - - 3. Dump any tables that were inaccessible to the older server by - using mysqldump to create a dump file. - - 4. Stop the newer MySQL server and restart the older one. - - 5. Reload the dump file into the older server. Your tables should - be accessible. - - It might also be the case that system tables in the mysql database - have changed and that downgrading introduces some loss of - functionality or requires some adjustments. Here are some - examples: - - * Trigger creation requires the TRIGGER privilege as of MySQL - 5.1. In MySQL 5.0, there is no TRIGGER privilege and SUPER is - required instead. If you downgrade from MySQL 5.1 to 5.0, you - will need to give the SUPER privilege to those accounts that - had the TRIGGER privilege in 5.1. - - * Triggers were added in MySQL 5.0, so if you downgrade from 5.0 - to 4.1, you cannot use triggers at all. - - * The mysql.proc.comment column definition changed between MySQL - 5.1 and 5.5. After a downgrade from 5.5 to 5.1, this table is - seen as corrupt and in need of repair. To workaround this - problem, execute mysql_upgrade from the version of MySQL to - which you downgraded. - -2.4.2.1. Downgrading to MySQL 5.0 - - When downgrading to MySQL 5.0 from MySQL 5.1, you should keep in - mind the following issues relating to features found in MySQL 5.1, - but not in MySQL 5.0: - - * Partitioning. MySQL 5.0 does not support user-defined - partitioning. If a table was created as a partitioned table in - 5.1 (or if an table created in a previous version of MySQL was - altered to include partitions after an upgrade to 5.1), the - table is accessible after downgrade only if you do one of the - following: - - + Export the table using mysqldump and then drop it in - MySQL 5.1; import the table again following the downgrade - to MySQL 5.0. - - + Prior to the downgrade, remove the table's partitioning - using ALTER TABLE table_name REMOVE PARTITIONING. - - * Event Scheduler. MySQL 5.0 does not support scheduled events. - If your databases contain scheduled event definitions, you - should prevent them from being dumped when you use mysqldump - by using the --skip-events option. (See Section 4.5.4, - "mysqldump --- A Database Backup Program.") - - * Stored routines. MySQL 5.1.21 added a number of new columns - to the mysql.proc table in which stored routine definitions - are stored. If you are downgrading from MySQL 5.1.21 or later - to MySQL 5.0, you cannot import the MySQL 5.1 routine - definitions into MySQL 5.0.46 or earlier using the dump of - mysql.proc created by mysqldump (such as when using the - --all-databases option). Instead, you should run mysqldump - --routines prior to performing the downgrade and run the - stored routines DDL statements following the downgrade. - See Bug#11986: http://bugs.mysql.com/bug.php?id=11986, - Bug#30029: http://bugs.mysql.com/bug.php?id=30029, and - Bug#30660: http://bugs.mysql.com/bug.php?id=30660, for more - information. - - * Triggers. Trigger creation requires the TRIGGER privilege as - of MySQL 5.1. In MySQL 5.0, there is no TRIGGER privilege and - SUPER is required instead. If you downgrade from MySQL 5.1 to - 5.0, you will need to give the SUPER privilege to those - accounts that had the TRIGGER privilege in 5.1. - -2.4.3. Checking Whether Tables or Indexes Must Be Rebuilt - - A binary upgrade or downgrade is one that installs one version of - MySQL "in place" over an existing version, without dumping and - reloading tables: - - 1. Stop the server for the existing version if it is running. - - 2. Install a different version of MySQL. This is an upgrade if - the new version is higher than the original version, a - downgrade if the version is lower. - - 3. Start the server for the new version. - - In many cases, the tables from the previous version of MySQL can - be used without problem by the new version. However, sometimes - changes occur that require tables or table indexes to be rebuilt, - as described in this section. If you have tables that are affected - by any of the issues described here, rebuild the tables or indexes - as necessary using the instructions given in Section 2.4.4, - "Rebuilding or Repairing Tables or Indexes." - - Table Incompatibilities - - After a binary upgrade to MySQL 5.1 from a MySQL 5.0 installation - that contains ARCHIVE tables, accessing those tables causes the - server to crash, even if you have run mysql_upgrade or CHECK TABLE - ... FOR UPGRADE. To work around this problem, use mysqldump to - dump all ARCHIVE tables before upgrading, and reload them into - MySQL 5.1 after upgrading. The same problem occurs for binary - downgrades from MySQL 5.1 to 5.0. - - Index Incompatibilities - - If you perform a binary upgrade without dumping and reloading - tables, you cannot upgrade directly from MySQL 4.1 to 5.1 or - higher. This occurs due to an incompatible change in the MyISAM - table index format in MySQL 5.0. Upgrade from MySQL 4.1 to 5.0 and - repair all MyISAM tables. Then upgrade from MySQL 5.0 to 5.1 and - check and repair your tables. - - Modifications to the handling of character sets or collations - might change the character sort order, which causes the ordering - of entries in any index that uses an affected character set or - collation to be incorrect. Such changes result in several possible - problems: - - * Comparison results that differ from previous results - - * Inability to find some index values due to misordered index - entries - - * Misordered ORDER BY results - - * Tables that CHECK TABLE reports as being in need of repair - - The solution to these problems is to rebuild any indexes that use - an affected character set or collation, either by dropping and - re-creating the indexes, or by dumping and reloading the entire - table. For information about rebuilding indexes, see Section - 2.4.4, "Rebuilding or Repairing Tables or Indexes." - - To check whether a table has indexes that must be rebuilt, consult - the following list. It indicates which versions of MySQL - introduced character set or collation changes that require indexes - to be rebuilt. Each entry indicates the version in which the - change occurred and the character sets or collations that the - change affects. If the change is associated with a particular bug - report, the bug number is given. - - The list applies both for binary upgrades and downgrades. For - example, Bug#27877: http://bugs.mysql.com/bug.php?id=27877 was - fixed in MySQL 5.1.24 and 5.4.0, so it applies to upgrades from - versions older than 5.1.24 to 5.1.24 or newer, and to downgrades - from 5.1.24 or newer to versions older than 5.1.24. - - In many cases, you can use CHECK TABLE ... FOR UPGRADE to identify - tables for which index rebuilding is required. (It will report: - Table upgrade required. Please do "REPAIR TABLE `tbl_name`" or - dump/reload to fix it!) In these cases, you can also use - mysqlcheck --check-upgrade or mysql_upgrade, which execute CHECK - TABLE. However, the use of CHECK TABLE applies only after - upgrades, not downgrades. Also, CHECK TABLE is not applicable to - all storage engines. For details about which storage engines CHECK - TABLE supports, see Section 12.4.2.3, "CHECK TABLE Syntax." - - Changes that cause index rebuilding to be necessary: - - * MySQL 5.0.48, 5.1.21 - (Bug#29461: http://bugs.mysql.com/bug.php?id=29461) - Affects indexes for columns that use any of these character - sets: eucjpms, euc_kr, gb2312, latin7, macce, ujis - Affected tables can be detected by CHECK TABLE ... FOR UPGRADE - as of MySQL 5.1.29, 5.4.0 (see - Bug#39585: http://bugs.mysql.com/bug.php?id=39585). - - * MySQL 5.0.48, 5.1.23 - (Bug#27562: http://bugs.mysql.com/bug.php?id=27562) - Affects indexes that use the ascii_general_ci collation for - columns that contain any of these characters: '`' GRAVE - ACCENT, '[' LEFT SQUARE BRACKET, '\' REVERSE SOLIDUS, ']' - RIGHT SQUARE BRACKET, '~' TILDE - Affected tables can be detected by CHECK TABLE ... FOR UPGRADE - as of MySQL 5.1.29, 5.4.0 (see - Bug#39585: http://bugs.mysql.com/bug.php?id=39585). - - * MySQL 5.1.24, 5.4.0 - (Bug#27877: http://bugs.mysql.com/bug.php?id=27877) - Affects indexes that use the utf8_general_ci or - ucs2_general_ci collation for columns that contain 'ß' LATIN - SMALL LETTER SHARP S (German). - Affected tables can be detected by CHECK TABLE ... FOR UPGRADE - as of MySQL 5.1.30, 5.4.0 (see - Bug#40053: http://bugs.mysql.com/bug.php?id=40053). - -2.4.4. Rebuilding or Repairing Tables or Indexes - - This section describes how to rebuild a table. This can be - necessitated by changes to MySQL such as how data types are - handled or changes to character set handling. For example, an - error in a collation might have been corrected, necessitating a - table rebuild to update the indexes for character columns that use - the collation. (For examples, see Section 2.4.3, "Checking Whether - Tables or Indexes Must Be Rebuilt.") It might also be that a table - repair or upgrade should be done as indicated by a table check - operation such as that performed by CHECK TABLE, mysqlcheck, or - mysql_upgrade. - - Methods for rebuilding a table include dumping and reloading it, - or using ALTER TABLE or REPAIR TABLE. - -Note - - If you are rebuilding tables because a different version of MySQL - will not handle them after a binary (in-place) upgrade or - downgrade, you must use the dump-and-reload method. Dump the - tables before upgrading or downgrading using your original version - of MySQL. Then reload the tables after upgrading or downgrading. - - If you use the dump-and-reload method of rebuilding tables only - for the purpose of rebuilding indexes, you can perform the dump - either before or after upgrading or downgrading. Reloading still - must be done afterward. - - To rebuild a table by dumping and reloading it, use mysqldump to - create a dump file and mysql to reload the file: -shell> mysqldump db_name t1 > dump.sql -shell> mysql db_name < dump.sql - - To rebuild all the tables in a single database, specify the - database name without any following table name: -shell> mysqldump db_name > dump.sql -shell> mysql db_name < dump.sql - - To rebuild all tables in all databases, use the --all-databases - option: -shell> mysqldump --all-databases > dump.sql -shell> mysql < dump.sql - - To rebuild a table with ALTER TABLE, use a "null" alteration; that - is, an ALTER TABLE statement that "changes" the table to use the - storage engine that it already has. For example, if t1 is a MyISAM - table, use this statement: -mysql> ALTER TABLE t1 ENGINE = MyISAM; - - If you are not sure which storage engine to specify in the ALTER - TABLE statement, use SHOW CREATE TABLE to display the table - definition. - - If you must rebuild a table because a table checking operation - indicates that the table is corrupt or needs an upgrade, you can - use REPAIR TABLE if that statement supports the table's storage - engine. For example, to repair a MyISAM table, use this statement: -mysql> REPAIR TABLE t1; - - For storage engines such as InnoDB that REPAIR TABLE does not - support, use mysqldump to create a dump file and mysql to reload - the file, as described earlier. - - For specifics about which storage engines REPAIR TABLE supports, - see Section 12.4.2.6, "REPAIR TABLE Syntax." - - mysqlcheck --repair provides command-line access to the REPAIR - TABLE statement. This can be a more convenient means of repairing - tables because you can use the --databases or --all-databases - option to repair all tables in specific databases or all - databases, respectively: -shell> mysqlcheck --repair --databases db_name ... -shell> mysqlcheck --repair --all-databases - -2.4.5. Copying MySQL Databases to Another Machine - - You can copy the .frm, .MYI, and .MYD files for MyISAM tables - between different architectures that support the same - floating-point format. (MySQL takes care of any byte-swapping - issues.) See Section 13.5, "The MyISAM Storage Engine." - - In cases where you need to transfer databases between different - architectures, you can use mysqldump to create a file containing - SQL statements. You can then transfer the file to the other - machine and feed it as input to the mysql client. - - Use mysqldump --help to see what options are available. - - The easiest (although not the fastest) way to move a database - between two machines is to run the following commands on the - machine on which the database is located: -shell> mysqladmin -h 'other_hostname' create db_name -shell> mysqldump db_name | mysql -h 'other_hostname' db_name - - If you want to copy a database from a remote machine over a slow - network, you can use these commands: -shell> mysqladmin create db_name -shell> mysqldump -h 'other_hostname' --compress db_name | mysql db_na -me - - You can also store the dump in a file, transfer the file to the - target machine, and then load the file into the database there. - For example, you can dump a database to a compressed file on the - source machine like this: -shell> mysqldump --quick db_name | gzip > db_name.gz - - Transfer the file containing the database contents to the target - machine and run these commands there: -shell> mysqladmin create db_name -shell> gunzip < db_name.gz | mysql db_name - - You can also use mysqldump and mysqlimport to transfer the - database. For large tables, this is much faster than simply using - mysqldump. In the following commands, DUMPDIR represents the full - path name of the directory you use to store the output from - mysqldump. - - First, create the directory for the output files and dump the - database: -shell> mkdir DUMPDIR -shell> mysqldump --tab=DUMPDIR db_name - - Then transfer the files in the DUMPDIR directory to some - corresponding directory on the target machine and load the files - into MySQL there: -shell> mysqladmin create db_name # create database -shell> cat DUMPDIR/*.sql | mysql db_name # create tables in databas -e -shell> mysqlimport db_name DUMPDIR/*.txt # load data into tables - - Do not forget to copy the mysql database because that is where the - grant tables are stored. You might have to run commands as the - MySQL root user on the new machine until you have the mysql - database in place. - - After you import the mysql database on the new machine, execute - mysqladmin flush-privileges so that the server reloads the grant - table information. - -2.5. Installing MySQL on Windows - - This section describes the process for installing MySQL on - Windows. - - To run MySQL on Windows, you need the following: - - * A Windows operating system such as Windows 2000, Windows XP, - Windows Vista, Windows Server 2003, or Windows Server 2008. - Both 32-bit and 64-bit versions are supported. - In addition to running MySQL as a standard application, you - can also run the MySQL server as a Windows service. By using a - service you can monitor and control the operation of the - server through the standard Windows service management tools. - For more information, see Section 2.5.5.6, "Starting MySQL as - a Windows Service." - Generally, you should install MySQL on Windows using an - account that has administrator rights. Otherwise, you may - encounter problems with certain operations such as editing the - PATH environment variable or accessing the Service Control - Manager. Once installed, MySQL does not need to be executed - using a user with Administrator privileges. - - * TCP/IP protocol support. - - * Enough space on the hard drive to unpack, install, and create - the databases in accordance with your requirements (generally - a minimum of 200 megabytes is recommended.) - - For a list of limitations within the Windows version of MySQL, see - Section D.7.3, "Windows Platform Limitations." - - In addition to the MySQL Server package, you may need or want - additional components to use MySQL with your application or - development environment. These include, but are not limited to: - - * If you plan to connect to the MySQL server via ODBC, you need - a Connector/ODBC driver. For more information, including - installation and configuration instructions, see Section 21.1, - "MySQL Connector/ODBC." - - * If you plan to use MySQL server with .NET applications, you - need the Connector/NET driver. For more information, including - installation and configuration instructions, see Section 21.2, - "MySQL Connector/NET." - - MySQL distributions for Windows can be downloaded from - http://dev.mysql.com/downloads/. See Section 2.1.3, "How to Get - MySQL." - - MySQL for Windows is available in several distribution formats, - detailed below. Generally speaking, you should use a binary - distribution that includes an installer. It is simpler to use than - the others, and you need no additional tools to get MySQL up and - running. The installer for the Windows version of MySQL, combined - with a GUI Config Wizard, automatically installs MySQL, creates an - option file, starts the server, and secures the default user - accounts. - - * Binary installer distribution. The installable distribution - comes packaged as a Microsoft Windows Installer (MSI) package - that you can install manually or automatically on your - systems. Two formats are available, an essentials package that - contains all the files you need to install and configure - MySQL, but no additional components, and a complete package - that includes MySQL, configuration tools, benchmarks and other - components. For more information on the specific differences, - see Section 2.5.2, "Choosing An Installation Package" - For instructions on installing MySQL using one of the MSI - installation packages, see Section 2.5.3, "Installing MySQL - with the MSI Package." - - * Standard binary distribution format packaged as a Zip file - containing all of the necessary files that you unpack into - your chosen location. This package contains all of the files - in the full Windows MSI Installer package, but does not - including an installation program. - For instructions on installing MySQL using the Zip file, see - Section 2.5.5, "Installing MySQL from a noinstall Zip - Archive." - - * The source distribution contains all the code and support - files for building the executables using the Visual Studio - compiler system. - For instructions on building MySQL from source on Windows, see - Section 2.5.10, "Installing MySQL from Source on Windows." - - MySQL on Windows considerations: - - * Large Table Support - If you need tables with a size larger than 4GB, install MySQL - on an NTFS or newer file system. Don't forget to use MAX_ROWS - and AVG_ROW_LENGTH when you create tables. See Section - 12.1.17, "CREATE TABLE Syntax." - - * MySQL and Virus Checking Software - Using virus scanning software such as Norton/Symantec - Anti-Virus on directories containing MySQL data and temporary - tables can cause issues, both in terms of the performance of - MySQL and the virus-scanning software mis-identifying the - contents of the files as containing spam. This is because of - the fingerprinting mechanism used by the virus scanning - software, and the way in which MySQL rapidly updates different - files, which may be identified as a potential security risk. - After installing MySQL Server, it is recommended that you - disable virus scanning on the main directory (datadir) being - used to store your MySQL table data. There is usually a system - built into the virus scanning software to allow certain - directories to be specifically ignored during virus scanning. - In addition, by default, MySQL creates temporary files in the - standard Windows temporary directory. To prevent the temporary - files also being scanned, you should configure a separate - temporary directory for MySQL temporary files and add this to - the virus scanning exclusion list. To do this, add a - configuration option for the tmpdir parameter to your my.ini - configuration file. For more information, see Section 2.5.5.2, - "Creating an Option File." - -2.5.1. Windows Installation Layout - - For MySQL 5.1 on Windows, the default installation directory is - C:\Program Files\MySQL\MySQL Server 5.1. Some Windows users prefer - to install in C:\mysql, the directory that formerly was used as - the default. However, the layout of the subdirectories remains the - same. - - For MySQL 5.1.23 and earlier, all of the files are located within - this parent directory, using the following structure: - - Table 2.2. Installation Layout for Windows using MySQL 5.1.23 and - earlier - Directory Contents of Directory - bin Client programs and the mysqld server - data Log files, databases - Docs Manual in CHM format - examples Example programs and scripts - include Include (header) files - lib Libraries - scripts Utility scripts - share Error message files - - For MySQL 5.1.24 and later, the default location of data directory - was changed. The remainder of the directory structure remains the - same: - - Table 2.3. Installation Layout for Windows using MySQL 5.1.24 and - later - Directory Contents of Directory - bin Client programs and the mysqld server - C:\Documents and Settings\All Users\Application Data\MySQL Log - files, databases - Docs Manual in CHM format - examples Example programs and scripts - include Include (header) files - lib Libraries - scripts Utility scripts - share Error message files - -2.5.2. Choosing An Installation Package - - For MySQL 5.1, there are three installation packages to choose - from when installing MySQL on Windows: - Packaging - Feature Essentials Complete Zip (No-install) - Installer Yes Yes No - Directory-only - MySQL Server Instance Config Wizard Yes Yes No - Test Suite No Yes Yes - MySQL Server Yes Yes Yes - MySQL Client Programs Yes Yes Yes - C Headers/Libraries Yes Yes Yes - Embedded Server No Optional Yes - Scripts and Examples No Optional Yes - - In the above table: - - * Yes indiciates that the component is installed by default. - - * No indicates that the component is not installed or included. - - * Optional indicates that the component is included with the - package, but not installed unless explicitly requested using - the Custom installation mode. - - The workflow for installing using the MSI installer is shown - below: - - Figure 2.1. Installation Workflow for Windows using MSI - Installation Workflow for Windows using MSI - - The workflow for installing using the MSI installer is shown - below: - - Figure 2.2. Installation Workflow for Windows using Zip - Installation Workflow for Windows using Zip - -Note - - For the Essentials and Complete packages in the MSI installer, you - can select individual components to be installed by using the - Custom mode, including disable the components confiurated for - installation by default. - - Full details on the components are suggested uses are provided - below for reference: - - * Windows Essentials --- this package has a file name similar to - mysql-essential-5.1.46-win32.msi and is supplied as a - Microsoft Installer (MSI) package. The package includes the - minimum set of files needed to install MySQL on Windows, - including the MySQL Server Instance Config Wizard. This - package does not include optional components such as the - embedded server, developer headers and libraries or benchmark - suite. - To install using this package, see Section 2.5.3, "Installing - MySQL with the MSI Package." - - * Windows MSI Installer (Complete) --- this package has a file - name similar to mysql-5.1.46-win32.zip and contains all files - needed for a complete Windows installation, including the - MySQL Server Instance Config Wizard. This package includes - optional components such as the embedded server and benchmark - suite. - To install using this package, see Section 2.5.3, "Installing - MySQL with the MSI Package." - - * Without installer --- this package has a file name similar to - mysql-noinstall-5.1.46-win32.zip and contains all the files - found in the Complete install package, with the exception of - the MySQL Server Instance Config Wizard. This package does not - include an automated installer, and must be manually installed - and configured. - - The Essentials package is recommended for most users. Both the - Essentials and Complete distributions are available as an .msi - file for use with the Windows Installer. The Noinstall - distribution is packaged as Zip archives. To use Zip archives, you - must have a tool that can unpack .zip files. - - When using the MSI installers you can automate the installation - process. For more information, see Section 2.5.3.2, "Installing - MySQL Automatically using MSI." To automate the creation of a - MySQL instance, see Section 2.5.4.13, "Creating an Instance from - the Command Line." - - Your choice of install package affects the installation process - you must follow. If you choose to install either the Essentials or - Complete install packages, see Section 2.5.3, "Installing MySQL - with the MSI Package." If you choose to install MySQL from the - Noinstall archive, see Section 2.5.5, "Installing MySQL from a - noinstall Zip Archive." - -2.5.3. Installing MySQL with the MSI Package - - The MSI package are designed to install and configure MySQL in - such a way that you can immediately get started using MySQL. - - The MySQL Installation Wizard and MySQL Config Wizard are - available in the Essentials and Complete install packages. They - are recommended for most standard MySQL installations. Exceptions - include users who need to install multiple instances of MySQL on a - single server host and advanced users who want complete control of - server configuration. - - * For information on installing using the GUI MSI installer - process, see Section 2.5.3, "Installing MySQL with the MSI - Package." - - * For information on installing using the command line using the - MSI package, see Section 2.5.3.2, "Installing MySQL - Automatically using MSI." - - * If you have previously installed MySQL using the MSI package - and want to remove MySQL, see Section 2.5.3.3, "Removing MySQL - Installed from the MSI Package." - - The workflow sequence for using the installer is shown in the - figure below: - - Figure 2.3. Installation Workflow for Windows using MSI Installer - Installation Workflow for Windows using MSI Installer - -Note - - Microsoft Windows XP and later include a firewall which - specifically blocks ports. If you plan on using MySQL through a - network port then you should open and create an exception for this - port before performing the installation. To check and if necessary - add an exception to the firewall settings: - - 1. First ensure that you are logged in as an Administrator or a - user with Administrator privileges. - - 2. Go to the Control Panel, and double click the Windows Firewall - icon. - - 3. Choose the Allow a program through Windows Firewall option and - click the Add port button. - - 4. Enter MySQL into the Name text box and 3306 (or the port of - your choice) into the Port number text box. - - 5. Also ensure that the TCP protocol radio button is selected. - - 6. If you wish, you can also limit access to the MySQL server by - choosing the Change scope button. - - 7. Confirm your choices by clicking the OK button. - - Additionally, when running the MySQL Installation Wizard on - Windows Vista, ensure that you are logged in as a user with - administrative rights. - -Note - - When using Windows Vista, you may want to disable User Account - Control (UAC) before performing the installation. If you do not do - so, then MySQL may be identified as a security risk, which will - mean that you need to enable MySQL. You can disable the security - checking by following these instructions: - - 1. Open Control Panel. - - 2. Under the User Accounts and Family Safety, select Add or - remove user accounts. - - 3. Click on the Got to the main User Accounts page link. - - 4. Click on Turn User Account Control on or off. You may be - prompted to provide permission to change this setting. Click - Continue. - - 5. Deselect or unceck the checkbox next to Use User Account - Control (UAC) to help protect your computer. Click OK to save - the setting. - - You will need to restart to complete the process. Click Restart - Now to reboot the machine and apply the changes. You can then - follow the instructions below for installing Windows. - -2.5.3.1. Using the MySQL Installation Wizard - - MySQL Installation Wizard is an installer for the MySQL server - that uses the latest installer technologies for Microsoft Windows. - The MySQL Installation Wizard, in combination with the MySQL - Config Wizard, allows a user to install and configure a MySQL - server that is ready for use immediately after installation. - - The MySQL Installation Wizard uses the standard Microsoft - Installer Engine (MSI) system is the standard installer for all - MySQL server distributions, version 4.1.5 and higher. Users of - previous versions of MySQL need to shut down and remove their - existing MySQL installations manually before installing MySQL with - the MySQL Installation Wizard. See Section 2.5.3.1.6, "Upgrading - MySQL with the Installation Wizard," for more information on - upgrading from a previous version. - - If you are upgrading an installation from MySQL 5.1.31 or earlier - to MySQL 5.1.32 or later, read the notes provided in Section - 2.5.3.1.6, "Upgrading MySQL with the Installation Wizard." - - The Microsoft Windows Installer Engine was updated with the - release of Windows XP; those using a previous version of Windows - can reference this Microsoft Knowledge Base article - (http://support.microsoft.com/default.aspx?scid=kb;EN-US;292539) - for information on upgrading to the latest version of the Windows - Installer Engine. - - In addition, Microsoft has introduced the WiX (Windows Installer - XML) toolkit. This is the first highly acknowledged Open Source - project from Microsoft. We have switched to WiX because it is an - Open Source project and it allows us to handle the complete - Windows installation process in a flexible manner using scripts. - - Improving the MySQL Installation Wizard depends on the support and - feedback of users like you. If you find that the MySQL - Installation Wizard is lacking some feature important to you, or - if you discover a bug, please report it in our bugs database using - the instructions given in Section 1.7, "How to Report Bugs or - Problems." - -2.5.3.1.1. Downloading and Starting the MySQL Installation Wizard - - The MySQL installation packages can be downloaded from - http://dev.mysql.com/downloads/. If the package you download is - contained within a Zip archive, you need to extract the archive - first. - - The process for starting the wizard depends on the contents of the - installation package you download. If there is a setup.exe file - present, double-click it to start the installation process. If - there is an .msi file present, double-click it to start the - installation process. - -2.5.3.1.2. Choosing an Install Type - - There are three installation types available: Typical, Complete, - and Custom. - - The Typical installation type installs the MySQL server, the mysql - command-line client, and the command-line utilities. The - command-line clients and utilities include mysqldump, myisamchk, - and several other tools to help you manage the MySQL server. - - The Complete installation type installs all components included in - the installation package. The full installation package includes - components such as the embedded server library, the benchmark - suite, support scripts, and documentation. - - The Custom installation type gives you complete control over which - packages you wish to install and the installation path that is - used. See Section 2.5.3.1.3, "The Custom Install Dialog," for more - information on performing a custom install. - - If you choose the Typical or Complete installation types and click - the Next button, you advance to the confirmation screen to verify - your choices and begin the installation. If you choose the Custom - installation type and click the Next button, you advance to the - custom installation dialog, described in Section 2.5.3.1.3, "The - Custom Install Dialog." - -2.5.3.1.3. The Custom Install Dialog - - If you wish to change the installation path or the specific - components that are installed by the MySQL Installation Wizard, - choose the Custom installation type. - - A tree view on the left side of the custom install dialog lists - all available components. Components that are not installed have a - red X icon; components that are installed have a gray icon. To - change whether a component is installed, click on that component's - icon and choose a new option from the drop-down list that appears. - - You can change the default installation path by clicking the - Change... button to the right of the displayed installation path. - - After choosing your installation components and installation path, - click the Next button to advance to the confirmation dialog. - -2.5.3.1.4. The Confirmation Dialog - - Once you choose an installation type and optionally choose your - installation components, you advance to the confirmation dialog. - Your installation type and installation path are displayed for you - to review. - - To install MySQL if you are satisfied with your settings, click - the Install button. To change your settings, click the Back - button. To exit the MySQL Installation Wizard without installing - MySQL, click the Cancel button. - - After installation is complete, you have the option of registering - with the MySQL web site. Registration gives you access to post in - the MySQL forums at forums.mysql.com (http://forums.mysql.com), - along with the ability to report bugs at bugs.mysql.com - (http://bugs.mysql.com) and to subscribe to our newsletter. The - final screen of the installer provides a summary of the - installation and gives you the option to launch the MySQL Config - Wizard, which you can use to create a configuration file, install - the MySQL service, and configure security settings. - -2.5.3.1.5. Changes Made by MySQL Installation Wizard - - Once you click the Install button, the MySQL Installation Wizard - begins the installation process and makes certain changes to your - system which are described in the sections that follow. - - Changes to the Registry - - The MySQL Installation Wizard creates one Windows registry key in - a typical install situation, located in - HKEY_LOCAL_MACHINE\SOFTWARE\MySQL AB. - - The MySQL Installation Wizard creates a key named after the major - version of the server that is being installed, such as MySQL - Server 5.1. It contains two string values, Location and Version. - The Location string contains the path to the installation - directory. In a default installation it contains C:\Program - Files\MySQL\MySQL Server 5.1\. The Version string contains the - release number. For example, for an installation of MySQL Server - 5.1.46, the key contains a value of 5.1.46. - - These registry keys are used to help external tools identify the - installed location of the MySQL server, preventing a complete scan - of the hard-disk to determine the installation path of the MySQL - server. The registry keys are not required to run the server, and - if you install MySQL using the noinstall Zip archive, the registry - keys are not created. - - Changes to the Start Menu - - The MySQL Installation Wizard creates a new entry in the Windows - Start menu under a common MySQL menu heading named after the major - version of MySQL that you have installed. For example, if you - install MySQL 5.1, the MySQL Installation Wizard creates a MySQL - Server 5.1 section in the Start menu. - - The following entries are created within the new Start menu - section: - - * MySQL Command Line Client: This is a shortcut to the mysql - command-line client and is configured to connect as the root - user. The shortcut prompts for a root user password when you - connect. - - * MySQL Server Instance Config Wizard: This is a shortcut to the - MySQL Config Wizard. Use this shortcut to configure a newly - installed server, or to reconfigure an existing server. - - * MySQL Documentation: This is a link to the MySQL server - documentation that is stored locally in the MySQL server - installation directory. This option is not available when the - MySQL server is installed using the Essentials installation - package. - - Changes to the File System - - The MySQL Installation Wizard by default installs the MySQL 5.1 - server to C:\Program Files\MySQL\MySQL Server 5.1, where Program - Files is the default location for applications in your system, and - 5.1 is the major version of your MySQL server. This is the - recommended location for the MySQL server, replacing the former - default location C:\mysql. - - By default, all MySQL applications are stored in a common - directory at C:\Program Files\MySQL, where Program Files is the - default location for applications in your Windows installation. A - typical MySQL installation on a developer machine might look like - this: -C:\Program Files\MySQL\MySQL Server 5.1 -C:\Program Files\MySQL\MySQL Workbench 5.1 OSS - - This approach makes it easier to manage and maintain all MySQL - applications installed on a particular system. - - In MySQL 5.1.23 and earlier, the default location for the data - files used by MySQL is located within the corresponding MySQL - Server installation directory. For MySQL 5.1.24 and later, the - default location of the data directory is the AppData directory - configured for the user that installed the MySQL application. - -2.5.3.1.6. Upgrading MySQL with the Installation Wizard - - The MySQL Installation Wizard can perform server upgrades - automatically using the upgrade capabilities of MSI. That means - you do not need to remove a previous installation manually before - installing a new release. The installer automatically shuts down - and removes the previous MySQL service before installing the new - version. - - Automatic upgrades are available only when upgrading between - installations that have the same major and minor version numbers. - For example, you can upgrade automatically from MySQL 5.1.34 to - MySQL 5.1.37, but not from MySQL 5.0 to MySQL 5.1. - - In MySQL 5.1.32 and later, the EXE version of the MSI installer - packages were removed. When upgrading an existing MySQL - installation from the old EXE based installer to the MSI based - installer, please keep the following notes in mind: - - * The MSI installer will not identify an existing installation - that was installed using the old EXE installer. This means - that the installer will not stop the existing server, or - detect that the existing password is required before - installing the new version. To work around this: - - 1. Stop the current server manually using net stop or - mysqladmin shutdown. - - 2. Remove the existing installation manually by using the - Add/Remove Programs control panel. This will keep the - existing configuration and data files, as these are not - removed automatically. - - 3. Install the new version of MySQL using the MSI installer. - When running the installation, skip updating the security - by deselecting the checkbox on the security screen. - - 4. Complete the installation, and then start the server - again. You should be able to login with your existing - user and password credentials. - - * You can only upgrade the version and release using the MSI - installer. For example, you can upgrade an open source - installation with an open source installer. You cannot upgrade - an open source installation using the enterprise installer. - - See Section 2.5.7, "Upgrading MySQL on Windows." - -2.5.3.2. Installing MySQL Automatically using MSI - - The Microsoft Installer (MSI) supports a both a quiet and a - passive mode that can be used to install MySQL automatically - without requireing intervention. You can use this either in - scripts to automatically install MySQL or through a terminal - connection such as Telnet where you do not have access to the - standard Windows user interface. The MSI packages can also be used - in combination with Microsoft's Group Policy system (part of - Windows Server 2003 and Windows Server 2008) to install MySQL - across multiple machines. - - To install MySQL from one of the MSI packages automatically from - the command line (or within a script), you need to use the - msiexec.exe tool. For example, to perform a quiet installation - (which shows no dialog boxes or progress): -shell> msiexec /i /quiet mysql-5.1.39.msi - - The /i indicates that you want to perform an installation. The - /quiet option indicates that you want no interactive elements. - - To provide a dialog box showing the progress during installation, - and the dialog boxes providing information on the installation and - registration of MySQL, use /passive mode instead of /quiet: -shell> msiexec /i /passive mysql-5.1.39.msi - - Regardless of the mode of the installation, installing the package - in this manner performs a 'Typical' installation, and installs the - default components into the standard location. - - You can also use this method to uninstall MySQL by using the - /uninstall or /x options: -shell> msiexec /x /quiet mysql-5.1.39.msi - - To install MySQL and configure a MySQL instance from the command - line, see Section 2.5.4.13, "Creating an Instance from the Command - Line." - - For information on using MSI packages to install software - automatically using Group Policy, see How to use Group Policy to - remotely install software in Windows Server 2003 - (http://support.microsoft.com/kb/816102). - -2.5.3.3. Removing MySQL Installed from the MSI Package - - To uninstall a MySQL where you have used the MSI packages, you - must use the Add/Remove Programs tool within Control Panel. To do - this: - - 1. Right click on the start menu and choose Control Panel. - - 2. If the Control Panel is set to category mode (you will see - Pick a category at the top of the Control Panel window), - double click on Add or Remove Programs. If the Control is set - to classic mode, doubgle click on the Add or Remove Programs - icon. - - 3. Find MySQL in the list of installed software. MySQL Server is - installed against major version numbers (MySQL 5.0, MySQL 5.1, - etc.). Select the version that you want to remove and click - Remove. - - 4. You will be prompted to confirm the removal. Click Yes to - remove MySQL. - - When MySQL is removed using this method, only the installed - components are removed. Any database information (including the - tables and data), import or export files, log files, and binary - logs produced during execution are kept in their configured - location. - -2.5.4. MySQL Server Instance Config Wizard - - The MySQL Server Instance Config Wizard helps automate the process - of configuring your server. It creates a custom MySQL - configuration file (my.ini or my.cnf) by asking you a series of - questions and then applying your responses to a template to - generate the configuration file that is tuned to your - installation. - - The complete and essential MSI installation packages include the - MySQL Server Instance Config Wizard in the MySQL 5.1 server. The - MySQL Server Instance Config Wizard is only available for Windows. - - The workflow sequence for using the MySQL Server Instance Config - Wizard is shown in the figure below: - - Figure 2.4. MySQL Server Instance Config Wizard Workflow - MySQL Server Instance Config Wizard Workflow - -2.5.4.1. Starting the MySQL Server Instance Config Wizard - - The MySQL Server Instance Config Wizard is normally started as - part of the installation process. You should only need to run the - MySQL Server Instance Config Wizard again when you need to change - the configuration parameters of your server. - - If you chose not to open a port prior to installing MySQL on - Windows Vista, you can choose to use the MySQL Server Instance - Config Wizard after installation. However, you must open a port in - the Windows Firewall. To do this see the instructions given in - Section 2.5.3.1.1, "Downloading and Starting the MySQL - Installation Wizard." Rather than opening a port, you also have - the option of adding MySQL as a program that bypasses the Windows - Firewall. One or the other option is sufficient --- you need not - do both. Additionally, when running the MySQL Server Config Wizard - on Windows Vista ensure that you are logged in as a user with - administrative rights. - MySQL Server Instance Config Wizard - - You can launch the MySQL Config Wizard by clicking the MySQL - Server Instance Config Wizard entry in the MySQL section of the - Windows Start menu. - - Alternatively, you can navigate to the bin directory of your MySQL - installation and launch the MySQLInstanceConfig.exe file directly. - - The MySQL Server Instance Config Wizard places the my.ini file in - the installation directory for the MySQL server. This helps - associate configuration files with particular server instances. - - To ensure that the MySQL server knows where to look for the my.ini - file, an argument similar to this is passed to the MySQL server as - part of the service installation: ---defaults-file="C:\Program Files\MySQL\MySQL Server 5.1\my.ini" - - Here, C:\Program Files\MySQL\MySQL Server 5.1 is replaced with the - installation path to the MySQL Server. The --defaults-file option - instructs the MySQL server to read the specified file for - configuration options when it starts. - - Apart from making changes to the my.ini file by running the MySQL - Server Instance Config Wizard again, you can modify it by opening - it with a text editor and making any necessary changes. You can - also modify the server configuration with the - http://www.mysql.com/products/administrator/ utility. For more - information about server configuration, see Section 5.1.2, "Server - Command Options." - - MySQL clients and utilities such as the mysql and mysqldump - command-line clients are not able to locate the my.ini file - located in the server installation directory. To configure the - client and utility applications, create a new my.ini file in the - Windows installation directory (for example, C:\WINDOWS). - - Under Windows Server 2003, Windows Server 2000, Windows XP, and - Windows Vista MySQL Server Instance Config Wizard will configure - MySQL to work as a Windows service. To start and stop MySQL you - use the Services application that is supplied as part of the - Windows Administrator Tools. - -2.5.4.2. Choosing a Maintenance Option - - If the MySQL Server Instance Config Wizard detects an existing - configuration file, you have the option of either reconfiguring - your existing server, or removing the server instance by deleting - the configuration file and stopping and removing the MySQL - service. - - To reconfigure an existing server, choose the Re-configure - Instance option and click the Next button. Any existing - configuration file is not overwritten, but renamed (within the - same directory) using a timestamp (Windows) or sequential number - (Linux). To remove the existing server instance, choose the Remove - Instance option and click the Next button. - - If you choose the Remove Instance option, you advance to a - confirmation window. Click the Execute button. The MySQL Server - Config Wizard stops and removes the MySQL service, and then - deletes the configuration file. The server installation and its - data folder are not removed. - - If you choose the Re-configure Instance option, you advance to the - Configuration Type dialog where you can choose the type of - installation that you wish to configure. - -2.5.4.3. Choosing a Configuration Type - - When you start the MySQL Server Instance Config Wizard for a new - MySQL installation, or choose the Re-configure Instance option for - an existing installation, you advance to the Configuration Type - dialog. - MySQL Server Instance Config Wizard: Configuration Type - - There are two configuration types available: Detailed - Configuration and Standard Configuration. The Standard - Configuration option is intended for new users who want to get - started with MySQL quickly without having to make many decisions - about server configuration. The Detailed Configuration option is - intended for advanced users who want more fine-grained control - over server configuration. - - If you are new to MySQL and need a server configured as a - single-user developer machine, the Standard Configuration should - suit your needs. Choosing the Standard Configuration option causes - the MySQL Config Wizard to set all configuration options - automatically with the exception of Service Options and Security - Options. - - The Standard Configuration sets options that may be incompatible - with systems where there are existing MySQL installations. If you - have an existing MySQL installation on your system in addition to - the installation you wish to configure, the Detailed Configuration - option is recommended. - - To complete the Standard Configuration, please refer to the - sections on Service Options and Security Options in Section - 2.5.4.10, "The Service Options Dialog," and Section 2.5.4.11, "The - Security Options Dialog," respectively. - -2.5.4.4. The Server Type Dialog - - There are three different server types available to choose from. - The server type that you choose affects the decisions that the - MySQL Server Instance Config Wizard makes with regard to memory, - disk, and processor usage. - MySQL Server Instance Config Wizard: Server Type - - * Developer Machine: Choose this option for a typical desktop - workstation where MySQL is intended only for personal use. It - is assumed that many other desktop applications are running. - The MySQL server is configured to use minimal system - resources. - - * Server Machine: Choose this option for a server machine where - the MySQL server is running alongside other server - applications such as FTP, email, and Web servers. The MySQL - server is configured to use a moderate portion of the system - resources. - - * Dedicated MySQL Server Machine: Choose this option for a - server machine that is intended to run only the MySQL server. - It is assumed that no other applications are running. The - MySQL server is configured to use all available system - resources. - -Note - - By selecting one of the preconfigured configurations, the values - and settings of various options in your my.cnf or my.ini will be - altered accordingly. The default values and options as described - in the reference manual may therefore be different to the options - and values that were created during the execution of the Config - Wizard. - -2.5.4.5. The Database Usage Dialog - - The Database Usage dialog allows you to indicate the storage - engines that you expect to use when creating MySQL tables. The - option you choose determines whether the InnoDB storage engine is - available and what percentage of the server resources are - available to InnoDB. - MySQL Server Instance Config Wizard: Usage Dialog - - * Multifunctional Database: This option enables both the InnoDB - and MyISAM storage engines and divides resources evenly - between the two. This option is recommended for users who use - both storage engines on a regular basis. - - * Transactional Database Only: This option enables both the - InnoDB and MyISAM storage engines, but dedicates most server - resources to the InnoDB storage engine. This option is - recommended for users who use InnoDB almost exclusively and - make only minimal use of MyISAM. - - * Non-Transactional Database Only: This option disables the - InnoDB storage engine completely and dedicates all server - resources to the MyISAM storage engine. This option is - recommended for users who do not use InnoDB. - - The Config Wizard uses a template to generate the server - configuration file. The Database Usage dialog sets one of the - following option strings: -Multifunctional Database: MIXED -Transactional Database Only: INNODB -Non-Transactional Database Only: MYISAM - - When these options are processed through the default template - (my-template.ini) the result is: -Multifunctional Database: -default-storage-engine=InnoDB -_myisam_pct=50 - -Transactional Database Only: -default-storage-engine=InnoDB -_myisam_pct=5 - -Non-Transactional Database Only: -default-storage-engine=MyISAM -_myisam_pct=100 -skip-innodb - - The _myisam_pct value is used to calculate the percentage of - resources dedicated to MyISAM. The remaining resources are - allocated to InnoDB. - -2.5.4.6. The InnoDB Tablespace Dialog - - Some users may want to locate the InnoDB tablespace files in a - different location than the MySQL server data directory. Placing - the tablespace files in a separate location can be desirable if - your system has a higher capacity or higher performance storage - device available, such as a RAID storage system. - MySQL Server Instance Config Wizard: InnoDB Data Tablespace - - To change the default location for the InnoDB tablespace files, - choose a new drive from the drop-down list of drive letters and - choose a new path from the drop-down list of paths. To create a - custom path, click the ... button. - - If you are modifying the configuration of an existing server, you - must click the Modify button before you change the path. In this - situation you must move the existing tablespace files to the new - location manually before starting the server. - -2.5.4.7. The Concurrent Connections Dialog - - To prevent the server from running out of resources, it is - important to limit the number of concurrent connections to the - MySQL server that can be established. The Concurrent Connections - dialog allows you to choose the expected usage of your server, and - sets the limit for concurrent connections accordingly. It is also - possible to set the concurrent connection limit manually. - MySQL Server Instance Config Wizard: Connections - - * Decision Support (DSS)/OLAP: Choose this option if your server - does not require a large number of concurrent connections. The - maximum number of connections is set at 100, with an average - of 20 concurrent connections assumed. - - * Online Transaction Processing (OLTP): Choose this option if - your server requires a large number of concurrent connections. - The maximum number of connections is set at 500. - - * Manual Setting: Choose this option to set the maximum number - of concurrent connections to the server manually. Choose the - number of concurrent connections from the drop-down box - provided, or enter the maximum number of connections into the - drop-down box if the number you desire is not listed. - -2.5.4.8. The Networking and Strict Mode Options Dialog - - Use the Networking Options dialog to enable or disable TCP/IP - networking and to configure the port number that is used to - connect to the MySQL server. - MySQL Server Instance Config Wizard: Network Configuration - - TCP/IP networking is enabled by default. To disable TCP/IP - networking, uncheck the box next to the Enable TCP/IP Networking - option. - - Port 3306 is used by default. To change the port used to access - MySQL, choose a new port number from the drop-down box or type a - new port number directly into the drop-down box. If the port - number you choose is in use, you are prompted to confirm your - choice of port number. - - Set the Server SQL Mode to either enable or disable strict mode. - Enabling strict mode (default) makes MySQL behave more like other - database management systems. If you run applications that rely on - MySQL's old "forgiving" behavior, make sure to either adapt those - applications or to disable strict mode. For more information about - strict mode, see Section 5.1.8, "Server SQL Modes." - -2.5.4.9. The Character Set Dialog - - The MySQL server supports multiple character sets and it is - possible to set a default server character set that is applied to - all tables, columns, and databases unless overridden. Use the - Character Set dialog to change the default character set of the - MySQL server. - MySQL Server Instance Config Wizard: Character Set - - * Standard Character Set: Choose this option if you want to use - latin1 as the default server character set. latin1 is used for - English and many Western European languages. - - * Best Support For Multilingualism: Choose this option if you - want to use utf8 as the default server character set. This is - a Unicode character set that can store characters from many - different languages. - - * Manual Selected Default Character Set / Collation: Choose this - option if you want to pick the server's default character set - manually. Choose the desired character set from the provided - drop-down list. - -2.5.4.10. The Service Options Dialog - - On Windows platforms, the MySQL server can be installed as a - Windows service. When installed this way, the MySQL server can be - started automatically during system startup, and even restarted - automatically by Windows in the event of a service failure. - - The MySQL Server Instance Config Wizard installs the MySQL server - as a service by default, using the service name MySQL. If you do - not wish to install the service, uncheck the box next to the - Install As Windows Service option. You can change the service name - by picking a new service name from the drop-down box provided or - by entering a new service name into the drop-down box. - -Note - - Service names can include any legal character except forward (/) - or backward (\) slashes, and must be less than 256 characters - long. - -Warning - - If you are installing multiple versions of MySQL onto the same - machine, you must choose a different service name for each version - that you install. If you do not choose a different service for - each installed version then the service manager information will - be inconsistent and this will cause problems when you try to - uninstall a previous version. - - If you have already installed multiple versions using the same - service name, you must manually edit the contents of the - HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services parameters - within the Windows registry to update the association of the - service name with the correct server version. - - Typically, when installing multiple versions you create a service - name based on the version information. For example, you might - install MySQL 5.x as mysql5, or specific versions such as MySQL - 5.1.30 as mysql50130. - - To install the MySQL server as a service but not have it started - automatically at startup, uncheck the box next to the Launch the - MySQL Server Automatically option. - -2.5.4.11. The Security Options Dialog - - The content of the security options portion of the MySQL Server - Instance Configuration Wizard will depend on whether this is a new - installation, or modifying an existing installation. - - * Setting the root password for a new installation - It is strongly recommended that you set a root password for - your MySQL server, and the MySQL Server Instance Config Wizard - requires by default that you do so. If you do not wish to set - a root password, uncheck the box next to the Modify Security - Settings option. - MySQL Server Instance Config Wizard: Security - - * To set the root password, enter the desired password into both - the New root password and Confirm boxes. - Setting the root password for an existing installation - If you are modifying the configuration of an existing - configuration, or you are installing an upgrade and the MySQL - Server Instance Configuration Wizard has detected an existing - MySQL system, then you must enter the existing password for - root before changing the configuration information. - MySQL Server Instance Config Wizard: Security (Existing - Installation) - If you want to change the current root password, enter the - desired new password into both the New root password and - Confirm boxes. - - To allow root logins from across the network, check the box next - to the Enable root access from remote machines option. This - decreases the security of your root account. - - To create an anonymous user account, check the box next to the - Create An Anonymous Account option. Creating an anonymous account - can decrease server security and cause login and permission - difficulties. For this reason, it is not recommended. - -2.5.4.12. The Confirmation Dialog - - The final dialog in the MySQL Server Instance Config Wizard is the - Confirmation Dialog. To start the configuration process, click the - Execute button. To return to a previous dialog, click the Back - button. To exit the MySQL Server Instance Config Wizard without - configuring the server, click the Cancel button. - MySQL Server Instance Config Wizard: Confirmation - - After you click the Execute button, the MySQL Server Instance - Config Wizard performs a series of tasks and displays the progress - onscreen as the tasks are performed. - - The MySQL Server Instance Config Wizard first determines - configuration file options based on your choices using a template - prepared by MySQL developers and engineers. This template is named - my-template.ini and is located in your server installation - directory. - - The MySQL Config Wizard then writes these options to the - corresponding configuration file. - - If you chose to create a service for the MySQL server, the MySQL - Server Instance Config Wizard creates and starts the service. If - you are reconfiguring an existing service, the MySQL Server - Instance Config Wizard restarts the service to apply your - configuration changes. - - If you chose to set a root password, the MySQL Config Wizard - connects to the server, sets your new root password, and applies - any other security settings you may have selected. - - After the MySQL Server Instance Config Wizard has completed its - tasks, it displays a summary. Click the Finish button to exit the - MySQL Server Config Wizard. - -2.5.4.13. Creating an Instance from the Command Line - - In addition to using the GUI interface to the MySQL Server - Instance Config Wizard, you can also create instances - automatically from the command line. - - To use the MySQL Server Instance Config Wizard on the command - line, you need to use the MySQLInstanceConfig.exe command that is - installed with MySQL in the bin directory within the installation - directory. MySQLInstanceConfig.exe takes a number of command-line - arguments the set the properties that would normally be selected - through the GUI interface, and then creates a new configuration - file (my.ini) by combining these selections with a template - configuration file to produce the working configuration file. - - The main command line options are provided in the table below. - Some of the options are required, while some options are optional. - - Table 2.4. MySQL Server Instance Config Wizard Command Line - Options - Option Description - Required Parameters - -nPRODUCTNAME The name of the instance when installed - -pPATH Path of the base directory for installation. This is - equivalent to the directory when using the basedir configuration - parameter - -vVERSION The version tag to use for this installation - Action to Perform - -i Install an instance - -r Remove an instance - -s Stop an existing instance - -q Perform the operation quietly - -lFILENAME Sae the installation progress in a logfile - Config File to Use - -tFILENAME Path to the template config file that will be used to - generate the installed configuration file - -cFILENAME Path to a config file to be generated - - The -t and -c options work together to set the configuration - parameters for a new instance. The -t option specifies the - template configuration file to use as the basic configuration, - which are then merged with the configuration parameters generated - by the MySQL Server Instance Config Wizard into the configuration - file specified by the -c option. - - A sample template file, my-template.ini is provided in the - toplevel MySQL installation directory. The file contains elements - are replaced automatically by the MySQL Server Instance Config - Wizard during configuration. - - If you specify a configuration file that already exists, the - existing configuration file will be saved in the file with the - original, with the date and time added. For example, the mysql.ini - will be copied to mysql 2009-10-27 1646.ini.bak. - - The parameters that you can specify on the command line are listed - in the table below. - - Table 2.5. MySQL Server Instance Config Wizard Parameters - Parameter Description - ServiceName=$ Specify the name of the service to be created - AddBinToPath={yes | no} Specifies whether to add the binary - directory of MySQL to the standard PATH environment variable - ServerType={DEVELOPMENT | SERVER | DEDICATED} Specify the server - type. For more information, see Section 2.5.4.4, "The Server Type - Dialog" - DatabaseType={MIXED | INNODB | MYISAM} Specify the default - database type. For more information, see Section 2.5.4.5, "The - Database Usage Dialog" - ConnectionUsage={DSS | OLTP} Specify the type of connection - support, this automates the setting for the number of concurrent - connections (see the ConnectionCount parameter). For more - information, see Section 2.5.4.7, "The Concurrent Connections - Dialog" - ConnectionCount=# Specify the number of concurrent connections to - support. For more information, see Section 2.5.4.4, "The Server - Type Dialog" - SkipNetworking={yes | no} Specify whether network support should - be supported. Specifying yes disables network access altogether - Port=# Specify the network port number to use for network - connections. For more information, see Section 2.5.4.8, "The - Networking and Strict Mode Options Dialog" - StrictMode={yes | no} Specify whether to use the strict SQL mode. - For more information, see Section 2.5.4.8, "The Networking and - Strict Mode Options Dialog" - Charset=$ Specify the default character set. For more information, - see Section 2.5.4.9, "The Character Set Dialog" - RootPassword=$ Specify the root password - RootCurrentPassword=$ Specify the current root password then - stopping and/or reconfiguring an existing service - -Note - - When specifying options on the command line, you can enclose the - entire command-line option and the value you are specifying using - double quotes. This enables you to use spaces in the options. For - example, "-cC:\mysql.ini". - - The following command installs a MySQL Server 5.1 instance from - the directory C:\Program Files\MySQL\MySQL Server 5.1 using the - service name MySQL51 and setting the root password to 1234. -shell> MySQLInstanceConfig.exe -i -q "-lC:\mysql_install_log.txt" » - "-nMySQL Server 5.1" "-pC:\Program Files\MySQL\MySQL Server 5.1" - -v5.1.39 » - "-tmy-template.ini" "-cC:\mytest.ini" ServerType=DEVELOPMENT Datab -aseType=MIXED » - ConnectionUsage=DSS Port=3311 ServiceName=MySQL51 RootPassword=123 -4 - - In the above example, a log file will be generated in - mysql_install_log.txt containing the information about the - instance creation process. The log file generated by the above - example is shown below: -Welcome to the MySQL Server Instance Configuration Wizard 1.0.16.0 -Date: 2009-10-27 17:07:21 - -Installing service ... - -Product Name: MySQL Server 5.1 -Version: 5.1.39 -Installation Path: C:\Program Files\MySQL\MySQL Server 5.1\ - -Creating configuration file C:\mytest.ini using template my-template. -ini. -Options: -DEVELOPMENT -MIXED -DSS -STRICTMODE - -Variables: -port: 3311 -default-character-set: latin1 -basedir: "C:/Program Files/MySQL/MySQL Server 5.1/" -datadir: "C:/Program Files/MySQL/MySQL Server 5.1/Data/" - - -Creating Windows service entry. -Service name: "MySQL51" -Parameters: "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" -- -defaults-file="C:\mytest.ini" MySQL51. -Windows service MySQL51 installed. - - When using the command-line, the return values in the following - table indicate an error performing the specified option. - - Table 2.6. Return Value from MySQL Server Instance Config Wizard - Value Description - 2 Configuration template file cannot be found - 3 The Windows service entry cannot be created - 4 Could not connect to the Service Control Manager - 5 The MySQL service cannot be started - 6 The MySQL service cannot be stopped - 7 The security settings cannot be applied - 8 The configuration file cannot be written - 9 The Windows service entry cannot be removed - - You can perform an installation of MySQL automatically using the - MSI packe. For more information, see Section 2.5.3.2, "Installing - MySQL Automatically using MSI." - -2.5.5. Installing MySQL from a noinstall Zip Archive - - Users who are installing from the noinstall package can use the - instructions in this section to manually install MySQL. The - process for installing MySQL from a Zip archive is as follows: - - 1. Extract the archive to the desired install directory - - 2. Create an option file - - 3. Choose a MySQL server type - - 4. Start the MySQL server - - 5. Secure the default user accounts - - This process is described in the sections that follow. - -2.5.5.1. Extracting the Install Archive - - To install MySQL manually, do the following: - - 1. If you are upgrading from a previous version please refer to - Section 2.5.7, "Upgrading MySQL on Windows," before beginning - the upgrade process. - - 2. Make sure that you are logged in as a user with administrator - privileges. - - 3. Choose an installation location. Traditionally, the MySQL - server is installed in C:\mysql. The MySQL Installation Wizard - installs MySQL under C:\Program Files\MySQL. If you do not - install MySQL at C:\mysql, you must specify the path to the - install directory during startup or in an option file. See - Section 2.5.5.2, "Creating an Option File." - - 4. Extract the install archive to the chosen installation - location using your preferred Zip archive tool. Some tools may - extract the archive to a folder within your chosen - installation location. If this occurs, you can move the - contents of the subfolder into the chosen installation - location. - -2.5.5.2. Creating an Option File - - If you need to specify startup options when you run the server, - you can indicate them on the command line or place them in an - option file. For options that are used every time the server - starts, you may find it most convenient to use an option file to - specify your MySQL configuration. This is particularly true under - the following circumstances: - - * The installation or data directory locations are different - from the default locations (C:\Program Files\MySQL\MySQL - Server 5.1 and C:\Program Files\MySQL\MySQL Server 5.1\data). - - * You need to tune the server settings, such as memory, cache, - or InnoDB configuration information. - - When the MySQL server starts on Windows, it looks for option files - in several locations, such as the Windows directory, C:\, and the - MySQL installation directory (for the full list of locations, see - Section 4.2.3.3, "Using Option Files"). The Windows directory - typically is named something like C:\WINDOWS. You can determine - its exact location from the value of the WINDIR environment - variable using the following command: -C:\> echo %WINDIR% - - MySQL looks for options in each location first in the my.ini file, - and then in the my.cnf file. However, to avoid confusion, it is - best if you use only one file. If your PC uses a boot loader where - C: is not the boot drive, your only option is to use the my.ini - file. Whichever option file you use, it must be a plain text file. - - You can also make use of the example option files included with - your MySQL distribution; see Section 4.2.3.3.2, "Preconfigured - Option Files." - - An option file can be created and modified with any text editor, - such as Notepad. For example, if MySQL is installed in E:\mysql - and the data directory is in E:\mydata\data, you can create an - option file containing a [mysqld] section to specify values for - the basedir and datadir options: -[mysqld] -# set basedir to your installation path -basedir=E:/mysql -# set datadir to the location of your data directory -datadir=E:/mydata/data - - Note that Windows path names are specified in option files using - (forward) slashes rather than backslashes. If you do use - backslashes, double them: -[mysqld] -# set basedir to your installation path -basedir=E:\\mysql -# set datadir to the location of your data directory -datadir=E:\\mydata\\data - - The rules for use of backslash in option file values are given in - Section 4.2.3.3, "Using Option Files." - - MySQL Enterprise For expert advice on the start-up options - appropriate to your circumstances, subscribe to the MySQL - Enterprise Monitor. For more information, see - http://www.mysql.com/products/enterprise/advisors.html. - - In MySQL 5.1.23 and earlier, the MySQL installer places the data - directory directly under the directory where you install MySQL. On - MySQL 5.1.24 and later, the data directory is located within the - AppData directory for the user running MySQL. - - If you would like to use a data directory in a different location, - you should copy the entire contents of the data directory to the - new location. For example, if you want to use E:\mydata as the - data directory instead, you must do two things: - - 1. Move the entire data directory and all of its contents from - the default location (for example C:\Program Files\MySQL\MySQL - Server 5.1\data) to E:\mydata. - - 2. Use a --datadir option to specify the new data directory - location each time you start the server. - -2.5.5.3. Selecting a MySQL Server Type - - The following table shows the available servers for Windows in - MySQL 5.1.20 and earlier. - Binary Description - mysqld-nt Optimized binary with named-pipe support - mysqld Optimized binary without named-pipe support - mysqld-debug Like mysqld-nt, but compiled with full debugging and - automatic memory allocation checking - - The following table shows the available servers for Windows in - MySQL 5.1.21 and later. - Binary Description - mysqld Optimized binary with named-pipe support - mysqld-debug Like mysqld, but compiled with full debugging and - automatic memory allocation checking - - All of the preceding binaries are optimized for modern Intel - processors, but should work on any Intel i386-class or higher - processor. - - Each of the servers in a distribution support the same set of - storage engines. The SHOW ENGINES statement displays which engines - a given server supports. - - All Windows MySQL 5.1 servers have support for symbolic linking of - database directories. - - MySQL supports TCP/IP on all Windows platforms. MySQL servers on - Windows support named pipes as indicated in the following list. - However, the default is to use TCP/IP regardless of platform. - (Named pipes are slower than TCP/IP in many Windows - configurations.) - - Use of named pipes is subject to these conditions: - - * Named pipes are enabled only if you start the server with the - --enable-named-pipe option. It is necessary to use this option - explicitly because some users have experienced problems with - shutting down the MySQL server when named pipes were used. - - * For MySQL 5.1.20 and earlier, named-pipe connections are - allowed only by the mysqld-nt and mysqld-debug servers. For - MySQL 5.1.21 and later, the mysqld and mysqld-debug servers - both contain support for named-pipe connections. - -Note - - Most of the examples in this manual use mysqld as the server name. - If you choose to use a different server, such as mysqld-nt or - mysqld-debug, make the appropriate substitutions in the commands - that are shown in the examples. - -2.5.5.4. Starting the Server for the First Time - - This section gives a general overview of starting the MySQL - server. The following sections provide more specific information - for starting the MySQL server from the command line or as a - Windows service. - - The information here applies primarily if you installed MySQL - using the Noinstall version, or if you wish to configure and test - MySQL manually rather than with the GUI tools. - - The examples in these sections assume that MySQL is installed - under the default location of C:\Program Files\MySQL\MySQL Server - 5.1. Adjust the path names shown in the examples if you have MySQL - installed in a different location. - - Clients have two options. They can use TCP/IP, or they can use a - named pipe if the server supports named-pipe connections. - - MySQL for Windows also supports shared-memory connections if the - server is started with the --shared-memory option. Clients can - connect through shared memory by using the --protocol=MEMORY - option. - - For information about which server binary to run, see Section - 2.5.5.3, "Selecting a MySQL Server Type." - - Testing is best done from a command prompt in a console window (or - "DOS window"). In this way you can have the server display status - messages in the window where they are easy to see. If something is - wrong with your configuration, these messages make it easier for - you to identify and fix any problems. - - To start the server, enter this command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" --console - - For a server that includes InnoDB support, you should see the - messages similar to those following as it starts (the path names - and sizes may differ): -InnoDB: The first specified datafile c:\ibdata\ibdata1 did not exist: -InnoDB: a new database to be created! -InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200 -InnoDB: Database physically writes the file full: wait... -InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be creat -ed -InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280 -InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be creat -ed -InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280 -InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be creat -ed -InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280 -InnoDB: Doublewrite buffer not found: creating new -InnoDB: Doublewrite buffer created -InnoDB: creating foreign key constraint system tables -InnoDB: foreign key constraint system tables created -011024 10:58:25 InnoDB: Started - - When the server finishes its startup sequence, you should see - something like this, which indicates that the server is ready to - service client connections: -mysqld: ready for connections -Version: '5.1.46' socket: '' port: 3306 - - The server continues to write to the console any further - diagnostic output it produces. You can open a new console window - in which to run client programs. - - If you omit the --console option, the server writes diagnostic - output to the error log in the data directory (C:\Program - Files\MySQL\MySQL Server 5.1\data by default). The error log is - the file with the .err extension. - -Note - - The accounts that are listed in the MySQL grant tables initially - have no passwords. After starting the server, you should set up - passwords for them using the instructions in Section 2.13, - "Post-Installation Setup and Testing." - -2.5.5.5. Starting MySQL from the Windows Command Line - - The MySQL server can be started manually from the command line. - This can be done on any version of Windows. - - To start the mysqld server from the command line, you should start - a console window (or "DOS window") and enter this command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" - - The path to mysqld may vary depending on the install location of - MySQL on your system. - - You can stop the MySQL server by executing this command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqladmin" -u root - shutdown - -Note - - If the MySQL root user account has a password, you need to invoke - mysqladmin with the -p option and supply the password when - prompted. - - This command invokes the MySQL administrative utility mysqladmin - to connect to the server and tell it to shut down. The command - connects as the MySQL root user, which is the default - administrative account in the MySQL grant system. Note that users - in the MySQL grant system are wholly independent from any login - users under Windows. - - If mysqld doesn't start, check the error log to see whether the - server wrote any messages there to indicate the cause of the - problem. The error log is located in the C:\Program - Files\MySQL\MySQL Server 5.1\data directory. It is the file with a - suffix of .err. You can also try to start the server as mysqld - --console; in this case, you may get some useful information on - the screen that may help solve the problem. - - The last option is to start mysqld with the --standalone and - --debug-dbug options. In this case, mysqld writes a log file - C:\mysqld.trace that should contain the reason why mysqld doesn't - start. See MySQL Internals: Porting - (http://forge.mysql.com/wiki/MySQL_Internals_Porting). - - Use mysqld --verbose --help to display all the options that mysqld - supports. - -2.5.5.6. Starting MySQL as a Windows Service - - On Windows, the recommended way to run MySQL is to install it as a - Windows service, whereby MySQL starts and stops automatically when - Windows starts and stops. A MySQL server installed as a service - can also be controlled from the command line using NET commands, - or with the graphical Services utility. Generally, to install - MySQL as a Windows service you should be logged in using an - account that has administrator rights. - - The Services utility (the Windows Service Control Manager) can be - found in the Windows Control Panel (under Administrative Tools on - Windows 2000, XP, Vista and Server 2003). To avoid conflicts, it - is advisable to close the Services utility while performing server - installation or removal operations from the command line. - - Before installing MySQL as a Windows service, you should first - stop the current server if it is running by using the following - command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqladmin" - -u root shutdown - -Note - - If the MySQL root user account has a password, you need to invoke - mysqladmin with the -p option and supply the password when - prompted. - - This command invokes the MySQL administrative utility mysqladmin - to connect to the server and tell it to shut down. The command - connects as the MySQL root user, which is the default - administrative account in the MySQL grant system. Note that users - in the MySQL grant system are wholly independent from any login - users under Windows. - - Install the server as a service using this command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" --install - - The service-installation command does not start the server. - Instructions for that are given later in this section. - - To make it easier to invoke MySQL programs, you can add the path - name of the MySQL bin directory to your Windows system PATH - environment variable: - - * On the Windows desktop, right-click on the My Computer icon, - and select Properties. - - * Next select the Advanced tab from the System Properties menu - that appears, and click the Environment Variables button. - - * Under System Variables, select Path, and then click the Edit - button. The Edit System Variable dialogue should appear. - - * Place your cursor at the end of the text appearing in the - space marked Variable Value. (Use the End key to ensure that - your cursor is positioned at the very end of the text in this - space.) Then enter the complete path name of your MySQL bin - directory (for example, C:\Program Files\MySQL\MySQL Server - 5.1\bin), Note that there should be a semicolon separating - this path from any values present in this field. Dismiss this - dialogue, and each dialogue in turn, by clicking OK until all - of the dialogues that were opened have been dismissed. You - should now be able to invoke any MySQL executable program by - typing its name at the DOS prompt from any directory on the - system, without having to supply the path. This includes the - servers, the mysql client, and all MySQL command-line - utilities such as mysqladmin and mysqldump. - You should not add the MySQL bin directory to your Windows - PATH if you are running multiple MySQL servers on the same - machine. - -Warning - - You must exercise great care when editing your system PATH by - hand; accidental deletion or modification of any portion of the - existing PATH value can leave you with a malfunctioning or even - unusable system. - - The following additional arguments can be used in MySQL 5.1 when - installing the service: - - * You can specify a service name immediately following the - --install option. The default service name is MySQL. - - * If a service name is given, it can be followed by a single - option. By convention, this should be - --defaults-file=file_name to specify the name of an option - file from which the server should read options when it starts. - The use of a single option other than --defaults-file is - possible but discouraged. --defaults-file is more flexible - because it enables you to specify multiple startup options for - the server by placing them in the named option file. - - * You can also specify a --local-service option following the - service name. This causes the server to run using the - LocalService Windows account that has limited system - privileges. This account is available only for Windows XP or - newer. If both --defaults-file and --local-service are given - following the service name, they can be in any order. - - For a MySQL server that is installed as a Windows service, the - following rules determine the service name and option files that - the server uses: - - * If the service-installation command specifies no service name - or the default service name (MySQL) following the --install - option, the server uses the a service name of MySQL and reads - options from the [mysqld] group in the standard option files. - - * If the service-installation command specifies a service name - other than MySQL following the --install option, the server - uses that service name. It reads options from the [mysqld] - group and the group that has the same name as the service in - the standard option files. This allows you to use the [mysqld] - group for options that should be used by all MySQL services, - and an option group with the service name for use by the - server installed with that service name. - - * If the service-installation command specifies a - --defaults-file option after the service name, the server - reads options only from the [mysqld] group of the named file - and ignores the standard option files. - - As a more complex example, consider the following command: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" - --install MySQL --defaults-file=C:\my-opts.cnf - - Here, the default service name (MySQL) is given after the - --install option. If no --defaults-file option had been given, - this command would have the effect of causing the server to read - the [mysqld] group from the standard option files. However, - because the --defaults-file option is present, the server reads - options from the [mysqld] option group, and only from the named - file. - - You can also specify options as Start parameters in the Windows - Services utility before you start the MySQL service. - - Once a MySQL server has been installed as a service, Windows - starts the service automatically whenever Windows starts. The - service also can be started immediately from the Services utility, - or by using a NET START MySQL command. The NET command is not case - sensitive. - - When run as a service, mysqld has no access to a console window, - so no messages can be seen there. If mysqld does not start, check - the error log to see whether the server wrote any messages there - to indicate the cause of the problem. The error log is located in - the MySQL data directory (for example, C:\Program - Files\MySQL\MySQL Server 5.1\data). It is the file with a suffix - of .err. - - When a MySQL server has been installed as a service, and the - service is running, Windows stops the service automatically when - Windows shuts down. The server also can be stopped manually by - using the Services utility, the NET STOP MySQL command, or the - mysqladmin shutdown command. - - You also have the choice of installing the server as a manual - service if you do not wish for the service to be started - automatically during the boot process. To do this, use the - --install-manual option rather than the --install option: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" --install-m -anual - - To remove a server that is installed as a service, first stop it - if it is running by executing NET STOP MySQL. Then use the - --remove option to remove it: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld" --remove - - If mysqld is not running as a service, you can start it from the - command line. For instructions, see Section 2.5.5.5, "Starting - MySQL from the Windows Command Line." - - Please see Section 2.5.6, "Troubleshooting a MySQL Installation - Under Windows," if you encounter difficulties during installation. - -2.5.5.7. Testing The MySQL Installation - - You can test whether the MySQL server is working by executing any - of the following commands: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqlshow" -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqlshow" -u root -mysql -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqladmin" version - status proc -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysql" test - -Note - - By default, mysqlshow will try to connect using the ODBC user. - This user is not created by default. You should specify a valid - user, or root with the right password to check the operation of - the server. - - If mysqld is slow to respond to TCP/IP connections from client - programs, there is probably a problem with your DNS. In this case, - start mysqld with the --skip-name-resolve option and use only - localhost and IP numbers in the Host column of the MySQL grant - tables. - - You can force a MySQL client to use a named-pipe connection rather - than TCP/IP by specifying the --pipe or --protocol=PIPE option, or - by specifying . (period) as the host name. Use the --socket option - to specify the name of the pipe if you do not want to use the - default pipe name. - - Note that if you have set a password for the root account, deleted - the anonymous account, or created a new user account, then you - must use the appropriate -u and -p options with the commands shown - above in order to connect with the MySQL Server. See Section - 4.2.2, "Connecting to the MySQL Server." - - For more information about mysqlshow, see Section 4.5.6, - "mysqlshow --- Display Database, Table, and Column Information." - -2.5.6. Troubleshooting a MySQL Installation Under Windows - - When installing and running MySQL for the first time, you may - encounter certain errors that prevent the MySQL server from - starting. The purpose of this section is to help you diagnose and - correct some of these errors. - - Your first resource when troubleshooting server issues is the - error log. The MySQL server uses the error log to record - information relevant to the error that prevents the server from - starting. The error log is located in the data directory specified - in your my.ini file. The default data directory location is - C:\Program Files\MySQL\MySQL Server 5.1\data. See Section 5.2.2, - "The Error Log." - - Another source of information regarding possible errors is the - console messages displayed when the MySQL service is starting. Use - the NET START MySQL command from the command line after installing - mysqld as a service to see any error messages regarding the - starting of the MySQL server as a service. See Section 2.5.5.6, - "Starting MySQL as a Windows Service." - - The following examples show other common error messages you may - encounter when installing MySQL and starting the server for the - first time: - - * If the MySQL server cannot find the mysql privileges database - or other critical files, you may see these messages: -System error 1067 has occurred. -Fatal error: Can't open privilege tables: Table 'mysql.host' doesn't -exist - These messages often occur when the MySQL base or data - directories are installed in different locations than the - default locations (C:\Program Files\MySQL\MySQL Server 5.1 and - C:\Program Files\MySQL\MySQL Server 5.1\data, respectively). - This situation may occur when MySQL is upgraded and installed - to a new location, but the configuration file is not updated - to reflect the new location. In addition, there may be old and - new configuration files that conflict. Be sure to delete or - rename any old configuration files when upgrading MySQL. - If you have installed MySQL to a directory other than - C:\Program Files\MySQL\MySQL Server 5.1, you need to ensure - that the MySQL server is aware of this through the use of a - configuration (my.ini) file. The my.ini file needs to be - located in your Windows directory, typically C:\WINDOWS. You - can determine its exact location from the value of the WINDIR - environment variable by issuing the following command from the - command prompt: -C:\> echo %WINDIR% - An option file can be created and modified with any text - editor, such as Notepad. For example, if MySQL is installed in - E:\mysql and the data directory is D:\MySQLdata, you can - create the option file and set up a [mysqld] section to - specify values for the basedir and datadir options: -[mysqld] -# set basedir to your installation path -basedir=E:/mysql -# set datadir to the location of your data directory -datadir=D:/MySQLdata - Note that Windows path names are specified in option files - using (forward) slashes rather than backslashes. If you do use - backslashes, double them: -[mysqld] -# set basedir to your installation path -basedir=C:\\Program Files\\MySQL\\MySQL Server 5.1 -# set datadir to the location of your data directory -datadir=D:\\MySQLdata - The rules for use of backslash in option file values are given - in Section 4.2.3.3, "Using Option Files." - If you change the datadir value in your MySQL configuration - file, you must move the contents of the existing MySQL data - directory before restarting the MySQL server. - See Section 2.5.5.2, "Creating an Option File." - - * If you reinstall or upgrade MySQL without first stopping and - removing the existing MySQL service and install MySQL using - the MySQL Config Wizard, you may see this error: -Error: Cannot create Windows service for MySql. Error: 0 - This occurs when the Config Wizard tries to install the - service and finds an existing service with the same name. - One solution to this problem is to choose a service name other - than mysql when using the configuration wizard. This allows - the new service to be installed correctly, but leaves the - outdated service in place. Although this is harmless, it is - best to remove old services that are no longer in use. - To permanently remove the old mysql service, execute the - following command as a user with administrative privileges, on - the command-line: -C:\> sc delete mysql -[SC] DeleteService SUCCESS - If the sc utility is not available for your version of - Windows, download the delsrv utility from - http://www.microsoft.com/windows2000/techinfo/reskit/tools/exi - sting/delsrv-o.asp and use the delsrv mysql syntax. - -2.5.7. Upgrading MySQL on Windows - - This section lists some of the steps you should take when - upgrading MySQL on Windows. - - 1. Review Section 2.4.1, "Upgrading MySQL," for additional - information on upgrading MySQL that is not specific to - Windows. - - 2. You should always back up your current MySQL installation - before performing an upgrade. See Section 6.2, "Database - Backup Methods." - - 3. Download the latest Windows distribution of MySQL from - http://dev.mysql.com/downloads/. - - 4. Before upgrading MySQL, you must stop the server. If the - server is installed as a service, stop the service with the - following command from the command prompt: -C:\> NET STOP MySQL - If you are not running the MySQL server as a service, use the - following command to stop it: -C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqladmin" -u root - shutdown - -Note - If the MySQL root user account has a password, you need to - invoke mysqladmin with the -p option and supply the password - when prompted. - - 5. When upgrading to MySQL 5.1 from a version previous to 4.1.5, - or when upgrading from a version of MySQL installed from a Zip - archive to a version of MySQL installed with the MySQL - Installation Wizard, you must manually remove the previous - installation and MySQL service (if the server is installed as - a service). - To remove the MySQL service, use the following command: -C:\> C:\mysql\bin\mysqld --remove - If you do not remove the existing service, the MySQL - Installation Wizard may fail to properly install the new MySQL - service. - - 6. When upgrading from MySQL 5.1.23 to MySQL 5.1.24, the change - in the default location of the data directory from a directory - within the MySQL installation to the AppData folder means that - you must manually copy the data files from your old - installation to the new location. - - 7. If you are using the MySQL Installation Wizard, start the - wizard as described in Section 2.5.3.1, "Using the MySQL - Installation Wizard." - - 8. If you are installing MySQL from a Zip archive, extract the - archive. You may either overwrite your existing MySQL - installation (usually located at C:\mysql), or install it into - a different directory, such as C:\mysql5. Overwriting the - existing installation is recommended. - - 9. If you were running MySQL as a Windows service and you had to - remove the service earlier in this procedure, reinstall the - service. (See Section 2.5.5.6, "Starting MySQL as a Windows - Service.") - 10. Restart the server. For example, use NET START MySQL if you - run MySQL as a service, or invoke mysqld directly otherwise. - 11. If you encounter errors, see Section 2.5.6, "Troubleshooting a - MySQL Installation Under Windows." - -2.5.8. Windows Post-Installation Procedures - - On Windows, the data directory and the grant tables do not have to - be created. MySQL Windows distributions include the grant tables - with a set of preinitialized accounts in the mysql database under - the data directory. It is unnecessary to run the mysql_install_db - script that is used on Unix. Regarding passwords, if you installed - MySQL using the Windows Installation Wizard, you may have already - assigned passwords to the accounts. (See Section 2.5.3.1, "Using - the MySQL Installation Wizard.") Otherwise, use the - password-assignment procedure given in Section 2.13.2, "Securing - the Initial MySQL Accounts." - - Before setting up passwords, you might want to try running some - client programs to make sure that you can connect to the server - and that it is operating properly. Make sure that the server is - running (see Section 2.5.5.4, "Starting the Server for the First - Time"), and then issue the following commands to verify that you - can retrieve information from the server. The output should be - similar to what is shown here: -C:\> C:\mysql\bin\mysqlshow -+--------------------+ -| Databases | -+--------------------+ -| information_schema | -| mysql | -| test | -+--------------------+ - -Note - - The above may not work if the correct user does not exist. If you - installed using the MSI packages and used the MySQL Server - Instance Config Wizard, then the root will haqve been created - automatically with the password you supplied. In this case, you - should use the -u and -p options where you will be prompted for - the password. - -Note - - The list of installed databases may vary, but will always include - the minimum of mysql and information_schema. In most cases, the - test database will also be installed automatically. - - If you specify the name of the database, then a list of the tables - within a given database will be displayed: -C:\> C:\mysql\bin\mysqlshow mysql -Database: mysql -+---------------------------+ -| Tables | -+---------------------------+ -| columns_priv | -| db | -| event | -| func | -| general_log | -| help_category | -| help_keyword | -| help_relation | -| help_topic | -| host | -| plugin | -| proc | -| procs_priv | -| servers | -| slow_log | -| tables_priv | -| time_zone | -| time_zone_leap_second | -| time_zone_name | -| time_zone_transition | -| time_zone_transition_type | -| user | -+---------------------------+ - - -C:\> C:\mysql\bin\mysql -e "SELECT Host,Db,User FROM db" mysql -+------+-------+------+ -| host | db | user | -+------+-------+------+ -| % | test% | | -+------+-------+------+ - - You may need to specify a different directory from the one shown; - if you used the Windows Installation Wizard, then the default - directory is C:\Program Files\MySQL\MySQL Server 5.1, and the - mysql and mysqlshow client programs are in C:\Program - Files\MySQL\MySQL Server 5.1\bin. See Section 2.5.3.1, "Using the - MySQL Installation Wizard," for more information. - - If you have already secured the initial MySQL accounts, you may - need to use the -u and -p options to supply a user name and - password to the mysqlshow and mysql client programs; otherwise the - programs may fail with an error, or you may not be able to view - all databases. For example, if you have assigned the password - "secretpass" to the MySQL root account, then you can invoke - mysqlshow and mysql as shown here: -C:\> C:\mysql\bin\mysqlshow -uroot -psecretpass -+--------------------+ -| Databases | -+--------------------+ -| information_schema | -| mysql | -| test | -+--------------------+ - -C:\> C:\mysql\bin\mysqlshow -uroot -psecretpass mysql -Database: mysql -+---------------------------+ -| Tables | -+---------------------------+ -| columns_priv | -| db | -| event | -| func | -| general_log | -| help_category | -| help_keyword | -| help_relation | -| help_topic | -| host | -| plugin | -| proc | -| procs_priv | -| servers | -| slow_log | -| tables_priv | -| time_zone | -| time_zone_leap_second | -| time_zone_name | -| time_zone_transition | -| time_zone_transition_type | -| user | -+---------------------------+ - - -C:\> C:\mysql\bin\mysql -uroot -psecretpass -e "SELECT Host,Db,User F -ROM db" mysql -+------+-------+------+ -| host | db | user | -+------+-------+------+ -| % | test% | | -+------+-------+------+ - - For more information about these programs, see Section 4.5.6, - "mysqlshow --- Display Database, Table, and Column Information," - and Section 4.5.1, "mysql --- The MySQL Command-Line Tool." - - If you are running a version of Windows that supports services and - you want the MySQL server to run automatically when Windows - starts, see Section 2.5.5.6, "Starting MySQL as a Windows - Service." - -2.5.9. MySQL on Windows Compared to MySQL on Unix - - MySQL for Windows has proven itself to be very stable. The Windows - version of MySQL has the same features as the corresponding Unix - version, with the following exceptions: - - * Limited number of ports - Windows systems have about 4,000 ports available for client - connections, and after a connection on a port closes, it takes - two to four minutes before the port can be reused. In - situations where clients connect to and disconnect from the - server at a high rate, it is possible for all available ports - to be used up before closed ports become available again. If - this happens, the MySQL server appears to be unresponsive even - though it is running. Note that ports may be used by other - applications running on the machine as well, in which case the - number of ports available to MySQL is lower. - For more information about this problem, see - http://support.microsoft.com/default.aspx?scid=kb;en-us;196271 - . - - * Concurrent reads - MySQL depends on the pread() and pwrite() system calls to be - able to mix INSERT and SELECT. Currently, we use mutexes to - emulate pread() and pwrite(). We intend to replace the file - level interface with a virtual interface in the future so that - we can use the readfile()/writefile() interface to get more - speed. The current implementation limits the number of open - files that MySQL 5.1 can use to 2,048, which means that you - cannot run as many concurrent threads on Windows as on Unix. - - * Blocking read - MySQL uses a blocking read for each connection. That has the - following implications if named-pipe connections are enabled: - - + A connection is not disconnected automatically after - eight hours, as happens with the Unix version of MySQL. - - + If a connection hangs, it is not possible to break it - without killing MySQL. - - + mysqladmin kill does not work on a sleeping connection. - - + mysqladmin shutdown cannot abort as long as there are - sleeping connections. - We plan to fix this problem in the future. - - * ALTER TABLE - While you are executing an ALTER TABLE statement, the table is - locked from being used by other threads. This has to do with - the fact that on Windows, you can't delete a file that is in - use by another thread. In the future, we may find some way to - work around this problem. - - * DATA DIRECTORY and INDEX DIRECTORY - The DATA DIRECTORY and INDEX DIRECTORY options for CREATE - TABLE are ignored on Windows, because Windows doesn't support - symbolic links. These options also are ignored on systems that - have a nonfunctional realpath() call. - - * DROP DATABASE - You cannot drop a database that is in use by another thread. - - * Case-insensitive names - File names are not case sensitive on Windows, so MySQL - database and table names are also not case sensitive on - Windows. The only restriction is that database and table names - must be specified using the same case throughout a given - statement. See Section 8.2.2, "Identifier Case Sensitivity." - - * Directory and file names - On Windows, MySQL Server supports only directory and file - names that are compatible with the current ANSI code pages. - For example, the following Japanese directory name will not - work in the Western locale (code page 1252): -datadir="C:/ç§ãŸã¡ã®ãƒ—ロジェクトã®ãƒ‡ãƒ¼ã‚¿" - The same limitation applies to directory and file names - referred to in SQL statements, such as the data file path name - in LOAD DATA INFILE. - - * The "\" path name separator character - Path name components in Windows are separated by the "\" - character, which is also the escape character in MySQL. If you - are using LOAD DATA INFILE or SELECT ... INTO OUTFILE, use - Unix-style file names with "/" characters: -mysql> LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr; -mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr; - Alternatively, you must double the "\" character: -mysql> LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr; -mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr; - - * Problems with pipes - Pipes do not work reliably from the Windows command-line - prompt. If the pipe includes the character ^Z / CHAR(24), - Windows thinks that it has encountered end-of-file and aborts - the program. - This is mainly a problem when you try to apply a binary log as - follows: -C:\> mysqlbinlog binary_log_file | mysql --user=root - If you have a problem applying the log and suspect that it is - because of a ^Z / CHAR(24) character, you can use the - following workaround: -C:\> mysqlbinlog binary_log_file --result-file=/tmp/bin.sql -C:\> mysql --user=root --execute "source /tmp/bin.sql" - The latter command also can be used to reliably read in any - SQL file that may contain binary data. - - * Access denied for user error - If MySQL cannot resolve your host name properly, you may get - the following error when you attempt to run a MySQL client - program to connect to a server running on the same machine: -Access denied for user 'some_user'@'unknown' -to database 'mysql' - To fix this problem, you should create a file named - \windows\hosts containing the following information: -127.0.0.1 localhost - - Here are some open issues for anyone who might want to help us - improve MySQL on Windows: - - * Add macros to use the faster thread-safe increment/decrement - methods provided by Windows. - -2.5.10. Installing MySQL from Source on Windows - - These instructions describe how to build binaries from source for - MySQL 5.1 on Windows. Instructions are provided for building - binaries from a standard source distribution or from the Bazaar - tree that contains the latest development source. - -Note - - The instructions here are strictly for users who want to test - MySQL on Microsoft Windows from the latest source distribution or - from the Bazaar tree. For production use, we do not advise using a - MySQL server built by yourself from source. Normally, it is best - to use precompiled binary distributions of MySQL that are built - specifically for optimal performance on Windows by Oracle - Corporation. Instructions for installing binary distributions are - available in Section 2.5, "Installing MySQL on Windows." - - To build MySQL on Windows from source, you must satisfy the - following system, compiler, and resource requirements: - - * Windows 2000, Windows XP, or newer version. - Windows Vista is supported when using Visual Studio 2005 - provided you have installed the following updates: - - + Microsoft Visual Studio 2005 Professional Edition - ENU - Service Pack 1 (KB926601) - (http://support.microsoft.com/?kbid=926601) - - + Security Update for Microsoft Visual Studio 2005 - Professional Edition - ENU (KB937061) - (http://support.microsoft.com/?kbid=937061) - - + Update for Microsoft Visual Studio 2005 Professional - Edition - ENU (KB932232) - (http://support.microsoft.com/?kbid=932232) - - * CMake, which can be downloaded from http://www.cmake.org. - After installing, modify your path to include the cmake - binary. - - * Microsoft Visual C++ 2005 Express Edition, Visual Studio .Net - 2003 (7.1), or Visual Studio 2005 (8.0) compiler system. - - * If you are using Visual C++ 2005 Express Edition, you must - also install an appropriate Platform SDK. More information and - links to downloads for various Windows platforms is available - from - http://www.microsoft.com/downloads/details.aspx?familyid=0baf2 - b35-c656-4969-ace8-e4c0c0716adb. - - * If you are compiling from a Bazaar tree or making changes to - the parser, you need bison for Windows, which can be - downloaded from - http://gnuwin32.sourceforge.net/packages/bison.htm. Download - the package labeled "Complete package, excluding sources". - After installing the package, modify your path to include the - bison binary and ensure that this binary is accessible from - Visual Studio. - - * Cygwin might be necessary if you want to run the test script - or package the compiled binaries and support files into a Zip - archive. (Cygwin is needed only to test or package the - distribution, not to build it.) Cygwin is available from - http://cygwin.com. - - * 3GB to 5GB of disk space. - - The exact system requirements for Visual Studio can be found here: - http://msdn.microsoft.com/vstudio/Previous/2003/sysreqs/default.as - px and - http://msdn.microsoft.com/vstudio/products/sysreqs/default.aspx - - You also need a MySQL source distribution for Windows, which can - be obtained two ways: - - * Obtain a source distribution packaged by Oracle Corporation. - These are available from http://dev.mysql.com/downloads/. - - * Package a source distribution yourself from the latest Bazaar - developer source tree. For instructions on pulling the latest - source files, see Section 2.3.3, "Installing from the - Development Source Tree." - - If you find something not working as expected, or you have - suggestions about ways to improve the current build process on - Windows, please send a message to the win32 mailing list. See - Section 1.6.1, "MySQL Mailing Lists." - -2.5.10.1. Building MySQL from Source Using CMake and Visual Studio - - You can build MySQL on Windows by using a combination of cmake and - Microsoft Visual Studio .NET 2003 (7.1), Microsoft Visual Studio - 2005 (8.0), Microsoft Visual Studio 2008 (9.0) or Microsoft Visual - C++ 2005 Express Edition. You must have the appropriate Microsoft - Platform SDK installed. - -Note - - To compile from the source code on Windows you must use the - standard source distribution (for example, mysql-5.1.46.tar.gz). - You build from the same distribution as used to build MySQL on - Unix, Linux and other platforms. Do not use the Windows Source - distributions as they do not contain the necessary configuration - script and other files. - - Follow this procedure to build MySQL: - - 1. If you are installing from a packaged source distribution, - create a work directory (for example, C:\workdir), and unpack - the source distribution there using WinZip or another Windows - tool that can read .zip files. This directory is the work - directory in the following instructions. - -Note - You must run the commands in the win directory from the - top-level source directory. Do not change into the win - directory, as the commands will not be executed correctly. - - 2. Start a command shell. If you have not configured the PATH and - other environment variables for all command shells, you may be - able to start a command shell from the Start Menu within the - Windows Visual Studio menu that contains the necessary - environment changes. - - 3. Within the command shell, navigate to the work directory and - run the following command: -C:\workdir>win\configure.js options - If you have associated the .js file extension with an - application such as a text editor, then you may need to use - the following command to force configure.js to be executed as - a script: -C:\workdir>cscript win\configure.js options - These options are available for configure.js: - - + WITH_INNOBASE_STORAGE_ENGINE: Enable the InnoDB storage - engine. - - + WITH_PARTITION_STORAGE_ENGINE: Enable user-defined - partitioning. - - + WITH_ARCHIVE_STORAGE_ENGINE: Enable the ARCHIVE storage - engine. - - + WITH_BLACKHOLE_STORAGE_ENGINE: Enable the BLACKHOLE - storage engine. - - + WITH_EXAMPLE_STORAGE_ENGINE: Enable the EXAMPLE storage - engine. - - + WITH_FEDERATED_STORAGE_ENGINE: Enable the FEDERATED - storage engine. - - + WITH_NDBCLUSTER_STORAGE_ENGINE (experimental): Enable the - NDBCLUSTER storage engine in the MySQL server; cause - binaries for the MySQL Cluster management and data node, - management client, and other programs to be built. - This option is supported only in MySQL Cluster NDB 7.0 - (NDBCLUSTER storage engine versions 6.4.0 and later) - using the MySQL Cluster sources. It cannot be used to - enable clustering support in other MySQL source trees or - distributions. - - + MYSQL_SERVER_SUFFIX=suffix: Server suffix, default none. - - + COMPILATION_COMMENT=comment: Server comment, default - "Source distribution". - - + MYSQL_TCP_PORT=port: Server port, default 3306. - - + DISABLE_GRANT_OPTIONS: Disables the --bootstrap, - --skip-grant-tables, and --init-file options for mysqld. - This option is available as of MySQL 5.1.15. - For example (type the command on one line): -C:\workdir>win\configure.js WITH_INNOBASE_STORAGE_ENGINE - WITH_PARTITION_STORAGE_ENGINE MYSQL_SERVER_SUFFIX=-pro - - 4. From the work directory, execute the win\build-vs9.bat - (Windows Visual Studio 2008), win\build-vs8.bat (Windows - Visual Studio 2005), or win\build-vs71.bat (Windows Visual - Stidion 2003) script, depending on the version of Visual - Studio you have installed. The script invokes CMake, which - generates the mysql.sln solution file. - You can also use the corresponding 64-bit file (for example - win\build-vs8_x64.bat or win\build-vs9_x64.bat) to build the - 64-bit version of MySQL. However, you cannot build the 64-bit - version with Visual Studio Express Edition. You must use - Visual Studio 2005 (8.0) or higher. - - 5. From the work directory, open the generated mysql.sln file - with Visual Studio and select the proper configuration using - the Configuration menu. The menu provides Debug, Release, - RelwithDebInfo, MinRelInfo options. Then select Solution > - Build to build the solution. - Remember the configuration that you use in this step. It is - important later when you run the test script because that - script needs to know which configuration you used. - - 6. Test the server. The server built using the preceding - instructions expects that the MySQL base directory and data - directory are C:\mysql and C:\mysql\data by default. If you - want to test your server using the source tree root directory - and its data directory as the base directory and data - directory, you need to tell the server their path names. You - can either do this on the command line with the --basedir and - --datadir options, or by placing appropriate options in an - option file. (See Section 4.2.3.3, "Using Option Files.") If - you have an existing data directory elsewhere that you want to - use, you can specify its path name instead. - When the server is running in standalone fashion or as a - service based on your configuration, try to connect to it from - the mysql interactive command-line utility. - You can also run the standard test script, mysql-test-run.pl. - This script is written in Perl, so you'll need either Cygwin - or ActiveState Perl to run it. You may also need to install - the modules required by the script. To run the test script, - change location into the mysql-test directory under the work - directory, set the MTR_VS_CONFIG environment variable to the - configuration you selected earlier (or use the --vs-config - option), and invoke mysql-test-run.pl. For example (using - Cygwin and the bash shell): -shell> cd mysql-test -shell> export MTR_VS_CONFIG=debug -shell> ./mysql-test-run.pl --force --timer -shell> ./mysql-test-run.pl --force --timer --ps-protocol - - When you are satisfied that the programs you have built are - working correctly, stop the server. Now you can install the - distribution. One way to do this is to use the make_win_bin_dist - script in the scripts directory of the MySQL source distribution - (see Section 4.4.2, "make_win_bin_dist --- Package MySQL - Distribution as ZIP Archive"). This is a shell script, so you must - have Cygwin installed if you want to use it. It creates a Zip - archive of the built executables and support files that you can - unpack in the location at which you want to install MySQL. - - It is also possible to install MySQL by copying directories and - files directly: - - 1. Create the directories where you want to install MySQL. For - example, to install into C:\mysql, use these commands: -C:\> mkdir C:\mysql -C:\> mkdir C:\mysql\bin -C:\> mkdir C:\mysql\data -C:\> mkdir C:\mysql\share -C:\> mkdir C:\mysql\scripts - If you want to compile other clients and link them to MySQL, - you should also create several additional directories: -C:\> mkdir C:\mysql\include -C:\> mkdir C:\mysql\lib -C:\> mkdir C:\mysql\lib\debug -C:\> mkdir C:\mysql\lib\opt - If you want to benchmark MySQL, create this directory: -C:\> mkdir C:\mysql\sql-bench - Benchmarking requires Perl support. See Section 2.15, "Perl - Installation Notes." - - 2. From the work directory, copy into the C:\mysql directory the - following files and directories: -C:\> cd \workdir -C:\workdir> mkdir C:\mysql -C:\workdir> mkdir C:\mysql\bin -C:\workdir> copy client\Release\*.exe C:\mysql\bin -C:\workdir> copy sql\Release\mysqld.exe C:\mysql\bin\mysqld.exe -C:\workdir> xcopy scripts\*.* C:\mysql\scripts /E -C:\workdir> xcopy share\*.* C:\mysql\share /E - If you want to compile other clients and link them to MySQL, - you should also copy several libraries and header files: -C:\workdir> copy lib\Release\mysqlclient.lib C:\mysql\lib\debug -C:\workdir> copy lib\Release\libmysql.* C:\mysql\lib\debug -C:\workdir> copy lib\Release\zlib.* C:\mysql\lib\debug -C:\workdir> copy lib\Release\mysqlclient.lib C:\mysql\lib\opt -C:\workdir> copy lib\Release\libmysql.* C:\mysql\lib\opt -C:\workdir> copy lib\Release\zlib.* C:\mysql\lib\opt -C:\workdir> copy include\*.h C:\mysql\include -C:\workdir> copy libmysql\libmysql.def C:\mysql\include - -Note - If you have compiled a Debug, rather than Release solution, - you can replace Release with Debug in the source file names - shown above. - If you want to benchmark MySQL, you should also do this: -C:\workdir> xcopy sql-bench\*.* C:\mysql\bench /E - - After installation, set up and start the server in the same way as - for binary Windows distributions. This includes creating the - system tables by running mysql_install_db. For more information, - see Section 2.5, "Installing MySQL on Windows." - -2.5.11. Compiling MySQL Clients on Windows - - In your source files, you should include my_global.h before - mysql.h: -#include -#include - - my_global.h includes any other files needed for Windows - compatibility (such as windows.h) if you compile your program on - Windows. - - You can either link your code with the dynamic libmysql.lib - library, which is just a wrapper to load in libmysql.dll on - demand, or link with the static mysqlclient.lib library. - - The MySQL client libraries are compiled as threaded libraries, so - you should also compile your code to be multi-threaded. - -2.6. Installing MySQL on Linux - - The following sections covers the installation of Linux using - RPMs. For information on using a generic binary package using tar, - see Section 2.2, "Installing MySQL from Generic Binaries on - Unix/Linux." For information on installing from source, see - Section 2.3, "MySQL Installation Using a Source Distribution." - - mysql.server can be found in the support-files directory under the - MySQL installation directory or in a MySQL source tree. You can - install it as /etc/init.d/mysql for automatic MySQL startup and - shutdown. See Section 2.13.1.2, "Starting and Stopping MySQL - Automatically." - -2.6.1. Installing MySQL from RPM Packages on Linux - - The recommended way to install MySQL on RPM-based Linux - distributions is by using the RPM packages. The RPMs that we - provide to the community should work on all versions of Linux that - support RPM packages and use glibc 2.3. To obtain RPM packages, - see Section 2.1.3, "How to Get MySQL." - - For non-RPM Linux distributions, you can install MySQL using a - .tar.gz package. See Section 2.2, "Installing MySQL from Generic - Binaries on Unix/Linux." - - We do provide some platform-specific RPMs; the difference between - a platform-specific RPM and a generic RPM is that a - platform-specific RPM is built on the targeted platform and is - linked dynamically whereas a generic RPM is linked statically with - LinuxThreads. - -Note - - RPM distributions of MySQL often are provided by other vendors. Be - aware that they may differ in features and capabilities from those - built by us, and that the instructions in this manual do not - necessarily apply to installing them. The vendor's instructions - should be consulted instead. - - In most cases, you need to install only the MySQL-server and - MySQL-client packages to get a functional MySQL installation. The - other packages are not required for a standard installation. - - RPMs for MySQL Cluster. Beginning with MySQL 5.1.24, standard - MySQL server RPMs built by MySQL no longer provide support for the - NDBCLUSTER storage engine. MySQL Cluster users wanting to upgrade - MySQL 5.1.23 or earlier installations from RPMs built by MySQL - should upgrade to MySQL Cluster NDB 6.2 or MySQL Cluster NDB 6.3; - RPMs that should work with most Linux distributions are available - for both of these release series. - -Important - - When upgrading a MySQL Cluster RPM installation, you must upgrade - all installed RPMs, including the Server and Client RPMs. - - For more information about installing MySQL Cluster from RPMs, see - Section 17.2.1, "MySQL Cluster Multi-Computer Installation." - - For upgrades, if your installation was originally produced by - installing multiple RPM packages, it is best to upgrade all the - packages, not just some. For example, if you previously installed - the server and client RPMs, do not upgrade just the server RPM. - - The RPM packages shown in the following list are available. The - names shown here use a suffix of .glibc23.i386.rpm, but particular - packages can have different suffixes, described later. - - * MySQL-server-VERSION.glibc23.i386.rpm - The MySQL server. You need this unless you only want to - connect to a MySQL server running on another machine. - - * MySQL-client-VERSION.glibc23.i386.rpm - The standard MySQL client programs. You probably always want - to install this package. - - * MySQL-devel-VERSION.glibc23.i386.rpm - The libraries and include files that are needed if you want to - compile other MySQL clients, such as the Perl modules. - - * MySQL-debuginfo-VERSION.glibc23.i386.rpm - This package contains debugging information. debuginfo RPMs - are never needed to use MySQL software; this is true both for - the server and for client programs. However, they contain - additional information that might be needed by a debugger to - analyze a crash. - - * MySQL-shared-VERSION.glibc23.i386.rpm - This package contains the shared libraries - (libmysqlclient.so*) that certain languages and applications - need to dynamically load and use MySQL. It contains - single-threaded and thread-safe libraries. If you install this - package, do not install the MySQL-shared-compat package. - - * MySQL-shared-compat-VERSION.glibc23.i386.rpm - This package includes the shared libraries for MySQL 3.23, - 4.0, and so on, up to the current release. It contains - single-threaded and thread-safe libraries. Install this - package instead of MySQL-shared if you have applications - installed that are dynamically linked against older versions - of MySQL but you want to upgrade to the current version - without breaking the library dependencies. - - * MySQL-shared-compat-advanced-gpl-VERSION.glibc23.i386.rpm, - MySQL-shared-compat-advanced-VERSION.glibc23.i386.rpm - These are like the MySQL-shared-compat package, but are for - the "MySQL Enterprise Server - Advanced Edition" products. - Install these packages rather than the normal - MySQL-shared-compat package if you want to included shared - client libraries for older MySQL versions. - - * MySQL-embedded-VERSION.glibc23.i386.rpm - The embedded MySQL server library. - - * MySQL-ndb-management-VERSION.glibc23.i386.rpm, - MySQL-ndb-storage-VERSION.glibc23.i386.rpm, - MySQL-ndb-tools-VERSION.glibc23.i386.rpm, - MySQL-ndb-extra-VERSION.glibc23.i386.rpm - Packages that contain additional files for MySQL Cluster - installations. - -Note - The MySQL-ndb-tools RPM requires a working installation of - perl. Prior to MySQL 5.1.18, the DBI and HTML::Template - packages were also required. See Section 2.15, "Perl - Installation Notes," and Section 17.4.21, "ndb_size.pl --- - NDBCLUSTER Size Requirement Estimator," for more information. - - * MySQL-test-VERSION.glibc23.i386.rpm - This package includes the MySQL test suite. - - * MySQL-VERSION.src.rpm - This contains the source code for all of the previous - packages. It can also be used to rebuild the RPMs on other - architectures (for example, Alpha or SPARC). - - The suffix of RPM package names (following the VERSION value) has - the following syntax: -.PLATFORM.CPU.rpm - - The PLATFORM and CPU values indicate the type of system for which - the package is built. PLATFORM indicates the platform and CPU - indicates the processor type or family. - - All packages are dynamically linked against glibc 2.3. The - PLATFORM value indicates whether the package is platform - independent or intended for a specific platform, as shown in the - following table. - glibc23 Platform independent, should run on any Linux distribution - that supports glibc 2.3 - rhel3, rhel4 Red Hat Enterprise Linux 3 or 4 - sles9, sles10 SuSE Linux Enterprise Server 9 or 10 - - In MySQL 5.1, only glibc23 packages are available currently. - - The CPU value indicates the processor type or family for which the - package is built. - i386 x86 processor, 386 and up - i586 x86 processor, Pentium and up - x86_64 64-bit x86 processor - ia64 Itanium (IA-64) processor - - To see all files in an RPM package (for example, a MySQL-server - RPM), run a command like this: -shell> rpm -qpl MySQL-server-VERSION.glibc23.i386.rpm - - To perform a standard minimal installation, install the server and - client RPMs: -shell> rpm -i MySQL-server-VERSION.glibc23.i386.rpm -shell> rpm -i MySQL-client-VERSION.glibc23.i386.rpm - - To install only the client programs, install just the client RPM: -shell> rpm -i MySQL-client-VERSION.glibc23.i386.rpm - - RPM provides a feature to verify the integrity and authenticity of - packages before installing them. If you would like to learn more - about this feature, see Section 2.1.4, "Verifying Package - Integrity Using MD5 Checksums or GnuPG." - - The server RPM places data under the /var/lib/mysql directory. The - RPM also creates a login account for a user named mysql (if one - does not exist) to use for running the MySQL server, and creates - the appropriate entries in /etc/init.d/ to start the server - automatically at boot time. (This means that if you have performed - a previous installation and have made changes to its startup - script, you may want to make a copy of the script so that you - don't lose it when you install a newer RPM.) See Section 2.13.1.2, - "Starting and Stopping MySQL Automatically," for more information - on how MySQL can be started automatically on system startup. - - If you want to install the MySQL RPM on older Linux distributions - that do not support initialization scripts in /etc/init.d - (directly or via a symlink), you should create a symbolic link - that points to the location where your initialization scripts - actually are installed. For example, if that location is - /etc/rc.d/init.d, use these commands before installing the RPM to - create /etc/init.d as a symbolic link that points there: -shell> cd /etc -shell> ln -s rc.d/init.d . - - However, all current major Linux distributions should support the - new directory layout that uses /etc/init.d, because it is required - for LSB (Linux Standard Base) compliance. - - If the RPM files that you install include MySQL-server, the mysqld - server should be up and running after installation. You should be - able to start using MySQL. - - If something goes wrong, you can find more information in the - binary installation section. See Section 2.2, "Installing MySQL - from Generic Binaries on Unix/Linux." - -Note - - The accounts that are listed in the MySQL grant tables initially - have no passwords. After starting the server, you should set up - passwords for them using the instructions in Section 2.13, - "Post-Installation Setup and Testing." - - During RPM installation, a user named mysql and a group named - mysql are created on the system. This is done using the useradd, - groupadd, and usermod commands. Those commands require appropriate - administrative privileges, which is ensured for locally managed - users and groups (as listed in the /etc/passwd and /etc/group - files) by the RPM installation process being run by root. - - For nonlocal user management (LDAP, NIS, and so forth), the - administrative tools may require additional authentication (such - as a password), and will fail if the installing user does not - provide this authentication. Even if they fail, the RPM - installation will not abort but succeed, and this is intentional. - If they failed, some of the intended transfer of ownership may be - missing, and it is recommended that the system administrator then - manually ensures some appropriate user andgroup exists and - manually transfers ownership following the actions in the RPM spec - file. - -2.7. Installing MySQL on Mac OS X - - MySQL for Mac OS X is available in a number of different forms: - - * Native Package Installer format, which uses the native Mac OS - X installer to walk you through the installation of MySQL. For - more information, see Section 2.7.1, "Installing MySQL Using - the Installation Package." You can use the package installer - with Mac OS X 10.3 and later, and available for both PowerPC - and Intel architectures, and both 32-bit and 64-bit - architectures. There is no Universal Binary available using - the package installation method. The user you use to perform - the installation must have administrator privileges. - - * Tar package format, which uses a file packaged using the Unix - tar and gzip commands. To use this method, you will need to - open a Terminal window. You do not need administrator - privileges using this method, as you can install the MySQL - server anywhere using this method. For more information on - using this method, you can use the generic instructions for - using a tarball, Section 2.2, "Installing MySQL from Generic - Binaries on Unix/Linux."You can use the package installer with - Mac OS X 10.3 and later, and available for both PowerPC and - Intel architectures, and both 32-bit and 64-bit architectures. - A Universal Binary, incorporating both Power PC and Intel - architectures and 32-bit and 64-bit binaries is available. - In addition to the core installation, the Package Installer - also includes Section 2.7.2, "Installing the MySQL Startup - Item" and Section 2.7.3, "Installing and Using the MySQL - Preference Pane," both of which simplify the management of - your installation. - - * Mac OS X server includes a version of MySQL as standard. If - you want to use a more recent version than that supplied with - the Mac OS X server release, you can make use of the package - or tar formats. For more information on using the MySQL - bundled with Mac OS X, see Section 2.7.4, "Using MySQL on Mac - OS X Server." - - For additional information on using MySQL on Mac OS X, see Section - 2.7.5, "MySQL Installation on Mac OS X Notes." - -2.7.1. Installing MySQL Using the Installation Package - - You can install MySQL on Mac OS X 10.3.x ("Panther") or newer - using a Mac OS X binary package in PKG format instead of the - binary tarball distribution. Please note that older versions of - Mac OS X (for example, 10.1.x or 10.2.x) are not supported by this - package. - - The package is located inside a disk image (.dmg) file that you - first need to mount by double-clicking its icon in the Finder. It - should then mount the image and display its contents. - -Note - - Before proceeding with the installation, be sure to shut down all - running MySQL server instances by either using the MySQL Manager - Application (on Mac OS X Server) or via mysqladmin shutdown on the - command line. - - When installing from the package version, you should also install - the MySQL Preference Pane, which will allow you to control the - startup and execution of your MySQL server from System - Preferences. For more information, see Section 2.7.3, "Installing - and Using the MySQL Preference Pane." - - When installing using the package installer, the files are - installed into a directory within /usr/local matching the name of - the installation version and platform. For example, the installer - file mysql-5.1.39-osx10.5-x86_64.pkg installs MySQL into - /usr/local/mysql-5.1.39-osx10.5-x86_64 . The installation layout - of the directory is as shown in the following table: - Directory Contents of Directory - bin Client programs and the mysqld server - data Log files, databases - docs Manual in Info format - include Include (header) files - lib Libraries - man Unix manual pages - mysql-test MySQL test suite - scripts Contains the mysql_install_db script - share/mysql Error message files - sql-bench Benchmarks - support-files Scripts and sample configuration files - /tmp/mysql.sock The location of the MySQL Unix socket - - During the package installer process, a symbolic link from - /usr/local/mysql to the version/platform specific directory - created during installation will be created automatically. - - 1. Download and open the MySQL package installer, which is - provided on a disk image (.dmg). Double-click to open the disk - image, which includes the main MySQL installation package, the - MySQLStartupItem.pkg installation package, and the - MySQL.prefPane. - - 2. Double-click on the MySQL installer package. It will be named - according to the version of MySQL you have downloaded. For - example, if you have downloaded MySQL 5.1.39, double-click - mysql-5.1.39-osx10.5-x86.pkg. - - 3. You will be presented with the openin installer dialog. Click - Continue to begihn installation. - MySQL Package Installer: Step 1 - - 4. A copy of the installation instructions and other important - information relevant to this installation are display. Click - Continue . - - 5. If you have downloaded the community version of MySQL, you - will be shown a copy of the relevent GNU General Public - License. Click Continue . - - 6. Select the drive you want to use to install the MySQL Startup - Item. The drive must have a valid, bootable, Mac OS X - operating system installed. Click Continue. - MySQL Package Installer: Step 4 - - 7. You will be asked to confirm the details of the installation, - including the space required for the installation. To change - the drive on which the startup item is installed you can click - either Go Back or Change Install Location.... To install the - startup item, click Install. - - 8. Once the installation has been completed successfully, you - will be given an Install Succeeded message. - - Once you have completed the basic installation, you must complete - the post-installation steps as specifed in Section 2.13, - "Post-Installation Setup and Testing." - - For convenience, you may also want to install the Section 2.7.2, - "Installing the MySQL Startup Item" and Section 2.7.3, "Installing - and Using the MySQL Preference Pane." - -2.7.2. Installing the MySQL Startup Item - - The MySQL Installation Package includes a startup item that can be - used to automatically startup and shutdown MySQL during boot. - - To install the MySQL Startup Item: - - 1. Download and open the MySQL package installer, which is - provided on a disk image (.dmg). Double-click to open the disk - image, which includes the main MySQL installation package, the - MySQLStartupItem.pkg installation package, and the - MySQL.prefPane. - - 2. Double-click on the MySQLStartItem.pkg file to start the - installation process. - - 3. You will be presented with the Install MySQL Startup Item - dialog. - MySQL Startup Item Installer: Step 1 - Click Continue to continue the installation process. - - 4. A copy of the installation instructions and other important - information relevant to this installation are display. Click - Continue . - - 5. Select the drive you want to use to install the MySQL Startup - Item. The drive must have a valid, bootable, Mac OS X - operating system installed. Click Continue. - MySQL Startup Item Installer: Step 3 - - 6. You will be asked to confirm the details of the installation. - To change the drive on which the startup item is installed you - can click either Go Back or Change Install Location.... To - install the startup item, click Install. - - 7. Once the installation has been completed successfully, you - will be given an Install Succeeded message. - MySQL Startup Item Installer: Step 5 - - The Startup Item for MySQL is installed into - /Library/StartupItems/MySQLCOM. The Startup Item installation adds - a variable MYSQLCOM=-YES- to the system configuration file - /etc/hostconfig. If you want to disable the automatic startup of - MySQL, simply change this variable to MYSQLCOM=-NO-. - - After the installation, you can start up MySQL by running the - following commands in a terminal window. You must have - administrator privileges to perform this task. - - If you have installed the Startup Item, use this command to start - the server: -shell> sudo /Library/StartupItems/MySQLCOM/MySQLCOM start - - You may be prompted for your password to complete the startup. - - If you have installed the Startup Item, use this command to stop - the server: -shell> sudo /Library/StartupItems/MySQLCOM/MySQLCOM stop - - You may be prompted for your password to complete the shutdown. - -2.7.3. Installing and Using the MySQL Preference Pane - - The MySQL Package installer disk image also includes a custom - MySQL Preference Pane that enables you to start, stop and control - automated startup during boot of your MySQL installation. - - To install the MySQL Preference Pane: - - 1. Download and open the MySQL package installer package, which - is provided on a disk image (.dmg). Double-click to open the - disk image, which includes the main MySQL installation - package, the MySQLStartupItem.pkg installation package, and - the MySQL.prefPane. - - 2. Double click on MySQL.prefPane. The MySQL System Preferences - will open. - - 3. If this is the first time you have installed the preference - pane, you will be asked to confirm installation and whether - you want to install the preference pane for all users, or only - the current user. To install the preference pane for all users - you will need administrator privileges. If necessary, you will - be prompted for the username and password for a user with - administrator privileges. - - 4. If you already have the MySQL Preference Pane installed, you - will be asked to confirm whether you want to overwrite the - existing MySQL Preference Pane. - -Note - - The MySQL Preference Pane only starts and stops MySQL installation - installed from the MySQL package installation that have been - installed in the default location. - - Once the MySQL Preference Pane has been installed, you can control - your MySQL server instance using the preference pane. To use the - preference pane, open the System Preferences... from the Apple - menu. Select the MySQL preference pane by clicking on the MySQL - logo within the Other section of the preference panes list. - MySQL Preference Pane - - The MySQL Preference Pane shows the current status of the MySQL - server, showing stopped (in red) if the server is not running and - running (in green) if the server has already been started. The - preference pane will also show the current setting for whether the - MySQL server has been set to start up automatically. - - * To start MySQL using the preference pane: - Click Start MySQL Server. You may be prompted for the username - and password of a user with administrator privileges to start - the MySQL server. - - * To stop MySQL using the preference pane: - Click Stop MySQL Server. You may be prompted for the username - and password of a user with administrator privileges to - shutdown the MySQL server. - - * To automatically start the MySQL server when the system boots: - Check the checkbox next to Automatically Start MySQL Server on - Startup. - - * To disable the automatic starting of the MySQL server when the - system boots: - Uncheck the checkbox next to Automatically Start MySQL Server - on Startup. - - You can close the System Preferences... once you have completed - your settings. - -2.7.4. Using MySQL on Mac OS X Server - - If you are running Mac OS X Server, a version of MySQL should - already be installed. The following table shows the versions of - MySQL that ship with Mac OS X Server versions. - Mac OS X Server Version MySQL Version - 10.2-10.2.2 3.23.51 - 10.2.3-10.2.6 3.23.53 - 10.3 4.0.14 - 10.3.2 4.0.16 - 10.4.0 4.1.10a - 10.5.0 5.0.45 - 10.6.0 5.0.82 - - The installation layout of MySQL on Mac OS X Server is as shown in - the table below: - Directory Contents of Directory - /usr/bin Client programs - /var/mysql Log files, databases - /usr/libexec The mysqld server - /usr/share/man Unix manual pages - /usr/share/mysql/mysql-test MySQL test suite - /usr/share/mysql Contains the mysql_install_db script - /var/mysql/mysql.sock The location of the MySQL Unix socket - -Note - - The MySQL server bundled with Mac OS X Server does not include the - MySQL client libraries and header files required if you want to - access and use MySQL from a third-party driver, such as Perl DBI - or PHP. For more information on obtaining and installing MySQL - libraries, see Mac OS X Server version 10.5: MySQL libraries - available for download (http://support.apple.com/kb/TA25017). - Alternatively, you can ignore the bundled MySQL server and install - MySQL from the package or tarball installation. - - For more information on managing the bundled MySQL instance in Mac - OS X Server 10.5, see Mac OS X Server: Web Technologies - Administration For Version 10.5 Leopard - (http://images.apple.com/server/macosx/docs/Web_Technologies_Admin - _v10.5.pdf). For more information on managing the bundled MySQL - instance in Mac OS X Server 10.6, see Mac OS X Server: Web - Technologies Administration Version 10.6 Snow Leopard - (http://manuals.info.apple.com/en_US/WebTech_v10.6.pdf). - -2.7.5. MySQL Installation on Mac OS X Notes - - You should keep the following issues and notes in mind: - - * The default location for the MySQL Unix socket is different on - Mac OS X and Mac OS X Server depending on the installation - type you chose. The default locations by installation are as - follows: - - Package Installer from MySQL /tmp/mysql.sock - Tarball from MySQL /tmp/mysql.sock - MySQL Bundled with Mac OS X Server /var/mysql/mysql.sock - To prevent issues, you should either change the configuration - of the socket used within your application (for example, - changing php.ini), or you should configure the socket location - using a MySQL configuration file and the socket option. For - more information, see Section 5.1.2, "Server Command Options." - - * You may need (or want) to create a specific mysql user to own - the MySQL directory and data. On Mac OS X 10.4 and lower you - can do this by using the Netinfo Manager application, located - within the Utilities folder within the Applications folder. On - Mac OS X 10.5 and later you can do this through the Directory - Utility. From Mac OS X 10.5 and later (including Mac OS X - Server 10.5) the mysql should already exist. For use in single - user mode, an entry for _mysql (note the underscore prefix) - should already exist within the system /etc/passwd file. - - * Due to a bug in the Mac OS X package installer, you may see - this error message in the destination disk selection dialog: -You cannot install this software on this disk. (null) - If this error occurs, simply click the Go Back button once to - return to the previous screen. Then click Continue to advance - to the destination disk selection again, and you should be - able to choose the destination disk correctly. We have - reported this bug to Apple and it is investigating this - problem. - - * Because the MySQL package installer installs the MySQL - contents into a version and platform specific directory, you - can use this to upgrade and migrate your database between - versions. You will need to either copy the data directory from - the old version to the new version, or alternatively specify - an alternative datadir value to set location of the data - directory. - - * You might want to add aliases to your shell's resource file to - make it easier to access commonly used programs such as mysql - and mysqladmin from the command line. The syntax for bash is: -alias mysql=/usr/local/mysql/bin/mysql -alias mysqladmin=/usr/local/mysql/bin/mysqladmin - For tcsh, use: -alias mysql /usr/local/mysql/bin/mysql -alias mysqladmin /usr/local/mysql/bin/mysqladmin - Even better, add /usr/local/mysql/bin to your PATH environment - variable. You can do this by modifying the appropriate startup - file for your shell. For more information, see Section 4.2.1, - "Invoking MySQL Programs." - - * After you have copied over the MySQL database files from the - previous installation and have successfully started the new - server, you should consider removing the old installation - files to save disk space. Additionally, you should also remove - older versions of the Package Receipt directories located in - /Library/Receipts/mysql-VERSION.pkg. - -2.8. Installing MySQL on Solaris - - To obtain a binary MySQL distribution for Solaris in tarball or - PKG format, http://dev.mysql.com/downloads/mysql/5.1.html. - - If you install MySQL using a binary tarball distribution on - Solaris, you may run into trouble even before you get the MySQL - distribution unpacked, as the Solaris tar cannot handle long file - names. This means that you may see errors when you try to unpack - MySQL. - - If this occurs, you must use GNU tar (gtar) to unpack the - distribution. - - You can install MySQL on Solaris using a binary package in PKG - format instead of the binary tarball distribution. Before - installing using the binary PKG format, you should create the - mysql user and group, for example: -groupadd mysql -useradd -g mysql mysql - - Some basic PKG-handling commands follow: - - * To add a package: -pkgadd -d package_name.pkg - - * To remove a package: -pkgrm package_name - - * To get a full list of installed packages: -pkginfo - - * To get detailed information for a package: -pkginfo -l package_name - - * To list the files belonging to a package: -pkgchk -v package_name - - * To get packaging information for an arbitrary file: -pkgchk -l -p file_name - -2.8.1. Solaris Notes - - For information about installing MySQL on Solaris using PKG - distributions, see Section 2.8, "Installing MySQL on Solaris." - - On Solaris, you may run into trouble even before you get the MySQL - distribution unpacked, as the Solaris tar cannot handle long file - names. This means that you may see errors when you try to unpack - MySQL. - - If this occurs, you must use GNU tar (gtar) to unpack the - distribution. - - If you have an UltraSPARC system, you can get 4% better - performance by adding -mcpu=v8 -Wa,-xarch=v8plusa to the CFLAGS - and CXXFLAGS environment variables. - - If you have Sun's Forte 5.0 (or newer) compiler, you can run - configure like this: -CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt" \ -CXX=CC CXXFLAGS="-noex -mt" \ -./configure --prefix=/usr/local/mysql --enable-assembler - - To create a 64-bit binary with Sun's Forte compiler, use the - following configuration options: -CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt -xarch=v9" \ -CXX=CC CXXFLAGS="-noex -mt -xarch=v9" ASFLAGS="-xarch=v9" \ -./configure --prefix=/usr/local/mysql --enable-assembler - - To create a 64-bit Solaris binary using gcc, add -m64 to CFLAGS - and CXXFLAGS and remove --enable-assembler from the configure - line. - - In the MySQL benchmarks, we obtained a 4% speed increase on - UltraSPARC when using Forte 5.0 in 32-bit mode, as compared to - using gcc 3.2 with the -mcpu flag. - - If you create a 64-bit mysqld binary, it is 4% slower than the - 32-bit binary, but can handle more threads and memory. - - When using Solaris 10 for x86_64, you should mount any file - systems on which you intend to store InnoDB files with the - forcedirectio option. (By default mounting is done without this - option.) Failing to do so will cause a significant drop in - performance when using the InnoDB storage engine on this platform. - - If you get a problem with fdatasync or sched_yield, you can fix - this by adding LIBS=-lrt to the configure line - - Solaris does not provide static versions of all system libraries - (libpthreads and libdl), so you cannot compile MySQL with - --static. If you try to do so, you get one of the following - errors: -ld: fatal: library -ldl: not found -undefined reference to `dlopen' -cannot find -lrt - - If you link your own MySQL client programs, you may see the - following error at runtime: -ld.so.1: fatal: libmysqlclient.so.#: -open failed: No such file or directory - - This problem can be avoided by one of the following methods: - - * Link clients with the -Wl,r/full/path/to/libmysqlclient.so - flag rather than with -Lpath). - - * Copy libmysqclient.so to /usr/lib. - - * Add the path name of the directory where libmysqlclient.so is - located to the LD_RUN_PATH environment variable before running - your client. - - If you have problems with configure trying to link with -lz when - you don't have zlib installed, you have two options: - - * If you want to be able to use the compressed communication - protocol, you need to get and install zlib from ftp.gnu.org. - - * Run configure with the --with-named-z-libs=no option when - building MySQL. - - If you are using gcc and have problems with loading user-defined - functions (UDFs) into MySQL, try adding -lgcc to the link line for - the UDF. - - If you would like MySQL to start automatically, you can copy - support-files/mysql.server to /etc/init.d and create a symbolic - link to it named /etc/rc3.d/S99mysql.server. - - If too many processes try to connect very rapidly to mysqld, you - should see this error in the MySQL log: -Error in accept: Protocol error - - You might try starting the server with the --back_log=50 option as - a workaround for this. (Use -O back_log=50 before MySQL 4.) - - To configure the generation of core files on Solaris you should - use the coreadm command. Because of the security implications of - generating a core on a setuid() application, by default, Solaris - does not support core files on setuid() programs. However, you can - modify this behavior using coreadm. If you enable setuid() core - files for the current user, they will be generated using the mode - 600 and owned by the superuser. - -2.9. Installing MySQL on i5/OS - - The i5/OS POWER MySQL package was created in cooperation with IBM. - MySQL works within the Portable Application Solution Environment - (PASE) on the System i series of hardware and will also provide - database services for the Zend Core for i5/OS. - - MySQL for i5/OS is provided both as a tar file and as a save file - (.savf) package that can be downloaded and installed directly - without any additional installation steps required. To install - MySQL using the tar file, see Section 2.2, "Installing MySQL from - Generic Binaries on Unix/Linux." - - MySQL is only supported on i5/OS V5R4 or later releases. The i5/OS - PASE must be installed for MySQL to operate. You must be able to - login as a user in *SECOFR class. - - You should the installation notes and tips for i5/OS before - starting installation. See i5/OS Installation Notes. - - Before Installation: - -Note - - The installation package will use an existing configuration if you - have previously installed MySQL (which is identified by looking - for the file /etc/my.cnf). The values for the data directory - (DATADIR) and owner of the MySQL files (USRPRF) specified during - the installation will be ignored, and the values determined from - the /etc/my.cnf will be used instead. - - If you want to change these parameters during a new install, you - should temporarily rename /etc/my.cnf, install MySQL using the new - parameters you want to use, and then merge your previous - /etc/my.cnf configuration settings with the new /etc/my.cnf file - that is created during installation. - - * You must have a user profile with PASE with suitable - privileges. The user should be within the *SECOFR class, such - as the QSECOFR user ID. You can use the WRKUSRPRF command to - check your user profile. - - * For network connections to MySQL, you must have TCP/IP - enabled. You should also check the following: - - + Ensure that a name has defined for the system. Run the - Configure TCP/IP (CFGTCP) command and select option 12 - (Change TCP/IP domain information) to display this - setting. Make sure that a value is listed in the Host - name field. - - + Make sure that the system has a loopback entry which - represents the localhost or 127.0.0.1. - - + Ensure that the IP address of the IBM i machine is mapped - correctly to the host name. - - To install MySQL on i5/OS, follow these steps: - - 1. On the System i machine, create a save file that will be used - to receive the downloaded installation save file. The file - should be located within the General Purpose Library (QGPL): -CRTSAVF FILE(QGPL/MYSQLINST) TESXT('MySQL Save file') - - 2. Download the MySQL installation save file in 32-bit - (mysql-5.1.39-i5os-power-32bit.savf) or 64-bit - (mysql-5.1.39-i5os-power-64bit.savf) from MySQL Downloads - (http://dev.mysql.com/downloads). - - 3. You need to FTP the downloaded .savf file directly into the - QGPL/MYSQLINST file on the System i server. You can do this - through FTP using the following steps after logging in to the - System i machine: -ftp> bin -ftp> cd qgpl -ftp> put mysql-5.1.39-i5os-power.savf mysqlinst - - 4. Log into the System i server using a user in the *SECOFR - class, such as the QSECOFR user ID. - - 5. You need to restore the installation library stored in the - .savf save file: -RSTLIB MYSQLINST DEV(*SAVF) SAVF(QGPL/MYSQLINST) MBROPT(*ALL) ALWOBJD -IF(*ALL) - -Note - You can ignore the security changes-type message at the bottom - of the installation panel. - - 6. Once you have finished restoring the MYSQLINST library, check - that all the necessary objects for installation are on the - system by using the Display Library (DSPLIB) command: -DSPLIB LIB(MYSQLINST) - - 7. You need to execute the installation command, - MYSQLINST/INSMYSQL. You can specify three parameter settings - during installation: - - + DIR('/QOpenSys/usr/local/mysql') sets the installation - location for the MySQL files. The directory will be - created if it does not already exist. - - + DATADIR('/QOpenSys/usr/local/mysql/data') sets the - location of the directory that will be used to store the - database files and binary logs. The default setting is - /QOpenSys/usr/local/mysql/data. Note that if the - installer detects an existing installation (due to the - existence of /etc/my.cnf), then the existing setting will - be used instead of the default. - - + USRPRF(MYSQL) sets the user profile that will own the - files that are installed. The profile will be created if - it does not already exist. - -Note - You should choose an appropriate user for using the MySQL - server installation. The user will be used whenever you - need to do any administration on the MySQL server. - Once you have set the appropriate parameters, you can begin - the installation. - The installation copies all the necessary files into a - directory matching the DIR configuration value; sets the - ownership on those files, sets up the MySQL environment and - creates the MySQL configuration file (in /etc/my.cnf) - completing all the steps in a typical binary installation - process automatically. If this is a new installation of MySQL, - or if the installer detects that this is a new version - (because the /etc/my.cnf file does not exist), then the - initial core MySQL databases will also be created during - installation. - Once the installation has been completed, you will get a - notice advising you to set the password for the root user. For - more information, Section 2.13, "Post-Installation Setup and - Testing." - - 8. Once the installation has completed, you can delete the - installation file: -DLTLIB LIB(MYSQLINST) - - Upgrading an existing MySQL instance - - You need to execute the upgrade command, MYSQLINST/UPGMYSQL. - -Note - - You cannot use MYSQLINST/UPGMYSQL to upgrade between major - versions of MySQL (for example from 5.0 to 5.1). For information - and advice on migrating between major versions you can use the - advice provided in Section 2.4.1.1, "Upgrading from MySQL 5.0 to - 5.1." - - You must specify 6 parameters to perform an upgrade: - - * DIR('/QOpenSys/usr/local/') --- sets the installation location - for the MySQL files. The directory will be created if it does - not already exist. This is the directory that the MySQL server - will be installed into, inside a directory with a name - matching the version and release. For example, if installing - MySQL 5.1.39 with the DIR set to /QOpenSys/usr/local/ would - result in /QOpenSys/usr/local/mysql-5.1.39-i5os-power64 and a - symbolic link to this directory will be created in - /QOpenSys/usr/local/mysql. - - * DATADIR('/QOpenSys/mysql/data') --- sets the location of the - directory that will be upgraded. - - * USRPRF('MYSQL') --- sets the user profile that will own the - files that are installed. The profile will be created if it - does not already exist; if it is created as part of the - upgrade process, it will be disabled initially. You may wish - to enable this user profile so that it can be used to start - the MySQL server later. It is best practice to use the one - previously created during the first installation. - - * MYSQLUSR('root user') --- any user account in the current - MySQL server with SUPER privileges. - - * PASSWORD('root user password') --- the password for the above - account. This is necessary as the upgrade starts the MySQL - server to upgrade the tables and the password is need to be - able to shutdown the MySQL server. - - * CURINST('path to previous install') --- the full path to the - installation that is being upgraded. For example an - installation in /QOpenSys/usr/local/ will be - /QOpenSys/usr/local/msyql-5.1.30-i5os-power64. Failure to - specify this option may result in corruption of your existing - data files. - - For example: -MYSQLINST/UPGMYSQL DIR('/QOpenSys/usr/local/') DATADIR('/QOpenSys/mys -ql/data') » - USERPRF(MYSQL) MYSQLUSR('root') PASSWORD('root') CURINST('/QOpen -Sys/usr/local/mysql-5.1.30-i5os-power64') - - You should receive a Program Message indicating UPGRADE - SUCCESSFUL! upon completion or an error message if there is a - problem.You can view the upgrade programs progression and the - error in the text file upgrade.log in the installation directory. - - To start MySQL: - - 1. Log into the System i server using the user profile create or - specified during installation. By default, this is MYSQL. - -Note - You should start mysqld_safe using a user that in the PASE - environment has the id=0 (the equivalent of the standard Unix - root user). If you do not use a user with this ID then the - system will be unable to change the user when executing mysqld - as set using --user option. If this happens, mysqld may be - unable to read the files located within the MySQL data - directory and the execution will fail. - - 2. Enter the PASE environment using call qp2term. - - 3. Start the MySQL server by changing to the installation - directory and running mysqld_safe, specifying the user name - used to install the server. The installer conveniently - installs a symbolic link to the installation directory - (mysql-5.0.42-i5os-power-32bit) as /opt/mysql/mysql: -> cd /opt/mysql/mysql -> bin/mysqld_safe --user=mysql & - You should see a message similar to the following: -Starting mysqld daemon with databases » - from /opt/mysql/mysql-enterprise-5.0.42-i5os-power-32bit/data - - If you are having problems starting MySQL server, see Section - 2.13.1.3, "Starting and Troubleshooting the MySQL Server." - - To stop MySQL: - - 1. Log into the System i server using the user profile create or - specified during installation. By default, this is MYSQL. - - 2. Enter the PASE environment using call qp2term. - - 3. Stop the MySQL server by changing into the installation - directory and running mysqladmin, specifying the user name - used to install the server: -> cd /opt/mysql/mysql -> bin/mysqladmin -u root shutdown - If the session that you started and stopped MySQL are the - same, you may get the log output from mysqld: - STOPPING server from pid file » - /opt/mysql/mysql-enterprise-5.0.42-i5os-power-32bit/data/I5DBX.R -CHLAND.IBM.COM.pid - 070718 10:34:20 mysqld ended - If the sessions used to start and stop MySQL are different, - you will not receive any confirmation of the shutdown. - - Note and tips - - * A problem has been identified with the installation process on - DBCS systems. If you are having problems install MySQL on a - DBCS system, you need to change your job's coded character set - identifier (CSSID) to 37 (EBCDIC) before executing the install - command, INSMYSQL. To do this, determine your existing CSSID - (using DSPJOB and selecting option 2), execute CHGJOB - CSSID(37), run INSMYSQL to install MySQL and then execute - CHGJOB again with your original CSSID. - - * If you want to use the Perl scripts that are included with - MySQL, you need to download the iSeries Tools for Developers - (5799-PTL). See - http://www-03.ibm.com/servers/enable/site/porting/tools/. - -2.10. Installing MySQL on FreeBSD - - This section provides information about using MySQL on variants of - FreeBSD Unix. - - The easiest (and preferred) way to install MySQL is to use the - mysql-server and mysql-client ports available at - http://www.freebsd.org/. Using these ports gives you the following - benefits: - - * A working MySQL with all optimizations enabled that are known - to work on your version of FreeBSD. - - * Automatic configuration and build. - - * Startup scripts installed in /usr/local/etc/rc.d. - - * The ability to use pkg_info -L to see which files are - installed. - - * The ability to use pkg_delete to remove MySQL if you no longer - want it on your machine. - - The MySQL build process requires GNU make (gmake) to work. If GNU - make is not available, you must install it first before compiling - MySQL. - - The recommended way to compile and install MySQL on FreeBSD with - gcc (2.95.2 and up) is: -CC=gcc CFLAGS="-O2 -fno-strength-reduce" \ - CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions \ - -felide-constructors -fno-strength-reduce" \ - ./configure --prefix=/usr/local/mysql --enable-assembler -gmake -gmake install -cd /usr/local/mysql -bin/mysql_install_db --user=mysql -bin/mysqld_safe & - - FreeBSD is known to have a very low default file handle limit. See - Section B.5.2.18, "'File' Not Found and Similar Errors." Start the - server by using the --open-files-limit option for mysqld_safe, or - raise the limits for the mysqld user in /etc/login.conf and - rebuild it with cap_mkdb /etc/login.conf. Also be sure that you - set the appropriate class for this user in the password file if - you are not using the default (use chpass mysqld-user-name). See - Section 4.3.2, "mysqld_safe --- MySQL Server Startup Script." - - In current versions of FreeBSD (at least 4.x and greater), you may - increase the limit on the amount of memory available for a process - by adding the following entries to the /boot/loader.conf file and - rebooting the machine (these are not settings that can be changed - at run time with the sysctl command): -kern.maxdsiz="1073741824" # 1GB -kern.dfldsiz="1073741824" # 1GB -kern.maxssiz="134217728" # 128MB - - For older versions of FreeBSD, you must recompile your kernel to - change the maximum data segment size for a process. In this case, - you should look at the MAXDSIZ option in the LINT config file for - more information. - - If you get problems with the current date in MySQL, setting the TZ - variable should help. See Section 2.14, "Environment Variables." - -2.11. Installing MySQL on HP-UX - - If you install MySQL using a binary tarball distribution on HP-UX, - you may run into trouble even before you get the MySQL - distribution unpacked, as the HP-UX tar cannot handle long file - names. This means that you may see errors when you try to unpack - MySQL. - - If this occurs, you must use GNU tar (gtar) to unpack the - distribution. - - Because of some critical bugs in the standard HP-UX libraries, you - should install the following patches before trying to run MySQL on - HP-UX 11.0: -PHKL_22840 Streams cumulative -PHNE_22397 ARPA cumulative - - This solves the problem of getting EWOULDBLOCK from recv() and - EBADF from accept() in threaded applications. - - If you are using gcc 2.95.1 on an unpatched HP-UX 11.x system, you - may get the following error: -In file included from /usr/include/unistd.h:11, - from ../include/global.h:125, - from mysql_priv.h:15, - from item.cc:19: -/usr/include/sys/unistd.h:184: declaration of C function ... -/usr/include/sys/pthread.h:440: previous declaration ... -In file included from item.h:306, - from mysql_priv.h:158, - from item.cc:19: - - The problem is that HP-UX does not define pthreads_atfork() - consistently. It has conflicting prototypes in - /usr/include/sys/unistd.h:184 and /usr/include/sys/pthread.h:440. - - One solution is to copy /usr/include/sys/unistd.h into - mysql/include and edit unistd.h and change it to match the - definition in pthread.h. Look for this line: -extern int pthread_atfork(void (*prepare)(), void (*parent)(), - void (*child)()); - - Change it to look like this: -extern int pthread_atfork(void (*prepare)(void), void (*parent)(void) -, - void (*child)(void)); - - After making the change, the following configure line should work: -CFLAGS="-fomit-frame-pointer -O3 -fpic" CXX=gcc \ -CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O3" \ -./configure --prefix=/usr/local/mysql --disable-shared - - If you are using HP-UX compiler, you can use the following command - (which has been tested with cc B.11.11.04): -CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure \ - --with-extra-character-set=complex - - You can ignore any errors of the following type: -aCC: warning 901: unknown option: `-3': use +help for online -documentation - - If you get the following error from configure, verify that you - don't have the path to the K&R compiler before the path to the - HP-UX C and C++ compiler: -checking for cc option to accept ANSI C... no -configure: error: MySQL requires an ANSI C compiler (and a C++ compil -er). -Try gcc. See the Installation chapter in the Reference Manual. - - Another reason for not being able to compile is that you didn't - define the +DD64 flags as just described. - - Another possibility for HP-UX 11 is to use the MySQL binaries - provided at http://dev.mysql.com/downloads/, which we have built - and tested ourselves. We have also received reports that the HP-UX - 10.20 binaries supplied by MySQL can be run successfully on HP-UX - 11. If you encounter problems, you should be sure to check your - HP-UX patch level. - -2.12. Installing MySQL on AIX - - Automatic detection of xlC is missing from Autoconf, so a number - of variables need to be set before running configure. The - following example uses the IBM compiler: -export CC="xlc_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192 " -export CXX="xlC_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192" -export CFLAGS="-I /usr/local/include" -export LDFLAGS="-L /usr/local/lib" -export CPPFLAGS=$CFLAGS -export CXXFLAGS=$CFLAGS - -./configure --prefix=/usr/local \ - --localstatedir=/var/mysql \ - --sbindir='/usr/local/bin' \ - --libexecdir='/usr/local/bin' \ - --enable-thread-safe-client \ - --enable-large-files - - The preceding options are used to compile the MySQL distribution - that can be found at http://www-frec.bull.com/. - - If you change the -O3 to -O2 in the preceding configure line, you - must also remove the -qstrict option. This is a limitation in the - IBM C compiler. - - If you are using gcc to compile MySQL, you must use the - -fno-exceptions flag, because the exception handling in gcc is not - thread-safe! There are also some known problems with IBM's - assembler that may cause it to generate bad code when used with - gcc. - - Use the following configure line with gcc 2.95 on AIX: -CC="gcc -pipe -mcpu=power -Wa,-many" \ -CXX="gcc -pipe -mcpu=power -Wa,-many" \ -CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \ -./configure --prefix=/usr/local/mysql --with-low-memory - - The -Wa,-many option is necessary for the compile to be - successful. IBM is aware of this problem but is in no hurry to fix - it because of the workaround that is available. We don't know if - the -fno-exceptions is required with gcc 2.95, but because MySQL - doesn't use exceptions and the option generates faster code, you - should always use it with gcc. - - If you get a problem with assembler code, try changing the - -mcpu=xxx option to match your CPU. Typically power2, power, or - powerpc may need to be used. Alternatively, you might need to use - 604 or 604e. We are not positive but suspect that power would - likely be safe most of the time, even on a power2 machine. - - If you don't know what your CPU is, execute a uname -m command. It - produces a string that looks like 000514676700, with a format of - xxyyyyyymmss where xx and ss are always 00, yyyyyy is a unique - system ID and mm is the ID of the CPU Planar. A chart of these - values can be found at - http://www16.boulder.ibm.com/pseries/en_US/cmds/aixcmds5/uname.htm - . - - This gives you a machine type and a machine model you can use to - determine what type of CPU you have. - - If you have problems with threads on AIX 5.3, you should upgrade - AIX 5.3 to technology level 7 (5300-07). - - If you have problems with signals (MySQL dies unexpectedly under - high load), you may have found an OS bug with threads and signals. - In this case, you can tell MySQL not to use signals by configuring - as follows: -CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \ -CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti \ --DDONT_USE_THR_ALARM" \ -./configure --prefix=/usr/local/mysql --with-debug \ - --with-low-memory - - This doesn't affect the performance of MySQL, but has the side - effect that you can't kill clients that are "sleeping" on a - connection with mysqladmin kill or mysqladmin shutdown. Instead, - the client dies when it issues its next command. - - On some versions of AIX, linking with libbind.a makes - getservbyname() dump core. This is an AIX bug and should be - reported to IBM. - - For AIX 4.2.1 and gcc, you have to make the following changes. - - After configuring, edit config.h and include/my_config.h and - change the line that says this: -#define HAVE_SNPRINTF 1 - - to this: -#undef HAVE_SNPRINTF - - And finally, in mysqld.cc, you need to add a prototype for - initgroups(). -#ifdef _AIX41 -extern "C" int initgroups(const char *,int); -#endif - - For 32-bit binaries, if you need to allocate a lot of memory to - the mysqld process, it is not enough to just use ulimit -d - unlimited. You may also have to modify mysqld_safe to add a line - something like this: -export LDR_CNTRL='MAXDATA=0x80000000' - - You can find more information about using a lot of memory at - http://publib16.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/lr - g_prg_support.htm. - - Users of AIX 4.3 should use gmake instead of the make utility - included with AIX. - - As of AIX 4.1, the C compiler has been unbundled from AIX as a - separate product. gcc 3.3.2 can be obtained here: - ftp://ftp.software.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc/gc - c/ - - The steps for compiling MySQL on AIX with gcc 3.3.2 are similar to - those for using gcc 2.95 (in particular, the need to edit config.h - and my_config.h after running configure). However, before running - configure, you should also patch the curses.h file as follows: -/opt/freeware/lib/gcc-lib/powerpc-ibm-aix5.2.0.0/3.3.2/include/curses -.h.ORIG - Mon Dec 26 02:17:28 2005 ---- /opt/freeware/lib/gcc-lib/powerpc-ibm-aix5.2.0.0/3.3.2/include/cu -rses.h -Mon Dec 26 02:40:13 2005 -*************** -*** 2023,2029 **** - - - #endif /* _AIX32_CURSES */ -! #if defined(__USE_FIXED_PROTOTYPES__) || defined(__cplusplus) || de -fined -(__STRICT_ANSI__) - extern int delwin (WINDOW *); - extern int endwin (void); - extern int getcurx (WINDOW *); ---- 2023,2029 ---- - - - #endif /* _AIX32_CURSES */ -! #if 0 && (defined(__USE_FIXED_PROTOTYPES__) || defined(__cplusplus) -|| defined -(__STRICT_ANSI__)) - extern int delwin (WINDOW *); - extern int endwin (void); - extern int getcurx (WINDOW *); - -2.13. Post-Installation Setup and Testing - - After installing MySQL, there are some issues that you should - address. For example, on Unix, you should initialize the data - directory and create the MySQL grant tables. On all platforms, an - important security concern is that the initial accounts in the - grant tables have no passwords. You should assign passwords to - prevent unauthorized access to the MySQL server. Optionally, you - can create time zone tables to enable recognition of named time - zones. - - The following sections include post-installation procedures that - are specific to Windows systems and to Unix systems. Another - section, Section 2.13.1.3, "Starting and Troubleshooting the MySQL - Server," applies to all platforms; it describes what to do if you - have trouble getting the server to start. Section 2.13.2, - "Securing the Initial MySQL Accounts," also applies to all - platforms. You should follow its instructions to make sure that - you have properly protected your MySQL accounts by assigning - passwords to them. - - When you are ready to create additional user accounts, you can - find information on the MySQL access control system and account - management in Section 5.4, "The MySQL Access Privilege System," - and Section 5.5, "MySQL User Account Management." - -2.13.1. Unix Post-Installation Procedures - - After installing MySQL on Unix, you need to initialize the grant - tables, start the server, and make sure that the server works - satisfactorily. You may also wish to arrange for the server to be - started and stopped automatically when your system starts and - stops. You should also assign passwords to the accounts in the - grant tables. - - On Unix, the grant tables are set up by the mysql_install_db - program. For some installation methods, this program is run for - you automatically: - - * If you install MySQL on Linux using RPM distributions, the - server RPM runs mysql_install_db. - - * If you install MySQL on Mac OS X using a PKG distribution, the - installer runs mysql_install_db. - - Otherwise, you'll need to run mysql_install_db yourself. - - The following procedure describes how to initialize the grant - tables (if that has not previously been done) and then start the - server. It also suggests some commands that you can use to test - whether the server is accessible and working properly. For - information about starting and stopping the server automatically, - see Section 2.13.1.2, "Starting and Stopping MySQL Automatically." - - After you complete the procedure and have the server running, you - should assign passwords to the accounts created by - mysql_install_db. Instructions for doing so are given in Section - 2.13.2, "Securing the Initial MySQL Accounts." - - In the examples shown here, the server runs under the user ID of - the mysql login account. This assumes that such an account exists. - Either create the account if it does not exist, or substitute the - name of a different existing login account that you plan to use - for running the server. - - 1. Change location into the top-level directory of your MySQL - installation, represented here by BASEDIR: -shell> cd BASEDIR - BASEDIR is likely to be something like /usr/local/mysql or - /usr/local. The following steps assume that you are located in - this directory. - - 2. If necessary, run the mysql_install_db program to set up the - initial MySQL grant tables containing the privileges that - determine how users are allowed to connect to the server. - You'll need to do this if you used a distribution type for - which the installation procedure doesn't run the program for - you. - Typically, mysql_install_db needs to be run only the first - time you install MySQL, so you can skip this step if you are - upgrading an existing installation, However, mysql_install_db - does not overwrite any existing privilege tables, so it should - be safe to run in any circumstances. - To initialize the grant tables, use one of the following - commands, depending on whether mysql_install_db is located in - the bin or scripts directory: -shell> bin/mysql_install_db --user=mysql -shell> scripts/mysql_install_db --user=mysql - It might be necessary to specify other options such as - --basedir or --datadir if mysql_install_db does not use the - correct locations for the installation directory or data - directory. For example: -shell> bin/mysql_install_db --user=mysql \ - --basedir=/opt/mysql/mysql \ - --datadir=/opt/mysql/mysql/data - The mysql_install_db script creates the server's data - directory. Under the data directory, it creates directories - for the mysql database that holds all database privileges and - the test database that you can use to test MySQL. The script - also creates privilege table entries for root and - anonymous-user accounts. The accounts have no passwords - initially. A description of their initial privileges is given - in Section 2.13.2, "Securing the Initial MySQL Accounts." - Briefly, these privileges allow the MySQL root user to do - anything, and allow anybody to create or use databases with a - name of test or starting with test_. - It is important to make sure that the database directories and - files are owned by the mysql login account so that the server - has read and write access to them when you run it later. To - ensure this, the --user option should be used as shown if you - run mysql_install_db as root. Otherwise, you should execute - the script while logged in as mysql, in which case you can - omit the --user option from the command. - mysql_install_db creates several tables in the mysql database, - including user, db, host, tables_priv, columns_priv, func, and - others. See Section 5.4, "The MySQL Access Privilege System," - for a complete listing and description of these tables. - If you don't want to have the test database, you can remove it - with mysqladmin -u root drop test after starting the server. - If you have trouble with mysql_install_db at this point, see - Section 2.13.1.1, "Problems Running mysql_install_db." - - 3. Start the MySQL server: -shell> bin/mysqld_safe --user=mysql & - It is important that the MySQL server be run using an - unprivileged (non-root) login account. To ensure this, the - --user option should be used as shown if you run mysqld_safe - as system root. Otherwise, you should execute the script while - logged in to the system as mysql, in which case you can omit - the --user option from the command. - Further instructions for running MySQL as an unprivileged user - are given in Section 5.3.6, "How to Run MySQL as a Normal - User." - If you neglected to create the grant tables before proceeding - to this step, the following message appears in the error log - file when you start the server: -mysqld: Can't find file: 'host.frm' - If you have other problems starting the server, see Section - 2.13.1.3, "Starting and Troubleshooting the MySQL Server." - - 4. Use mysqladmin to verify that the server is running. The - following commands provide simple tests to check whether the - server is up and responding to connections: -shell> bin/mysqladmin version -shell> bin/mysqladmin variables - The output from mysqladmin version varies slightly depending - on your platform and version of MySQL, but should be similar - to that shown here: -shell> bin/mysqladmin version -mysqladmin Ver 14.12 Distrib 5.1.46, for pc-linux-gnu on i686 -... - -Server version 5.1.46 -Protocol version 10 -Connection Localhost via UNIX socket -UNIX socket /var/lib/mysql/mysql.sock -Uptime: 14 days 5 hours 5 min 21 sec - -Threads: 1 Questions: 366 Slow queries: 0 -Opens: 0 Flush tables: 1 Open tables: 19 -Queries per second avg: 0.000 - To see what else you can do with mysqladmin, invoke it with - the --help option. - - 5. Verify that you can shut down the server: -shell> bin/mysqladmin -u root shutdown - - 6. Verify that you can start the server again. Do this by using - mysqld_safe or by invoking mysqld directly. For example: -shell> bin/mysqld_safe --user=mysql --log & - If mysqld_safe fails, see Section 2.13.1.3, "Starting and - Troubleshooting the MySQL Server." - - 7. Run some simple tests to verify that you can retrieve - information from the server. The output should be similar to - what is shown here: -shell> bin/mysqlshow -+-----------+ -| Databases | -+-----------+ -| mysql | -| test | -+-----------+ - -shell> bin/mysqlshow mysql -Database: mysql -+---------------------------+ -| Tables | -+---------------------------+ -| columns_priv | -| db | -| func | -| help_category | -| help_keyword | -| help_relation | -| help_topic | -| host | -| proc | -| procs_priv | -| tables_priv | -| time_zone | -| time_zone_leap_second | -| time_zone_name | -| time_zone_transition | -| time_zone_transition_type | -| user | -+---------------------------+ - -shell> bin/mysql -e "SELECT Host,Db,User FROM db" mysql -+------+--------+------+ -| host | db | user | -+------+--------+------+ -| % | test | | -| % | test_% | | -+------+--------+------+ - - 8. There is a benchmark suite in the sql-bench directory (under - the MySQL installation directory) that you can use to compare - how MySQL performs on different platforms. The benchmark suite - is written in Perl. It requires the Perl DBI module that - provides a database-independent interface to the various - databases, and some other additional Perl modules: -DBI -DBD::mysql -Data::Dumper -Data::ShowTable - These modules can be obtained from CPAN - (http://www.cpan.org/). See also Section 2.15.1, "Installing - Perl on Unix." - The sql-bench/Results directory contains the results from many - runs against different databases and platforms. To run all - tests, execute these commands: -shell> cd sql-bench -shell> perl run-all-tests - If you don't have the sql-bench directory, you probably - installed MySQL using RPM files other than the source RPM. - (The source RPM includes the sql-bench benchmark directory.) - In this case, you must first install the benchmark suite - before you can use it. There are separate benchmark RPM files - named mysql-bench-VERSION.i386.rpm that contain benchmark code - and data. - If you have a source distribution, there are also tests in its - tests subdirectory that you can run. For example, to run - auto_increment.tst, execute this command from the top-level - directory of your source distribution: -shell> mysql -vvf test < ./tests/auto_increment.tst - The expected result of the test can be found in the - ./tests/auto_increment.res file. - - 9. At this point, you should have the server running. However, - none of the initial MySQL accounts have a password, so you - should assign passwords using the instructions found in - Section 2.13.2, "Securing the Initial MySQL Accounts." - - The MySQL 5.1 installation procedure creates time zone tables in - the mysql database. However, you must populate the tables manually - using the instructions in Section 9.6, "MySQL Server Time Zone - Support." - -2.13.1.1. Problems Running mysql_install_db - - The purpose of the mysql_install_db script is to generate new - MySQL privilege tables. It does not overwrite existing MySQL - privilege tables, and it does not affect any other data. - - If you want to re-create your privilege tables, first stop the - mysqld server if it is running. Then rename the mysql directory - under the data directory to save it, and then run - mysql_install_db. Suppose that your current directory is the MySQL - installation directory and that mysql_install_db is located in the - bin directory and the data directory is named data. To rename the - mysql database and re-run mysql_install_db, use these commands. -shell> mv data/mysql data/mysql.old -shell> bin/mysql_install_db --user=mysql - - When you run mysql_install_db, you might encounter the following - problems: - - * mysql_install_db fails to install the grant tables - You may find that mysql_install_db fails to install the grant - tables and terminates after displaying the following messages: -Starting mysqld daemon with databases from XXXXXX -mysqld ended - In this case, you should examine the error log file very - carefully. The log should be located in the directory XXXXXX - named by the error message and should indicate why mysqld - didn't start. If you do not understand what happened, include - the log when you post a bug report. See Section 1.7, "How to - Report Bugs or Problems." - - * There is a mysqld process running - This indicates that the server is running, in which case the - grant tables have probably been created already. If so, there - is no need to run mysql_install_db at all because it needs to - be run only once (when you install MySQL the first time). - - * Installing a second mysqld server does not work when one - server is running - This can happen when you have an existing MySQL installation, - but want to put a new installation in a different location. - For example, you might have a production installation, but you - want to create a second installation for testing purposes. - Generally the problem that occurs when you try to run a second - server is that it tries to use a network interface that is in - use by the first server. In this case, you should see one of - the following error messages: -Can't start server: Bind on TCP/IP port: -Address already in use -Can't start server: Bind on unix socket... - For instructions on setting up multiple servers, see Section - 5.6, "Running Multiple MySQL Servers on the Same Machine." - - * You do not have write access to the /tmp directory - If you do not have write access to create temporary files or a - Unix socket file in the default location (the /tmp directory), - an error occurs when you run mysql_install_db or the mysqld - server. - You can specify different locations for the temporary - directory and Unix socket file by executing these commands - prior to starting mysql_install_db or mysqld, where - some_tmp_dir is the full path name to some directory for which - you have write permission: -shell> TMPDIR=/some_tmp_dir/ -shell> MYSQL_UNIX_PORT=/some_tmp_dir/mysql.sock -shell> export TMPDIR MYSQL_UNIX_PORT - Then you should be able to run mysql_install_db and start the - server with these commands: -shell> bin/mysql_install_db --user=mysql -shell> bin/mysqld_safe --user=mysql & - If mysql_install_db is located in the scripts directory, - modify the first command to scripts/mysql_install_db. - See Section B.5.4.5, "How to Protect or Change the MySQL Unix - Socket File," and Section 2.14, "Environment Variables." - - There are some alternatives to running the mysql_install_db script - provided in the MySQL distribution: - - * If you want the initial privileges to be different from the - standard defaults, you can modify mysql_install_db before you - run it. However, it is preferable to use GRANT and REVOKE to - change the privileges after the grant tables have been set up. - In other words, you can run mysql_install_db, and then use - mysql -u root mysql to connect to the server as the MySQL root - user so that you can issue the necessary GRANT and REVOKE - statements. - If you want to install MySQL on several machines with the same - privileges, you can put the GRANT and REVOKE statements in a - file and execute the file as a script using mysql after - running mysql_install_db. For example: -shell> bin/mysql_install_db --user=mysql -shell> bin/mysql -u root < your_script_file - By doing this, you can avoid having to issue the statements - manually on each machine. - - * It is possible to re-create the grant tables completely after - they have previously been created. You might want to do this - if you're just learning how to use GRANT and REVOKE and have - made so many modifications after running mysql_install_db that - you want to wipe out the tables and start over. - To re-create the grant tables, remove all the .frm, .MYI, and - .MYD files in the mysql database directory. Then run the - mysql_install_db script again. - - * You can start mysqld manually using the --skip-grant-tables - option and add the privilege information yourself using mysql: -shell> bin/mysqld_safe --user=mysql --skip-grant-tables & -shell> bin/mysql mysql - From mysql, manually execute the SQL commands contained in - mysql_install_db. Make sure that you run mysqladmin - flush-privileges or mysqladmin reload afterward to tell the - server to reload the grant tables. - Note that by not using mysql_install_db, you not only have to - populate the grant tables manually, you also have to create - them first. - -2.13.1.2. Starting and Stopping MySQL Automatically - - Generally, you start the mysqld server in one of these ways: - - * Invoke mysqld directly. This works on any platform. - - * Run the MySQL server as a Windows service. The service can be - set to start the server automatically when Windows starts, or - as a manual service that you start on request. For - instructions, see Section 2.5.5.6, "Starting MySQL as a - Windows Service." - - * Invoke mysqld_safe, which tries to determine the proper - options for mysqld and then runs it with those options. This - script is used on Unix and Unix-like systems. See Section - 4.3.2, "mysqld_safe --- MySQL Server Startup Script." - - * Invoke mysql.server. This script is used primarily at system - startup and shutdown on systems that use System V-style run - directories, where it usually is installed under the name - mysql. The mysql.server script starts the server by invoking - mysqld_safe. See Section 4.3.3, "mysql.server --- MySQL Server - Startup Script." - - * On Mac OS X, install a separate MySQL Startup Item package to - enable the automatic startup of MySQL on system startup. The - Startup Item starts the server by invoking mysql.server. See - Section 2.7, "Installing MySQL on Mac OS X," for details. - - The mysqld_safe and mysql.server scripts and the Mac OS X Startup - Item can be used to start the server manually, or automatically at - system startup time. mysql.server and the Startup Item also can be - used to stop the server. - - To start or stop the server manually using the mysql.server - script, invoke it with start or stop arguments: -shell> mysql.server start -shell> mysql.server stop - - Before mysql.server starts the server, it changes location to the - MySQL installation directory, and then invokes mysqld_safe. If you - want the server to run as some specific user, add an appropriate - user option to the [mysqld] group of the /etc/my.cnf option file, - as shown later in this section. (It is possible that you will need - to edit mysql.server if you've installed a binary distribution of - MySQL in a nonstandard location. Modify it to change location into - the proper directory before it runs mysqld_safe. If you do this, - your modified version of mysql.server may be overwritten if you - upgrade MySQL in the future, so you should make a copy of your - edited version that you can reinstall.) - - mysql.server stop stops the server by sending a signal to it. You - can also stop the server manually by executing mysqladmin - shutdown. - - To start and stop MySQL automatically on your server, you need to - add start and stop commands to the appropriate places in your - /etc/rc* files. - - If you use the Linux server RPM package - (MySQL-server-VERSION.rpm), the mysql.server script is installed - in the /etc/init.d directory with the name mysql. You need not - install it manually. See Section 2.6.1, "Installing MySQL from RPM - Packages on Linux," for more information on the Linux RPM - packages. - - Some vendors provide RPM packages that install a startup script - under a different name such as mysqld. - - If you install MySQL from a source distribution or using a binary - distribution format that does not install mysql.server - automatically, you can install it manually. The script can be - found in the support-files directory under the MySQL installation - directory or in a MySQL source tree. - - To install mysql.server manually, copy it to the /etc/init.d - directory with the name mysql, and then make it executable. Do - this by changing location into the appropriate directory where - mysql.server is located and executing these commands: -shell> cp mysql.server /etc/init.d/mysql -shell> chmod +x /etc/init.d/mysql - - Older Red Hat systems use the /etc/rc.d/init.d directory rather - than /etc/init.d. Adjust the preceding commands accordingly. - Alternatively, first create /etc/init.d as a symbolic link that - points to /etc/rc.d/init.d: -shell> cd /etc -shell> ln -s rc.d/init.d . - - After installing the script, the commands needed to activate it to - run at system startup depend on your operating system. On Linux, - you can use chkconfig: -shell> chkconfig --add mysql - - On some Linux systems, the following command also seems to be - necessary to fully enable the mysql script: -shell> chkconfig --level 345 mysql on - - On FreeBSD, startup scripts generally should go in - /usr/local/etc/rc.d/. The rc(8) manual page states that scripts in - this directory are executed only if their basename matches the - *.sh shell file name pattern. Any other files or directories - present within the directory are silently ignored. In other words, - on FreeBSD, you should install the mysql.server script as - /usr/local/etc/rc.d/mysql.server.sh to enable automatic startup. - - As an alternative to the preceding setup, some operating systems - also use /etc/rc.local or /etc/init.d/boot.local to start - additional services on startup. To start up MySQL using this - method, you could append a command like the one following to the - appropriate startup file: -/bin/sh -c 'cd /usr/local/mysql; ./bin/mysqld_safe --user=mysql &' - - For other systems, consult your operating system documentation to - see how to install startup scripts. - - You can add options for mysql.server in a global /etc/my.cnf file. - A typical /etc/my.cnf file might look like this: -[mysqld] -datadir=/usr/local/mysql/var -socket=/var/tmp/mysql.sock -port=3306 -user=mysql - -[mysql.server] -basedir=/usr/local/mysql - - The mysql.server script supports the following options: basedir, - datadir, and pid-file. If specified, they must be placed in an - option file, not on the command line. mysql.server supports only - start and stop as command-line arguments. - - The following table shows which option groups the server and each - startup script read from option files. - Script Option Groups - mysqld [mysqld], [server], [mysqld-major_version] - mysqld_safe [mysqld], [server], [mysqld_safe] - mysql.server [mysqld], [mysql.server], [server] - - [mysqld-major_version] means that groups with names like - [mysqld-5.0] and [mysqld-5.1] are read by servers having versions - 5.0.x, 5.1.x, and so forth. This feature can be used to specify - options that can be read only by servers within a given release - series. - - For backward compatibility, mysql.server also reads the - [mysql_server] group and mysqld_safe also reads the [safe_mysqld] - group. However, you should update your option files to use the - [mysql.server] and [mysqld_safe] groups instead when using MySQL - 5.1. - - See Section 4.2.3.3, "Using Option Files." - -2.13.1.3. Starting and Troubleshooting the MySQL Server - - This section provides troubleshooting suggestions for problems - starting the server on Unix. If you are using Windows, see Section - 2.5.6, "Troubleshooting a MySQL Installation Under Windows." - - If you have problems starting the server, here are some things to - try: - - * Check the error log to see why the server does not start. - - * Specify any special options needed by the storage engines you - are using. - - * Make sure that the server knows where to find the data - directory. - - * Make sure that the server can access the data directory. The - ownership and permissions of the data directory and its - contents must be set such that the server can read and modify - them. - - * Verify that the network interfaces the server wants to use are - available. - - Some storage engines have options that control their behavior. You - can create a my.cnf file and specify startup options for the - engines that you plan to use. If you are going to use storage - engines that support transactional tables (InnoDB, NDB), be sure - that you have them configured the way you want before starting the - server: - - * If you are using InnoDB tables, see Section 13.6.2, "InnoDB - Configuration." - - * If you are using MySQL Cluster, see Section 17.3, "MySQL - Cluster Configuration." - - MySQL Enterprise For expert advice on start-up options appropriate - to your circumstances, subscribe to The MySQL Enterprise Monitor. - For more information, see - http://www.mysql.com/products/enterprise/advisors.html. - - Storage engines will use default option values if you specify - none, but it is recommended that you review the available options - and specify explicit values for those for which the defaults are - not appropriate for your installation. - - When the mysqld server starts, it changes location to the data - directory. This is where it expects to find databases and where it - expects to write log files. The server also writes the pid - (process ID) file in the data directory. - - The data directory location is hardwired in when the server is - compiled. This is where the server looks for the data directory by - default. If the data directory is located somewhere else on your - system, the server will not work properly. You can determine what - the default path settings are by invoking mysqld with the - --verbose and --help options. - - If the default locations don't match the MySQL installation layout - on your system, you can override them by specifying options to - mysqld or mysqld_safe on the command line or in an option file. - - To specify the location of the data directory explicitly, use the - --datadir option. However, normally you can tell mysqld the - location of the base directory under which MySQL is installed and - it looks for the data directory there. You can do this with the - --basedir option. - - To check the effect of specifying path options, invoke mysqld with - those options followed by the --verbose and --help options. For - example, if you change location into the directory where mysqld is - installed and then run the following command, it shows the effect - of starting the server with a base directory of /usr/local: -shell> ./mysqld --basedir=/usr/local --verbose --help - - You can specify other options such as --datadir as well, but - --verbose and --help must be the last options. - - Once you determine the path settings you want, start the server - without --verbose and --help. - - If mysqld is currently running, you can find out what path - settings it is using by executing this command: -shell> mysqladmin variables - - Or: -shell> mysqladmin -h host_name variables - - host_name is the name of the MySQL server host. - - If you get Errcode 13 (which means Permission denied) when - starting mysqld, this means that the privileges of the data - directory or its contents do not allow the server access. In this - case, you change the permissions for the involved files and - directories so that the server has the right to use them. You can - also start the server as root, but this raises security issues and - should be avoided. - - On Unix, change location into the data directory and check the - ownership of the data directory and its contents to make sure the - server has access. For example, if the data directory is - /usr/local/mysql/var, use this command: -shell> ls -la /usr/local/mysql/var - - If the data directory or its files or subdirectories are not owned - by the login account that you use for running the server, change - their ownership to that account. If the account is named mysql, - use these commands: -shell> chown -R mysql /usr/local/mysql/var -shell> chgrp -R mysql /usr/local/mysql/var - - If it possible that even with correct ownership, MySQL may fail to - start up if there is other security software running on your - system that manages application access to various parts of the - file system. In this case, you may need to reconfigure that - software to enable mysqld to access the directories it uses during - normal operation. - - If the server fails to start up correctly, check the error log. - Log files are located in the data directory (typically C:\Program - Files\MySQL\MySQL Server 5.1\data on Windows, - /usr/local/mysql/data for a Unix binary distribution, and - /usr/local/var for a Unix source distribution). Look in the data - directory for files with names of the form host_name.err and - host_name.log, where host_name is the name of your server host. - Then examine the last few lines of these files. On Unix, you can - use tail to display them: -shell> tail host_name.err -shell> tail host_name.log - - The error log should contain information that indicates why the - server couldn't start. - - If either of the following errors occur, it means that some other - program (perhaps another mysqld server) is using the TCP/IP port - or Unix socket file that mysqld is trying to use: -Can't start server: Bind on TCP/IP port: Address already in use -Can't start server: Bind on unix socket... - - Use ps to determine whether you have another mysqld server - running. If so, shut down the server before starting mysqld again. - (If another server is running, and you really want to run multiple - servers, you can find information about how to do so in Section - 5.6, "Running Multiple MySQL Servers on the Same Machine.") - - If no other server is running, try to execute the command telnet - your_host_name tcp_ip_port_number. (The default MySQL port number - is 3306.) Then press Enter a couple of times. If you don't get an - error message like telnet: Unable to connect to remote host: - Connection refused, some other program is using the TCP/IP port - that mysqld is trying to use. You'll need to track down what - program this is and disable it, or else tell mysqld to listen to a - different port with the --port option. In this case, you'll also - need to specify the port number for client programs when - connecting to the server via TCP/IP. - - Another reason the port might be inaccessible is that you have a - firewall running that blocks connections to it. If so, modify the - firewall settings to allow access to the port. - - If the server starts but you can't connect to it, you should make - sure that you have an entry in /etc/hosts that looks like this: -127.0.0.1 localhost - - This problem occurs only on systems that do not have a working - thread library and for which MySQL must be configured to use - MIT-pthreads. - - If you cannot get mysqld to start, you can try to make a trace - file to find the problem by using the --debug-dbug option. See MySQL - Internals: Porting - (http://forge.mysql.com/wiki/MySQL_Internals_Porting). - -2.13.2. Securing the Initial MySQL Accounts - - Part of the MySQL installation process is to set up the mysql - database that contains the grant tables: - - * Windows distributions contain preinitialized grant tables that - are installed automatically. - - * On Unix, the grant tables are populated by the - mysql_install_db program. Some installation methods run this - program for you. Others require that you execute it manually. - For details, see Section 2.13.1, "Unix Post-Installation - Procedures." - - The grant tables define the initial MySQL user accounts and their - access privileges. These accounts are set up as follows: - - * Accounts with the user name root are created. These are - superuser accounts that can do anything. The initial root - account passwords are empty, so anyone can connect to the - MySQL server as root --- without a password --- and be granted - all privileges. - - + On Windows, one root account is created; this account - allows connecting from the local host only. The Windows - installer will optionally create an account allowing for - connections from any host only if the user selects the - Enable root access from remote machines option during - installation. - - + On Unix, both root accounts are for connections from the - local host. Connections must be made from the local host - by specifying a host name of localhost for one of the - accounts, or the actual host name or IP number for the - other. - - * Two anonymous-user accounts are created, each with an empty - user name. The anonymous accounts have no password, so anyone - can use them to connect to the MySQL server. - - + On Windows, one anonymous account is for connections from - the local host. It has no global privileges. (Before - MySQL 5.1.16, it has all global privileges, just like the - root accounts.) The other is for connections from any - host and has all privileges for the test database and for - other databases with names that start with test. - - + On Unix, both anonymous accounts are for connections from - the local host. Connections must be made from the local - host by specifying a host name of localhost for one of - the accounts, or the actual host name or IP number for - the other. These accounts have all privileges for the - test database and for other databases with names that - start with test_. - - As noted, none of the initial accounts have passwords. This means - that your MySQL installation is unprotected until you do something - about it: - - * If you want to prevent clients from connecting as anonymous - users without a password, you should either assign a password - to each anonymous account or else remove the accounts. - - * You should assign a password to each MySQL root account. - - The following instructions describe how to set up passwords for - the initial MySQL accounts, first for the anonymous accounts and - then for the root accounts. Replace "newpwd" in the examples with - the actual password that you want to use. The instructions also - cover how to remove the anonymous accounts, should you prefer not - to allow anonymous access at all. - - You might want to defer setting the passwords until later, so that - you don't need to specify them while you perform additional setup - or testing. However, be sure to set them before using your - installation for production purposes. - - Anonymous Account Password Assignment - - To assign passwords to the anonymous accounts, connect to the - server as root and then use either SET PASSWORD or UPDATE. In - either case, be sure to encrypt the password using the PASSWORD() - function. - - To use SET PASSWORD on Windows, do this: -shell> mysql -u root -mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd'); -mysql> SET PASSWORD FOR ''@'%' = PASSWORD('newpwd'); - - To use SET PASSWORD on Unix, do this: -shell> mysql -u root -mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd'); -mysql> SET PASSWORD FOR ''@'host_name' = PASSWORD('newpwd'); - - In the second SET PASSWORD statement, replace host_name with the - name of the server host. This is the name that is specified in the - Host column of the non-localhost record for root in the user - table. If you don't know what host name this is, issue the - following statement before using SET PASSWORD: -mysql> SELECT Host, User FROM mysql.user; - - Look for the record that has root in the User column and something - other than localhost in the Host column. Then use that Host value - in the second SET PASSWORD statement. - - Anonymous Account Removal - - If you prefer to remove the anonymous accounts instead, do so as - follows: -shell> mysql -u root -mysql> DROP USER ''; - - The DROP statement applies both to Windows and to Unix. On - Windows, if you want to remove only the anonymous account that has - the same privileges as root, do this instead: -shell> mysql -u root -mysql> DROP USER ''@'localhost'; - - That account allows anonymous access but has full privileges, so - removing it improves security. - - root Account Password Assignment - - You can assign passwords to the root accounts in several ways. The - following discussion demonstrates three methods: - - * Use the SET PASSWORD statement - - * Use the mysqladmin command-line client program - - * Use the UPDATE statement - - To assign passwords using SET PASSWORD, connect to the server as - root and issue SET PASSWORD statements. Be sure to encrypt the - password using the PASSWORD() function. - - For Windows, do this: -shell> mysql -u root -mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpwd'); -mysql> SET PASSWORD FOR 'root'@'%' = PASSWORD('newpwd'); - - For Unix, do this: -shell> mysql -u root -mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpwd'); -mysql> SET PASSWORD FOR 'root'@'host_name' = PASSWORD('newpwd'); - - In the second SET PASSWORD statement, replace host_name with the - name of the server host. This is the same host name that you used - when you assigned the anonymous account passwords. - - If the user table contains an account with User and Host values of - 'root' and '127.0.0.1', use an additional SET PASSWORD statement - to set that account's password: -mysql> SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('newpwd'); - - To assign passwords to the root accounts using mysqladmin, execute - the following commands: -shell> mysqladmin -u root password "newpwd" -shell> mysqladmin -u root -h host_name password "newpwd" - - These commands apply both to Windows and to Unix. In the second - command, replace host_name with the name of the server host. The - double quotes around the password are not always necessary, but - you should use them if the password contains spaces or other - characters that are special to your command interpreter. - - The mysqladmin method of setting the root account passwords does - not set the password for the 'root'@'127.0.0.1' account. To do so, - use SET PASSWORD as shown earlier. - - You can also use UPDATE to modify the user table directly. The - following UPDATE statement assigns a password to all root - accounts: -shell> mysql -u root -mysql> UPDATE mysql.user SET Password = PASSWORD('newpwd') - -> WHERE User = 'root'; -mysql> FLUSH PRIVILEGES; - - The UPDATE statement applies both to Windows and to Unix. - - After the passwords have been set, you must supply the appropriate - password whenever you connect to the server. For example, if you - want to use mysqladmin to shut down the server, you can do so - using this command: -shell> mysqladmin -u root -p shutdown -Enter password: (enter root password here) - -Note - - If you forget your root password after setting it up, Section - B.5.4.1, "How to Reset the Root Password," covers the procedure - for resetting it. - - To set up additional accounts, you can use the GRANT statement. - For instructions, see Section 5.5.2, "Adding User Accounts." - -2.14. Environment Variables - - This section lists all the environment variables that are used - directly or indirectly by MySQL. Most of these can also be found - in other places in this manual. - - Note that any options on the command line take precedence over - values specified in option files and environment variables, and - values in option files take precedence over values in environment - variables. - - In many cases, it is preferable to use an option file instead of - environment variables to modify the behavior of MySQL. See Section - 4.2.3.3, "Using Option Files." - Variable Description - CXX The name of your C++ compiler (for running configure). - CC The name of your C compiler (for running configure). - CFLAGS Flags for your C compiler (for running configure). - CXXFLAGS Flags for your C++ compiler (for running configure). - DBI_USER The default user name for Perl DBI. - DBI_TRACE Trace options for Perl DBI. - HOME The default path for the mysql history file is - $HOME/.mysql_history. - LD_RUN_PATH Used to specify the location of libmysqlclient.so. - MYSQL_DEBUG Debug trace options when debugging. - MYSQL_GROUP_SUFFIX Option group suffix value (like specifying - --defaults-group-suffix). - MYSQL_HISTFILE The path to the mysql history file. If this - variable is set, its value overrides the default for - $HOME/.mysql_history. - MYSQL_HOME The path to the directory in which the server-specific - my.cnf file resides (as of MySQL 5.0.3). - MYSQL_HOST The default host name used by the mysql command-line - client. - MYSQL_PS1 The command prompt to use in the mysql command-line - client. - MYSQL_PWD The default password when connecting to mysqld. Note - that using this is insecure. See Section 5.3.2.2, "End-User - Guidelines for Password Security." - MYSQL_TCP_PORT The default TCP/IP port number. - MYSQL_UNIX_PORT The default Unix socket file name; used for - connections to localhost. - PATH Used by the shell to find MySQL programs. - TMPDIR The directory where temporary files are created. - TZ This should be set to your local time zone. See Section - B.5.4.6, "Time Zone Problems." - UMASK The user-file creation mode when creating files. See note - following table. - UMASK_DIR The user-directory creation mode when creating - directories. See note following table. - USER The default user name on Windows and NetWare used when - connecting to mysqld. - - The UMASK and UMASK_DIR variables, despite their names, are used - as modes, not masks: - - * If UMASK is set, mysqld uses ($UMASK | 0600) as the mode for - file creation, so that newly created files have a mode in the - range from 0600 to 0666 (all values octal). - - * If UMASK_DIR is set, mysqld uses ($UMASK_DIR | 0700) as the - base mode for directory creation, which then is AND-ed with - ~(~$UMASK & 0666), so that newly created directories have a - mode in the range from 0700 to 0777 (all values octal). The - AND operation may remove read and write permissions from the - directory mode, but not execute permissions. - - MySQL assumes that the value for UMASK or UMASK_DIR is in octal if - it starts with a zero. - -2.15. Perl Installation Notes - - Perl support for MySQL is provided by means of the DBI/DBD client - interface. The interface requires Perl 5.6.0, and 5.6.1 or later - is preferred. DBI does not work if you have an older version of - Perl. - - If you want to use transactions with Perl DBI, you need to have - DBD::mysql 2.0900. If you are using the MySQL 4.1 or newer client - library, you must use DBD::mysql 2.9003 or newer. Support for - server-side prepared statements requires DBD::mysql 3.0009 or - newer. - - Perl support is not included with MySQL distributions. You can - obtain the necessary modules from http://search.cpan.org for Unix, - or by using the ActiveState ppm program on Windows. The following - sections describe how to do this. - - Perl support for MySQL must be installed if you want to run the - MySQL benchmark scripts; see Section 7.1.3, "The MySQL Benchmark - Suite." It is also required for the MySQL Cluster ndb_size.pl - utility; see Section 17.4.21, "ndb_size.pl --- NDBCLUSTER Size - Requirement Estimator." - -2.15.1. Installing Perl on Unix - - MySQL Perl support requires that you have installed MySQL client - programming support (libraries and header files). Most - installation methods install the necessary files. However, if you - installed MySQL from RPM files on Linux, be sure that you've - installed the developer RPM. The client programs are in the client - RPM, but client programming support is in the developer RPM. - - If you want to install Perl support, the files you need can be - obtained from the CPAN (Comprehensive Perl Archive Network) at - http://search.cpan.org. - - The easiest way to install Perl modules on Unix is to use the CPAN - module. For example: -shell> perl -MCPAN -e shell -cpan> install DBI -cpan> install DBD::mysql - - The DBD::mysql installation runs a number of tests. These tests - attempt to connect to the local MySQL server using the default - user name and password. (The default user name is your login name - on Unix, and ODBC on Windows. The default password is "no - password.") If you cannot connect to the server with those values - (for example, if your account has a password), the tests fail. You - can use force install DBD::mysql to ignore the failed tests. - - DBI requires the Data::Dumper module. It may be installed; if not, - you should install it before installing DBI. - - It is also possible to download the module distributions in the - form of compressed tar archives and build the modules manually. - For example, to unpack and build a DBI distribution, use a - procedure such as this: - - 1. Unpack the distribution into the current directory: -shell> gunzip < DBI-VERSION.tar.gz | tar xvf - - This command creates a directory named DBI-VERSION. - - 2. Change location into the top-level directory of the unpacked - distribution: -shell> cd DBI-VERSION - - 3. Build the distribution and compile everything: -shell> perl Makefile.PL -shell> make -shell> make test -shell> make install - - The make test command is important because it verifies that the - module is working. Note that when you run that command during the - DBD::mysql installation to exercise the interface code, the MySQL - server must be running or the test fails. - - It is a good idea to rebuild and reinstall the DBD::mysql - distribution whenever you install a new release of MySQL, - particularly if you notice symptoms such as that all your DBI - scripts fail after you upgrade MySQL. - - If you do not have access rights to install Perl modules in the - system directory or if you want to install local Perl modules, the - following reference may be useful: - http://servers.digitaldaze.com/extensions/perl/modules.html#module - s - - Look under the heading "Installing New Modules that Require - Locally Installed Modules." - -2.15.2. Installing ActiveState Perl on Windows - - On Windows, you should do the following to install the MySQL DBD - module with ActiveState Perl: - - 1. Get ActiveState Perl from - http://www.activestate.com/Products/ActivePerl/ and install - it. - - 2. Open a console window (a "DOS window"). - - 3. If necessary, set the HTTP_proxy variable. For example, you - might try a setting like this: -set HTTP_proxy=my.proxy.com:3128 - - 4. Start the PPM program: -C:\> C:\perl\bin\ppm.pl - - 5. If you have not previously done so, install DBI: -ppm> install DBI - - 6. If this succeeds, run the following command: -ppm> install DBD-mysql - - This procedure should work with ActiveState Perl 5.6 or newer. - - If you cannot get the procedure to work, you should install the - MyODBC driver instead and connect to the MySQL server through - ODBC: -use DBI; -$dbh= DBI->connect("DBI:ODBC:$dsn",$user,$password) || - die "Got error $DBI::errstr when connecting to $dsn\n"; - -2.15.3. Problems Using the Perl DBI/DBD Interface - - If Perl reports that it cannot find the ../mysql/mysql.so module, - the problem is probably that Perl cannot locate the - libmysqlclient.so shared library. You should be able to fix this - problem by one of the following methods: - - * Compile the DBD::mysql distribution with perl Makefile.PL - -static -config rather than perl Makefile.PL. - - * Copy libmysqlclient.so to the directory where your other - shared libraries are located (probably /usr/lib or /lib). - - * Modify the -L options used to compile DBD::mysql to reflect - the actual location of libmysqlclient.so. - - * On Linux, you can add the path name of the directory where - libmysqlclient.so is located to the /etc/ld.so.conf file. - - * Add the path name of the directory where libmysqlclient.so is - located to the LD_RUN_PATH environment variable. Some systems - use LD_LIBRARY_PATH instead. - - Note that you may also need to modify the -L options if there are - other libraries that the linker fails to find. For example, if the - linker cannot find libc because it is in /lib and the link command - specifies -L/usr/lib, change the -L option to -L/lib or add -L/lib - to the existing link command. - - If you get the following errors from DBD::mysql, you are probably - using gcc (or using an old binary compiled with gcc): -/usr/bin/perl: can't resolve symbol '__moddi3' -/usr/bin/perl: can't resolve symbol '__divdi3' - - Add -L/usr/lib/gcc-lib/... -lgcc to the link command when the - mysql.so library gets built (check the output from make for - mysql.so when you compile the Perl client). The -L option should - specify the path name of the directory where libgcc.a is located - on your system. - - Another cause of this problem may be that Perl and MySQL are not - both compiled with gcc. In this case, you can solve the mismatch - by compiling both with gcc. - - You may see the following error from DBD::mysql when you run the - tests: -t/00base............install_driver(mysql) failed: -Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mys -ql: -../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: -uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 16 -9. - - This means that you need to include the -lz compression library on - the link line. That can be done by changing the following line in - the file lib/DBD/mysql/Install.pm: -$sysliblist .= " -lm"; - - Change that line to: -$sysliblist .= " -lm -lz"; - - After this, you must run make realclean and then proceed with the - installation from the beginning. - - If you want to install DBI on SCO, you have to edit the Makefile - in DBI-xxx and each subdirectory. Note that the following assumes - gcc 2.95.2 or newer: -OLD: NEW: -CC = cc CC = gcc -CCCDLFLAGS = -KPIC -W1,-Bexport CCCDLFLAGS = -fpic -CCDLFLAGS = -wl,-Bexport CCDLFLAGS = - -LD = ld LD = gcc -G -fpic -LDDLFLAGS = -G -L/usr/local/lib LDDLFLAGS = -L/usr/local/lib -LDFLAGS = -belf -L/usr/local/lib LDFLAGS = -L/usr/local/lib - -LD = ld LD = gcc -G -fpic -OPTIMISE = -Od OPTIMISE = -O1 - -OLD: -CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include - -NEW: -CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include - - These changes are necessary because the Perl dynaloader does not - load the DBI modules if they were compiled with icc or cc. - - If you want to use the Perl module on a system that does not - support dynamic linking (such as SCO), you can generate a static - version of Perl that includes DBI and DBD::mysql. The way this - works is that you generate a version of Perl with the DBI code - linked in and install it on top of your current Perl. Then you use - that to build a version of Perl that additionally has the DBD code - linked in, and install that. - - On SCO, you must have the following environment variables set: -LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib - - Or: -LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ - /usr/progressive/lib:/usr/skunk/lib -LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ - /usr/progressive/lib:/usr/skunk/lib -MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:\ - /usr/skunk/man: - - First, create a Perl that includes a statically linked DBI module - by running these commands in the directory where your DBI - distribution is located: -shell> perl Makefile.PL -static -config -shell> make -shell> make install -shell> make perl - - Then you must install the new Perl. The output of make perl - indicates the exact make command you need to execute to perform - the installation. On SCO, this is make -f Makefile.aperl inst_perl - MAP_TARGET=perl. - - Next, use the just-created Perl to create another Perl that also - includes a statically linked DBD::mysql by running these commands - in the directory where your DBD::mysql distribution is located: -shell> perl Makefile.PL -static -config -shell> make -shell> make install -shell> make perl - - Finally, you should install this new Perl. Again, the output of - make perl indicates the command to use. From 55da5f1fbf76057acfcab204de557c4d4eaf1956 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sat, 2 Mar 2013 12:23:08 +0200 Subject: [PATCH 047/294] References: lp:1136303 - adapting wsrep status variable usage according to wsrep provider version 2.2 behavior --- sql/sql_parse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 866d45ff701..08dafcc3a25 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2431,9 +2431,6 @@ mysql_execute_command(THD *thd) break; case SQLCOM_SHOW_STATUS: { -#ifdef WITH_WSREP - if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); -#endif /* WITH_WSREP */ execute_show_status(thd, all_tables); break; } @@ -5021,6 +5018,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) if (!thd->sent_row_count) status_var_increment(thd->status_var.empty_queries); status_var_add(thd->status_var.rows_sent, thd->sent_row_count); +#ifdef WITH_WSREP + if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); +#endif /* WITH_WSREP */ return res; } From 7ba8b2ae4933850c841a3dfa2bb4515aca6062be Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 3 Mar 2013 03:22:48 +0400 Subject: [PATCH 048/294] MDEV-4232 : percona.innodb_sys_index fails due to a wrong version_comment --- mysql-test/suite/percona/innodb_sys_index.result | 2 +- mysql-test/suite/percona/innodb_sys_index.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/percona/innodb_sys_index.result b/mysql-test/suite/percona/innodb_sys_index.result index 3dc1dcfebc8..756098d1127 100644 --- a/mysql-test/suite/percona/innodb_sys_index.result +++ b/mysql-test/suite/percona/innodb_sys_index.result @@ -3,7 +3,7 @@ Warnings: Note 1051 Unknown table 't1' select @@version_comment limit 1 ; @@version_comment -Source distribution, wsrep_X.Y.rZ +Source distribution, wsrep_ SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; CREATE TABLE test.t1 ( `a` SERIAL NOT NULL , `b` VARCHAR( 255 ) NOT NULL , INDEX ( `b` ) ) ENGINE = InnoDB ; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; diff --git a/mysql-test/suite/percona/innodb_sys_index.test b/mysql-test/suite/percona/innodb_sys_index.test index 9c6c83e029a..99d9e675148 100644 --- a/mysql-test/suite/percona/innodb_sys_index.test +++ b/mysql-test/suite/percona/innodb_sys_index.test @@ -5,7 +5,7 @@ drop table if exists t1; # # test for bug LP#875797 "Using 'innodb_sys_indexes' causes core dump" # ---replace_regex /wsrep_[0-9]+\.[a-zA-Z0-9]+\.r[0-9X]+/wsrep_X.Y.rZ/ +--replace_regex /wsrep_[0-9\.Xr]+/wsrep_/ select @@version_comment limit 1 ; --disable_result_log SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; From 4174f1a47437dff6614f01c75651b371d8fcb876 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 4 Mar 2013 23:01:36 +0200 Subject: [PATCH 049/294] References: MDEV-4211 - appended format description event for TOI replication write set, FD carries binlog checksum algorithm --- sql/sql_parse.cc | 11 ++++++++--- sql/wsrep_mysqld.cc | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 08dafcc3a25..89074ac9ad0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8073,7 +8073,7 @@ static inline wsrep_status_t wsrep_apply_rbr( char *buf= (char *)rbr_buf; int rcode= 0; int event= 1; - + Format_description_log_event *description_event = wsrep_format_desc; DBUG_ENTER("wsrep_apply_rbr"); if (thd->killed == KILL_CONNECTION) @@ -8100,7 +8100,7 @@ static inline wsrep_status_t wsrep_apply_rbr( { int exec_res; int error = 0; - Log_event* ev= wsrep_read_log_event(&buf, &buf_len, wsrep_format_desc); + Log_event* ev= wsrep_read_log_event(&buf, &buf_len, description_event); if (!ev) { @@ -8116,6 +8116,9 @@ static inline wsrep_status_t wsrep_apply_rbr( DBUG_ASSERT(buf_len != 0 || ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)); break; + case FORMAT_DESCRIPTION_EVENT: + description_event = (Format_description_log_event *)ev; + break; default: break; } @@ -8174,7 +8177,9 @@ static inline wsrep_status_t wsrep_apply_rbr( WSREP_ERROR("Error in %s event: commit of row events failed: %lld", ev->get_type_str(), (long long)thd->wsrep_trx_seqno); } - delete ev; + + if (description_event != ev) + delete ev; } error: diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9e1c84b897e..96c3879d443 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -976,6 +976,8 @@ int wsrep_to_buf_helper( return 1; Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); int ret(0); + wsrep_format_desc->checksum_alg = binlog_checksum_options; + wsrep_format_desc->write(&tmp_io_cache); if (ev.write(&tmp_io_cache)) ret= 1; if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; close_cached_file(&tmp_io_cache); From 972acdb16484ec6b533d7bc6fabeec32a9e6ecc3 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 5 Mar 2013 00:01:20 +0200 Subject: [PATCH 050/294] References: lp:1144911 - merged fix for prepared statement processing from upstream. Merged fix is revision 3853 in lp:~codership/codership-mysql/5.5-23 --- sql/sql_parse.cc | 159 ++++++++++++++++++++++++--------------------- sql/sql_prepare.cc | 20 +++++- 2 files changed, 105 insertions(+), 74 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 89074ac9ad0..117f23afb99 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6052,6 +6052,89 @@ void mysql_init_multi_delete(LEX *lex) } #ifdef WITH_WSREP +void wsrep_replay_transaction(THD *thd) +{ + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) + { + if (thd->wsrep_exec_mode!= REPL_RECV) + { + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); + + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); + + thd_proc_info(thd, "wsrep replaying trx"); + WSREP_DEBUG("replay trx: %s %lld", + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + int rcode = wsrep->replay_trx(wsrep, + &thd->wsrep_trx_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_wsrep_thd); + + switch (rcode) + { + case WSREP_OK: + thd->wsrep_conflict_state= NO_CONFLICT; + wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); + WSREP_DEBUG("trx_replay successful for: %ld %llu", + thd->thread_id, (long long)thd->real_id); + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + thd->wsrep_bf_thd = NULL; + wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + } +} + static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state) { @@ -6078,79 +6161,9 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, WSREP_DEBUG("abort in exec query state, avoiding autocommit"); } - /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) { - if (thd->wsrep_exec_mode!= REPL_RECV) { - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay issue, thd has reported status already"); - } - thd->stmt_da->reset_diagnostics_area(); - - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - mysql_reset_thd_for_next_command(thd, opt_userstat_running); - thd->killed= NOT_KILLED; - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%ld)", - thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); - - thd_proc_info(thd, "wsrep replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)thd->wsrep_trx_seqno); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_trx_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_wsrep_thd); - - switch (rcode) { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); - WSREP_DEBUG("trx_replay successful for: %ld %llu", - thd->thread_id, (long long)thd->real_id); - break; - case WSREP_TRX_FAIL: - if (thd->stmt_da->is_sent) { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - } - thd->wsrep_conflict_state= ABORTED; - thd->wsrep_bf_thd = NULL; - wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, query: %s", - rcode, thd->query() ? thd->query() : "void"); - /* we're now in inconsistent state, must abort */ - unireg_abort(1); - break; - } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } + if (thd->wsrep_conflict_state== MUST_REPLAY) + { + wsrep_replay_transaction(thd); } /* setting error code for BF aborted trxs */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c1f07581106..10aa1ccec26 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3483,7 +3483,9 @@ Prepared_statement::set_parameters(String *expanded_query, return res; } - +#ifdef WITH_WSREP +void wsrep_replay_transaction(THD *thd); +#endif /* WITH_WSREP */ /** Execute a prepared statement. Re-prepare it a limited number of times if necessary. @@ -3563,6 +3565,22 @@ reexecute: error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + switch (thd->wsrep_conflict_state) + { + case CERT_FAILURE: + WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %ld err: %d", + thd->thread_id, thd->stmt_da->sql_errno() ); + thd->wsrep_conflict_state = NO_CONFLICT; + break; + + case MUST_REPLAY: + (void)wsrep_replay_transaction(thd); + default: break; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ if (error && !thd->is_fatal_error && !thd->killed && reprepare_observer.is_invalidated() && From 3e841b77e0b683bcf16546eeef8c286150ed2b6f Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 26 Mar 2013 16:40:02 +0200 Subject: [PATCH 051/294] References: MDEV-4328 - avoiding race condition for wsrep_format_desc access --- sql/wsrep_mysqld.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 96c3879d443..e653d790747 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -976,8 +976,12 @@ int wsrep_to_buf_helper( return 1; Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); int ret(0); - wsrep_format_desc->checksum_alg = binlog_checksum_options; - wsrep_format_desc->write(&tmp_io_cache); + + Format_description_log_event *tmp_fd = new Format_description_log_event(4); + tmp_fd->checksum_alg = binlog_checksum_options; + tmp_fd->write(&tmp_io_cache); + delete tmp_fd; + if (ev.write(&tmp_io_cache)) ret= 1; if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; close_cached_file(&tmp_io_cache); From e95fdb74ab85bf24b805c1d4ead8c3d3a791b79a Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 21 May 2013 00:10:35 +0300 Subject: [PATCH 052/294] merged in revisions 3853..3857 from lp:codership-mysql/5.5-23 --- scripts/mysqld_safe.sh | 50 ++++++++++++++++++--------- scripts/wsrep_sst_rsync.sh | 11 +++--- sql/wsrep_hton.cc | 5 +++ storage/innobase/handler/ha_innodb.cc | 1 + storage/innobase/include/srv0srv.h | 8 +++++ storage/innobase/include/trx0trx.h | 3 ++ storage/innobase/srv/srv0srv.c | 33 ++++++++++++++++++ storage/innobase/trx/trx0trx.c | 3 ++ storage/xtradb/handler/ha_innodb.cc | 1 + storage/xtradb/include/srv0srv.h | 8 +++++ storage/xtradb/include/trx0trx.h | 3 ++ storage/xtradb/srv/srv0srv.c | 33 ++++++++++++++++++ storage/xtradb/trx/trx0trx.c | 3 ++ 13 files changed, 140 insertions(+), 22 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 0bd49af876e..bbe12db35f3 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -214,29 +214,39 @@ wsrep_pick_url() { # Run mysqld with --wsrep-recover and parse recovered position from log. # Position will be stored in wsrep_start_position_opt global. -wsrep_recovery() { +wsrep_start_position_opt="" +wsrep_recover_position() { local mysqld_cmd="$@" - wr_logfile=$(mktemp) - [ "$EUID" = "0" ] && chown $user $wr_logfile + local wr_logfile=$(mktemp) + local euid=$(id -u) + local ret=0 + + [ "$euid" = "0" ] && chown $user $wr_logfile chmod 600 $wr_logfile + log_notice "WSREP: Running position recovery with --log_error=$wr_logfile" + $mysqld_cmd --log_error=$wr_logfile --wsrep-recover - rp=$(grep "WSREP: Recovered position:" $wr_logfile) + + local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" if [ -z "$rp" ]; then - skipped=$(grep WSREP $wr_logfile | grep "skipping position recovery") + local skipped="$(grep WSREP $wr_logfile | grep 'skipping position recovery')" if [ -z "$skipped" ]; then - log_error "WSREP: Failed to recover position: " \ - `cat $wr_logfile`; + log_error "WSREP: Failed to recover position: " `cat $wr_logfile`; + ret=1 else log_notice "WSREP: Position recovery skipped" fi else - start_pos=$(echo $rp | sed 's/.*WSREP\:\ Recovered\ position://' \ - | sed 's/^[ \t]*//') - wsrep_start_position_opt="--wsrep_start_position=$start_pos" + local start_pos="$(echo $rp | sed 's/.*WSREP\:\ Recovered\ position://' \ + | sed 's/^[ \t]*//')" log_notice "WSREP: Recovered position $start_pos" + wsrep_start_position_opt="--wsrep_start_position=$start_pos" fi + rm $wr_logfile + + return $ret } parse_arguments() { @@ -303,9 +313,9 @@ parse_arguments() { --wsrep[-_]provider=*) if test -n "$val" && test "$val" != "none" then - wsrep_restart=1 - fi - ;; + wsrep_restart=1 + fi + ;; --help) usage ;; *) @@ -864,20 +874,26 @@ have_sleep=1 # maximum number of wsrep restarts max_wsrep_restarts=0 +# maximum number of wsrep restarts +max_wsrep_restarts=0 + while true do rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety - [ -n "$wsrep_urls" ] && url=`wsrep_pick_url $wsrep_urls` # check connect address - start_time=`date +%M%S` + # this sets wsrep_start_position_opt + wsrep_recover_position "$cmd" + + [ $? -ne 0 ] && exit 1 # + + [ -n "$wsrep_urls" ] && url=`wsrep_pick_url $wsrep_urls` # check connect address + if [ -z "$url" ] then - wsrep_recovery "$cmd" eval_log_error "$cmd $wsrep_start_position_opt $nohup_redir" else - wsrep_recovery "$cmd" eval_log_error "$cmd $wsrep_start_position_opt --wsrep_cluster_address=$url $nohup_redir" fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index d510477535c..7cbfd8cbcdb 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -89,14 +89,14 @@ then # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') # New filter - exclude everything except dirs (schemas) and innodb files - FILTER=(-f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') + FILTER=(-f '- lost+found' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') RC=0 rsync --archive --no-times --ignore-times --inplace --delete --quiet \ $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA" \ rsync://$WSREP_SST_OPT_ADDR || RC=$? - [ $RC -ne 0 ] && echo "rsync returned code $RC:" >> /dev/stderr + [ $RC -ne 0 ] && wsrep_log_error "rsync returned code $RC:" case $RC in 0) RC=0 # Success @@ -136,7 +136,7 @@ then if check_pid $RSYNC_PID then - echo "rsync daemon already running." + wsrep_log_error "rsync daemon already running." exit 114 # EALREADY fi rm -rf "$RSYNC_PID" @@ -189,7 +189,8 @@ EOF if ! ps -p $MYSQLD_PID >/dev/null then - echo "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." >&2 + wsrep_log_error \ + "Parent mysqld process (PID:$MYSQLD_PID) terminated unexpectedly." exit 32 fi @@ -203,7 +204,7 @@ EOF # cleanup_joiner else - echo "Unrecognized role: '$WSREP_SST_OPT_ROLE'" + wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'" exit 22 # EINVAL fi diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 0e013556f45..576e6b8ad47 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -178,6 +178,7 @@ int wsrep_commit(handlerton *hton, THD *thd, bool all) extern Rpl_filter* binlog_filter; extern my_bool opt_log_slave_updates; +extern void wsrep_write_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); enum wsrep_trx_status wsrep_run_wsrep_commit( THD *thd, handlerton *hton, bool all) @@ -337,6 +338,10 @@ wsrep_run_wsrep_commit( (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, &thd->wsrep_trx_seqno); if (rcode == WSREP_TRX_MISSING) { + WSREP_WARN("Transaction missing in provider, thd: %ld, SQL: %s", + thd->thread_id, thd->query()); + wsrep_write_rbr_buf(thd, rbr_data, data_len); + rcode = WSREP_OK; } else if (rcode == WSREP_BF_ABORT) { mysql_mutex_lock(&thd->LOCK_wsrep_thd); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1b211ab4226..f54098814b8 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12626,6 +12626,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, int rcode = wsrep_innobase_kill_one_trx( bf_thd, bf_trx, victim_trx, signal); mutex_exit(&kernel_mutex); + wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { WSREP_DEBUG("victim does not have transaction"); diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 093be2a6dcb..91151312367 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -566,6 +566,14 @@ srv_conc_enter_innodb( /*==================*/ trx_t* trx); /*!< in: transaction object associated with the thread */ +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx); /*!< in: transaction object associated with the + thread */ +#endif /* WITH_WSREP */ /*********************************************************************//** This lets a thread enter InnoDB regardless of the number of threads inside InnoDB. This must be called when a thread ends a lock wait. */ diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 7572c766301..40474344cff 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -729,6 +729,9 @@ struct trx_struct{ /*------------------------------*/ char detailed_error[256]; /*!< detailed error message for last error, or empty. */ +#ifdef WITH_WSREP + os_event_t wsrep_event; /* event waited for in srv_conc_slot */ +#endif /* WITH_WSREP */ }; #define TRX_MAX_N_THREADS 32 /* maximum number of diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 57046ff644c..dfa5a683acf 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1148,6 +1148,23 @@ srv_general_init(void) /* Maximum allowable purge history length. <=0 means 'infinite'. */ UNIV_INTERN ulong srv_max_purge_lag = 0; +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx) /*!< in: transaction object associated with the + thread */ +{ + os_fast_mutex_lock(&srv_conc_mutex); + if (trx->wsrep_event) { + if (wsrep_debug) + fprintf(stderr, "WSREP: conc slot cancel\n"); + os_event_set(trx->wsrep_event); + } + os_fast_mutex_unlock(&srv_conc_mutex); +} +#endif /* WITH_WSREP */ /*********************************************************************//** Puts an OS thread to wait if there are too many concurrent threads (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ @@ -1299,6 +1316,19 @@ retry: srv_conc_n_waiting_threads++; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_n_waiting_threads--; + os_fast_mutex_unlock(&srv_conc_mutex); + if (wsrep_debug) + fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); + trx->declared_to_be_inside_innodb = TRUE; + trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; + return; + } + trx->wsrep_event = slot->event; +#endif /* WITH_WSREP */ os_fast_mutex_unlock(&srv_conc_mutex); /* Go to wait for the event; when a thread leaves InnoDB it will @@ -1313,6 +1343,9 @@ retry: thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); os_event_wait(slot->event); thd_wait_end(trx->mysql_thd); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ trx->op_info = ""; diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 23cac1e11db..42c326fc3e0 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -193,6 +193,9 @@ trx_create( /* Remember to free the vector explicitly. */ trx->autoinc_locks = ib_vector_create( mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ return(trx); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index fc68878d860..7b96c18d835 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13752,6 +13752,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, signal); mutex_exit(&kernel_mutex); + wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { WSREP_DEBUG("victim does not have transaction"); diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index e125d1c3853..6f0b53ef2ba 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -635,6 +635,14 @@ srv_conc_enter_innodb( /*==================*/ trx_t* trx); /*!< in: transaction object associated with the thread */ +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx); /*!< in: transaction object associated with the + thread */ +#endif /* WITH_WSREP */ /*********************************************************************//** This lets a thread enter InnoDB regardless of the number of threads inside InnoDB. This must be called when a thread ends a lock wait. */ diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index eded5c303fa..2a08fdf442b 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -747,6 +747,9 @@ struct trx_struct{ /*------------------------------*/ char detailed_error[256]; /*!< detailed error message for last error, or empty. */ +#ifdef WITH_WSREP + os_event_t wsrep_event; /* event waited for in srv_conc_slot */ +#endif /* WITH_WSREP */ /*------------------------------*/ ulint io_reads; ib_uint64_t io_read; diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index c46977e4812..ee03c6b050d 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -1234,6 +1234,23 @@ srv_general_init(void) /* Maximum allowable purge history length. <=0 means 'infinite'. */ UNIV_INTERN ulong srv_max_purge_lag = 0; +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx) /*!< in: transaction object associated with the + thread */ +{ + os_fast_mutex_lock(&srv_conc_mutex); + if (trx->wsrep_event) { + if (wsrep_debug) + fprintf(stderr, "WSREP: conc slot cancel\n"); + os_event_set(trx->wsrep_event); + } + os_fast_mutex_unlock(&srv_conc_mutex); +} +#endif /* WITH_WSREP */ /*********************************************************************//** Puts an OS thread to wait if there are too many concurrent threads (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ @@ -1466,6 +1483,19 @@ retry: srv_conc_n_waiting_threads++; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_n_waiting_threads--; + os_fast_mutex_unlock(&srv_conc_mutex); + if (wsrep_debug) + fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); + trx->declared_to_be_inside_innodb = TRUE; + trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; + return; + } + trx->wsrep_event = slot->event; +#endif /* WITH_WSREP */ os_fast_mutex_unlock(&srv_conc_mutex); /* Go to wait for the event; when a thread leaves InnoDB it will @@ -1488,6 +1518,9 @@ retry: thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); os_event_wait(slot->event); thd_wait_end(trx->mysql_thd); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ trx->op_info = ""; diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index 521fc96d35c..e6c72c09184 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -211,6 +211,9 @@ trx_create( /* Remember to free the vector explicitly. */ trx->autoinc_locks = ib_vector_create( mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ return(trx); } From 9d1546fe2cdced5efb4af831fa2e560b7f80fb54 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sat, 25 May 2013 12:22:57 +0300 Subject: [PATCH 053/294] References: MDEV-4572 - merge with lp:codership-mysql/5.5-23 revisions 3858..3867 --- scripts/mysqld_safe.sh | 2 +- scripts/wsrep_sst_common.sh | 2 +- scripts/wsrep_sst_mysqldump.sh | 14 +++++++------- scripts/wsrep_sst_rsync.sh | 2 +- scripts/wsrep_sst_xtrabackup.sh | 11 ++--------- sql/sql_admin.cc | 3 +++ sql/sql_insert.cc | 15 ++++++++++++++- sql/wsrep_hton.cc | 1 + sql/wsrep_sst.cc | 2 +- sql/wsrep_utils.cc | 6 ++---- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/lock/lock0lock.c | 5 +++++ storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/lock/lock0lock.c | 5 +++++ 14 files changed, 45 insertions(+), 27 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 09524fedcc0..7db2a5605e1 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -227,7 +227,7 @@ wsrep_recover_position() { log_notice "WSREP: Running position recovery with --log_error=$wr_logfile" - $mysqld_cmd --log_error=$wr_logfile --wsrep-recover + eval_log_error $mysqld_cmd --log_error=$wr_logfile --wsrep-recover local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" if [ -z "$rp" ]; then diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 5c292465ecc..017f4877fd6 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -91,7 +91,7 @@ wsrep_log() # echo everything to stderr so that it gets into common error log # deliberately made to look different from the rest of the log local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" - echo "WSREP_SST: $* ($tst)" >>/dev/stderr + echo "WSREP_SST: $* ($tst)" >&2 } wsrep_log_error() diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 120533edc4e..4434792240d 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -38,12 +38,12 @@ local_ip() return 1 } -if test -z "$WSREP_SST_OPT_USER"; then err "USER cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_HOST"; then err "HOST cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_PORT"; then err "PORT cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_LPORT"; then err "LPORT cannot be nil"; exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_SOCKET";then err "SOCKET cannot be nil";exit $EINVAL; fi -if test -z "$WSREP_SST_OPT_GTID"; then err "GTID cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_USER"; then wsrep_log_error "USER cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_HOST"; then wsrep_log_error "HOST cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_PORT"; then wsrep_log_error "PORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_LPORT"; then wsrep_log_error "LPORT cannot be nil"; exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_SOCKET";then wsrep_log_error "SOCKET cannot be nil";exit $EINVAL; fi +if test -z "$WSREP_SST_OPT_GTID"; then wsrep_log_error "GTID cannot be nil"; exit $EINVAL; fi if local_ip $WSREP_SST_OPT_HOST && \ [ "$WSREP_SST_OPT_PORT" = "$WSREP_SST_OPT_LPORT" ] @@ -57,7 +57,7 @@ fi if ! mysql --version | grep 'Distrib 5.5' >/dev/null then mysql --version >&2 - err "this operation requires MySQL client version 5.5.x" + wsrep_log_error "this operation requires MySQL client version 5.5.x" exit $EINVAL fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 7cbfd8cbcdb..583d70fda5e 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -32,7 +32,7 @@ cleanup_joiner() rm -rf "$RSYNC_CONF" rm -rf "$MAGIC_FILE" rm -rf "$RSYNC_PID" - echo " done." >&2 + wsrep_log_info "Joiner cleanup done." } check_pid() diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 08cd221c2a2..f9bddd7bd4e 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -98,16 +98,9 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then - TMPDIR=${TMPDIR:-""} - if [ -z "${TMPDIR}" ]; then - # try to get it from my.cnf - TMPDIR=$(grep -E '^\s*tmpdir' $WSREP_SST_OPT_CONF | \ - awk -F = '{ print $2 }' | sed 's/^\s//g' | sed 's/\s.*//g' ) - # if failed default to /tmp - [ -z "${TMPDIR}" ] && TMPDIR="/tmp" - fi + TMPDIR=${TMPDIR:-"/tmp"} - INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar + INNOBACKUPEX_ARGS="--galera-info --stream=tar --defaults-file=${WSREP_SST_OPT_CONF} --socket=${WSREP_SST_OPT_SOCKET}" diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 4414a077df8..c68d4dc16a4 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1073,6 +1073,8 @@ bool Optimize_table_statement::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? mysql_recreate_table(thd, first_table) : mysql_admin_table(thd, first_table, &m_lex->check_opt, @@ -1104,6 +1106,7 @@ bool Repair_table_statement::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair", TL_WRITE, 1, test(m_lex->check_opt.sql_flags & TT_USEFRM), diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d374244a205..4f080235069 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3658,7 +3658,8 @@ bool select_insert::send_eof() trans_table, table->file->table_type())); #ifdef WITH_WSREP - error= (thd->wsrep_conflict_state == MUST_ABORT) ? -1 : + error= (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); #else @@ -4249,6 +4250,18 @@ bool select_create::send_eof() { trans_commit_stmt(thd); trans_commit_implicit(thd); +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state != NO_CONFLICT) + { + WSREP_DEBUG("select_create commit failed, thd: %lu err: %d %s", + thd->thread_id, thd->wsrep_conflict_state, thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + abort_result_set(); + return TRUE; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ } table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 576e6b8ad47..8b682d579d8 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -321,6 +321,7 @@ wsrep_run_wsrep_commit( { 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_trx_handle.trx_id) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 597d0ea087d..5aca1de6d0e 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -937,7 +937,7 @@ static int sst_donate_other (const char* method, { WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)", ret, strerror(ret)); - return ret; + return -ret; } mysql_cond_wait (&arg.cond, &arg.lock); diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index daba0e4cab2..392fb65d82c 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -353,10 +353,8 @@ size_t guess_ip (char* buf, size_t buf_len) // try to find the address of the first one #if (TARGET_OS_LINUX == 1) - const char cmd[] = "/sbin/ifconfig | " -// "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "grep -E '^[[:space:]]+inet addr:' | grep -m1 -v 'inet addr:127' | " - "sed 's/:/ /' | awk '{ print $3 }'"; + const char cmd[] = "ip addr show | grep -E '^\\s*inet' | grep -m1 global |" + " awk '{ print $2 }' | sed 's/\\/.*//'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3ed744382c7..f0ae2ff9f86 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4513,7 +4513,7 @@ wsrep_innobase_mysql_sort( memcpy(tmp_str, str, str_length); tmp_length = charset->coll->strnxfrm(charset, str, str_length, - tmp_str, tmp_length); + tmp_str, str_length); DBUG_ASSERT(tmp_length == str_length); break; diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 4791100f555..853e65c8573 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -5666,6 +5666,11 @@ lock_rec_convert_impl_to_expl( implicit lock. Because cannot lock at this moment.*/ if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) +#ifdef WITH_WSREP + && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + /* BF-BF conflict is possible if advancing into + lock_rec_other_has_conflicting*/ +#endif /* WITH_WSREP */ && lock_rec_other_has_conflicting( LOCK_X | LOCK_REC_NOT_GAP, block, heap_no, impl_trx)) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 02ee941351e..a0f953a41f4 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5176,7 +5176,7 @@ wsrep_innobase_mysql_sort( memcpy(tmp_str, str, str_length); tmp_length = charset->coll->strnxfrm(charset, str, str_length, - tmp_str, tmp_length); + tmp_str, str_length); DBUG_ASSERT(tmp_length == str_length); break; diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 3d97def3750..a38656200db 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -5691,6 +5691,11 @@ lock_rec_convert_impl_to_expl( implicit lock. Because cannot lock at this moment.*/ if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) +#ifdef WITH_WSREP + && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + /* BF-BF conflict is possible if advancing into + lock_rec_other_has_conflicting*/ +#endif /* WITH_WSREP */ && lock_rec_other_has_conflicting( LOCK_X | LOCK_REC_NOT_GAP, block, heap_no, impl_trx)) { From 24fd60895bb57918247f7e01d977223207a95319 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 27 May 2013 22:51:22 +0300 Subject: [PATCH 054/294] References lp:1012138 - merged fix from lp:codership-mysql --- sql/wsrep_var.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index c79c0a6a19f..b051254f3ff 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -286,6 +286,7 @@ bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) if (ret != WSREP_OK) { WSREP_ERROR("Set options returned %d", ret); + refresh_provider_options(); return true; } return refresh_provider_options(); From f37231cf46a8586c96462bee63ae3726961d7f1c Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 27 May 2013 23:03:08 +0300 Subject: [PATCH 055/294] References: MDEV-3924 lp:1088267 - merged fix from lp:codership-mysql --- sql/sql_parse.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0765138c1c9..c8be6be541f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7205,8 +7205,14 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal) 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_brute_force((void *)tmp)) +#else if ((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) +#endif /* WITH_WSREP */ { tmp->awake(kill_signal); error=0; From 7e0db6be56dd8f5f4343ebfe4d3c7ac225f38a01 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 12 Jun 2013 17:07:48 +0500 Subject: [PATCH 056/294] MDEV-4600 mariadb-galera-server-5.5 on ubuntu has no dependency to galera while debian has. dependency on galera added to the Ubuntu packaging script. --- debian/dist/Ubuntu/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index d1cf8531932..7234fdb8bfb 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -15,7 +15,7 @@ Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}) +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=23.2) Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mariadb-galera-server, mysql-server, virtual-mysql-server Conflicts: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, From 71509626d2ef792ace47faccbbfff9a294648411 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 13 Jun 2013 09:44:34 +0300 Subject: [PATCH 057/294] References: lp:1187526 - merged fix from wsrep-5.5-23 --- storage/innobase/handler/ha_innodb.cc | 9 ++++----- storage/xtradb/handler/ha_innodb.cc | 21 ++++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 89682a714a6..af52be63e20 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2760,10 +2760,6 @@ innobase_commit_low( /*================*/ trx_t* trx) /*!< in: transaction handle */ { - if (trx_is_started(trx)) { - - trx_commit_for_mysql(trx); - } #ifdef WITH_WSREP THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; @@ -2781,7 +2777,10 @@ innobase_commit_low( #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ - trx_commit_for_mysql(trx); + if (trx_is_started(trx)) { + + trx_commit_for_mysql(trx); + } #ifdef WITH_WSREP if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } #endif /* WITH_WSREP */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 373fd0bc01c..29efd7d237c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -3375,16 +3375,6 @@ innobase_commit_low( /*================*/ trx_t* trx) /*!< in: transaction handle */ { - if (trx_is_started(trx)) { - - /* Save the current replication position for write to trx sys - header for undo purposes, see the comment at corresponding call - at innobase_xa_prepare(). */ - - innobase_copy_repl_coords_to_trx((THD *) trx->mysql_thd, trx); - - trx_commit_for_mysql(trx); - } #ifdef WITH_WSREP THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; @@ -3402,7 +3392,16 @@ innobase_commit_low( #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ - trx_commit_for_mysql(trx); + if (trx_is_started(trx)) { + + /* Save the current replication position for write to trx sys + header for undo purposes, see the comment at corresponding call + at innobase_xa_prepare(). */ + + innobase_copy_repl_coords_to_trx((THD *) trx->mysql_thd, trx); + + trx_commit_for_mysql(trx); + } #ifdef WITH_WSREP if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } #endif /* WITH_WSREP */ From bf9d5b7f64f6e1c8b679dc941d7d1537cfccee65 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 13 Jun 2013 09:49:48 +0300 Subject: [PATCH 058/294] References: lp:1134892 MDEV-4624 - merged fix from LP wsrep-5.5-23 --- storage/innobase/handler/ha_innodb.cc | 1 + storage/innobase/row/row0ins.c | 22 ++++---- storage/innobase/row/row0upd.c | 72 +++++++++++++++++++++++---- storage/xtradb/handler/ha_innodb.cc | 1 + storage/xtradb/row/row0ins.c | 22 ++++---- storage/xtradb/row/row0upd.c | 72 +++++++++++++++++++++++---- 6 files changed, 152 insertions(+), 38 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index af52be63e20..bf47908282c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7224,6 +7224,7 @@ wsrep_append_foreign_key( foreign->foreign_table->name) : foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); +#define WSREP_DEBUG_PRINT #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index f5d387191ac..a8d6699c31e 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1077,19 +1077,21 @@ row_ins_foreign_check_on_constraint( cascade->state = UPD_NODE_UPDATE_CLUSTERED; +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, FALSE); + if (err != DB_SUCCESS) { + fprintf(stderr, + "WSREP: foreign key append failed: %lu\n", err); + } else +#endif err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); -#ifdef WITH_WSREP - if (err == DB_SUCCESS) { - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - clust_rec, - clust_index, - FALSE, FALSE); - } -#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 0368fd68d78..ba0a70d2c48 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -174,13 +174,47 @@ func_exit: } #ifdef WITH_WSREP -ulint wsrep_append_foreign_key(trx_t *trx, - dict_foreign_t* foreign, - const rec_t* clust_rec, - dict_index_t* clust_index, - ibool referenced, - ibool shared); +static +ibool +wsrep_row_upd_index_is_foreign( +/*========================*/ + dict_index_t* index, /*!< in: index */ + trx_t* trx) /*!< in: transaction */ +{ + dict_table_t* table = index->table; + dict_foreign_t* foreign; + ibool froze_data_dict = FALSE; + ibool is_referenced = FALSE; + if (!UT_LIST_GET_FIRST(table->foreign_list)) { + + return(FALSE); + } + + if (trx->dict_operation_lock_mode == 0) { + row_mysql_freeze_data_dictionary(trx); + froze_data_dict = TRUE; + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + if (foreign->foreign_index == index) { + + is_referenced = TRUE; + goto func_exit; + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + +func_exit: + if (froze_data_dict) { + row_mysql_unfreeze_data_dictionary(trx); + } + + return(is_referenced); +} #endif /* WITH_WSREP */ /*********************************************************************//** @@ -1757,6 +1791,9 @@ row_upd_sec_index_entry( if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { +#ifdef WITH_WSREP + que_node_t *parent = que_node_get_parent(node); +#endif /* WITH_WSREP */ err = btr_cur_del_mark_set_sec_rec( 0, btr_cur, TRUE, thr, &mtr); @@ -1775,7 +1812,11 @@ row_upd_sec_index_entry( index, offsets, thr, &mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced) { + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + wsrep_row_upd_index_is_foreign(index, trx) + ) { ulint* offsets = rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, @@ -1966,6 +2007,9 @@ row_upd_clust_rec_by_insert( rec_t* rec; ulint* offsets = NULL; +#ifdef WITH_WSREP + que_node_t *parent = que_node_get_parent(node); +#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2043,7 +2087,11 @@ err_exit: } } #ifdef WITH_WSREP - if (!referenced) { + if (!referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + wsrep_row_upd_index_is_foreign(index, trx) + ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); switch (err) { @@ -2270,6 +2318,7 @@ row_upd_del_mark_clust_rec( ulint err; #ifdef WITH_WSREP rec_t* rec; + que_node_t *parent = que_node_get_parent(node); #endif /* WITH_WSREP */ ut_ad(node); @@ -2305,7 +2354,12 @@ row_upd_del_mark_clust_rec( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced) { + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + thr_get_trx(thr) && + wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)) + ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); switch (err) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 29efd7d237c..c93f031ff71 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8187,6 +8187,7 @@ wsrep_append_foreign_key( foreign->foreign_table->name) : foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); +#define WSREP_DEBUG_PRINT #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 925446e4722..f50f7916813 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1077,19 +1077,21 @@ row_ins_foreign_check_on_constraint( cascade->state = UPD_NODE_UPDATE_CLUSTERED; +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, FALSE); + if (err != DB_SUCCESS) { + fprintf(stderr, + "WSREP: foreign key append failed: %lu\n", err); + } else +#endif err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); -#ifdef WITH_WSREP - if (err == DB_SUCCESS) { - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - clust_rec, - clust_index, - FALSE, FALSE); - } -#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 7d8e63f0058..ff63a8801ce 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -174,13 +174,47 @@ func_exit: } #ifdef WITH_WSREP -ulint wsrep_append_foreign_key(trx_t *trx, - dict_foreign_t* foreign, - const rec_t* clust_rec, - dict_index_t* clust_index, - ibool referenced, - ibool shared); +static +ibool +wsrep_row_upd_index_is_foreign( +/*========================*/ + dict_index_t* index, /*!< in: index */ + trx_t* trx) /*!< in: transaction */ +{ + dict_table_t* table = index->table; + dict_foreign_t* foreign; + ibool froze_data_dict = FALSE; + ibool is_referenced = FALSE; + if (!UT_LIST_GET_FIRST(table->foreign_list)) { + + return(FALSE); + } + + if (trx->dict_operation_lock_mode == 0) { + row_mysql_freeze_data_dictionary(trx); + froze_data_dict = TRUE; + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + if (foreign->foreign_index == index) { + + is_referenced = TRUE; + goto func_exit; + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + +func_exit: + if (froze_data_dict) { + row_mysql_unfreeze_data_dictionary(trx); + } + + return(is_referenced); +} #endif /* WITH_WSREP */ /*********************************************************************//** @@ -1776,6 +1810,9 @@ row_upd_sec_index_entry( if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { +#ifdef WITH_WSREP + que_node_t *parent = que_node_get_parent(node); +#endif /* WITH_WSREP */ err = btr_cur_del_mark_set_sec_rec( 0, btr_cur, TRUE, thr, &mtr); @@ -1794,7 +1831,11 @@ row_upd_sec_index_entry( index, offsets, thr, &mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced) { + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + wsrep_row_upd_index_is_foreign(index, trx) + ) { ulint* offsets = rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, @@ -1985,6 +2026,9 @@ row_upd_clust_rec_by_insert( rec_t* rec; ulint* offsets = NULL; +#ifdef WITH_WSREP + que_node_t *parent = que_node_get_parent(node); +#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2064,7 +2108,11 @@ err_exit: } } #ifdef WITH_WSREP - if (!referenced) { + if (!referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + wsrep_row_upd_index_is_foreign(index, trx) + ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); switch (err) { @@ -2296,6 +2344,7 @@ row_upd_del_mark_clust_rec( ulint err; #ifdef WITH_WSREP rec_t* rec; + que_node_t *parent = que_node_get_parent(node); #endif /* WITH_WSREP */ ut_ad(node); @@ -2331,7 +2380,12 @@ row_upd_del_mark_clust_rec( node, pcur, index->table, index, offsets, thr, mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced) { + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + thr_get_trx(thr) && + wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)) + ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); switch (err) { From b0d30e234efeddd4b1ee62e89b510b5d64a5ec07 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 13 Jun 2013 09:55:28 +0300 Subject: [PATCH 059/294] References lp:1169326 - merged fix from LP wsrep-5.5-23 Now at revision 3874 in lp:~codership/codership-mysql/5.5-23 --- sql/log_event.cc | 29 +++++++++++++++++++++++++++++ sql/slave.cc | 17 ----------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 21c6a64df90..cc18e1925cf 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4042,6 +4042,21 @@ Query_log_event::do_shall_skip(Relay_log_info *rli) DBUG_RETURN(Log_event::EVENT_SKIP_COUNT); } } +#ifdef WITH_WSREP + else if (wsrep_mysql_replication_bundle && WSREP_ON && thd->wsrep_mysql_replicated > 0 && + (!strncasecmp(query , "BEGIN", 5) || !strncasecmp(query , "COMMIT", 6))) + { + if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) + { + WSREP_DEBUG("skipping wsrep commit %d", thd->wsrep_mysql_replicated); + DBUG_RETURN(Log_event::EVENT_SKIP_IGNORE); + } + else + { + thd->wsrep_mysql_replicated = 0; + } + } +#endif DBUG_RETURN(Log_event::do_shall_skip(rli)); } @@ -6200,6 +6215,20 @@ Xid_log_event::do_shall_skip(Relay_log_info *rli) thd->variables.option_bits&= ~OPTION_BEGIN; DBUG_RETURN(Log_event::EVENT_SKIP_COUNT); } +#ifdef WITH_WSREP + else if (wsrep_mysql_replication_bundle && WSREP_ON) + { + if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) + { + WSREP_DEBUG("skipping wsrep commit %d", thd->wsrep_mysql_replicated); + DBUG_RETURN(Log_event::EVENT_SKIP_IGNORE); + } + else + { + thd->wsrep_mysql_replicated = 0; + } + } +#endif DBUG_RETURN(Log_event::do_shall_skip(rli)); } #endif /* !MYSQL_CLIENT */ diff --git a/sql/slave.cc b/sql/slave.cc index caef5acd5f1..c89ae69698f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2602,23 +2602,6 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) ev->thd = thd; // because up to this point, ev->thd == 0 int reason= ev->shall_skip(rli); -#ifdef WITH_WSREP - if (WSREP_ON && (ev->get_type_code() == XID_EVENT || - (ev->get_type_code() == QUERY_EVENT && thd->wsrep_mysql_replicated > 0 && - (!strncasecmp(((Query_log_event*)ev)->query , "BEGIN", 5) || - !strncasecmp(((Query_log_event*)ev)->query , "COMMIT", 6) )))) - { - if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) - { - WSREP_DEBUG("skipping wsrep commit %d", thd->wsrep_mysql_replicated); - reason = Log_event::EVENT_SKIP_IGNORE; - } - else - { - thd->wsrep_mysql_replicated = 0; - } - } -#endif if (reason == Log_event::EVENT_SKIP_COUNT) sql_slave_skip_counter= --rli->slave_skip_counter; mysql_mutex_unlock(&rli->data_lock); From 4107af8810c49dcf17ade88342179594eb1ca040 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 13 Jun 2013 10:22:37 +0300 Subject: [PATCH 060/294] References: lp:1182441 - merged fix from revision: http://bazaar.launchpad.net/~percona-core/percona-xtradb-cluster/release-5.5.31/revision/416 --- storage/xtradb/include/trx0sys.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h index 4683c097b53..4747fd979aa 100644 --- a/storage/xtradb/include/trx0sys.h +++ b/storage/xtradb/include/trx0sys.h @@ -566,6 +566,22 @@ We must remember this limit in order to keep file compatibility. */ //#if UNIV_PAGE_SIZE < 4096 //# error "UNIV_PAGE_SIZE < 4096" //#endif + + +/* The offset to WSREP XID headers */ +#ifdef WITH_WSREP +#define TRX_SYS_WSREP_XID_INFO (UNIV_PAGE_SIZE - 3500) +#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 +#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 + +/* XID field: formatID, gtrid_len, bqual_len, xid_data */ +#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) +#define TRX_SYS_WSREP_XID_FORMAT 4 +#define TRX_SYS_WSREP_XID_GTRID_LEN 8 +#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 +#define TRX_SYS_WSREP_XID_DATA 16 +#endif /* WITH_WSREP*/ + /** The offset of the MySQL replication info in the trx system header; this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are written at prepare time and are the main copy. */ @@ -589,22 +605,6 @@ crash recovery rollbacks a PREPAREd transaction, they are copied back. */ within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ -#ifdef WITH_WSREP -/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused - otherwise (see comments for MySQL bug #34058). */ -/** */ -#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO -#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 -#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 - -/* XID field: formatID, gtrid_len, bqual_len, xid_data */ -#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) -#define TRX_SYS_WSREP_XID_FORMAT 4 -#define TRX_SYS_WSREP_XID_GTRID_LEN 8 -#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 -#define TRX_SYS_WSREP_XID_DATA 16 -#endif /* WITH_WSREP*/ - /** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ From 3fa8559debb41102089788bcbe575d887a25dffd Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 14 Jun 2013 22:01:18 +0500 Subject: [PATCH 061/294] MDEV-4656 MariaDB-Galera deb packages cannot be built, expected files are missing. Kristian changed the install directory for these files to share/mysql. (that was changeset 3334.1.345 Fix wrong install location for DEB supportfiles.) But dist/mariadb-galera-server.files weren't changed accordingly. Here we fix them. --- debian/dist/Debian/mariadb-galera-server-5.5.files | 4 ++-- debian/dist/Ubuntu/mariadb-galera-server-5.5.files | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files index 4f5735ba639..87857f27912 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files @@ -94,5 +94,5 @@ usr/share/mysql/mysql_system_tables_data.sql usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_performance_tables.sql usr/share/mysql/mysql_test_data_timezone.sql -usr/support-files/wsrep.cnf -usr/support-files/wsrep_notify +usr/share/mysql/wsrep.cnf +usr/share/mysql/wsrep_notify diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files index c2a556f844d..c30fa841749 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files @@ -96,4 +96,5 @@ usr/share/mysql/mysql_system_tables_data.sql usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_performance_tables.sql usr/share/mysql/mysql_test_data_timezone.sql -usr/support-files/wsrep.cnf +usr/share/mysql/wsrep.cnf +usr/share/mysql/wsrep_notify From 7d2a0e9da45fb66659493767fa3adda1e7ef499d Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sat, 15 Jun 2013 16:15:17 +0300 Subject: [PATCH 062/294] References lp:1108035 - merged fix from http://bazaar.launchpad.net/~percona-core/percona-xtradb-cluster/release-5.5.31/revision/394 --- storage/xtradb/os/os0proc.c | 9 +++++++++ storage/xtradb/srv/srv0start.c | 12 +++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c index c9ee707e923..9ce04602082 100644 --- a/storage/xtradb/os/os0proc.c +++ b/storage/xtradb/os/os0proc.c @@ -57,6 +57,9 @@ UNIV_INTERN ibool os_use_large_pages; /* Large page size. This may be a boot-time option on some platforms */ UNIV_INTERN ulint os_large_page_size; +#ifdef WITH_WSREP +extern my_bool wsrep_recovery; +#endif /* WITH_WSREP */ /****************************************************************//** Converts the current process id to a number. It is not guaranteed that the number is unique. In Linux returns the 'process number' of the current @@ -183,6 +186,12 @@ skip: # else size = UNIV_PAGE_SIZE; # endif +#ifdef WITH_WSREP + /* Don't populate if wsrep_recovery is ON */ + if (wsrep_recovery) { + populate = FALSE; + } +#endif /* WITH_WSREP */ /* Align block size to system page size */ ut_ad(ut_is_2pow(size)); size = *n = ut_2pow_round(*n + (size - 1), size); diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c index 9e0477253cd..3c930beb00e 100644 --- a/storage/xtradb/srv/srv0start.c +++ b/storage/xtradb/srv/srv0start.c @@ -90,7 +90,10 @@ Created 2/16/1996 Heikki Tuuri # include "zlib.h" /* for ZLIB_VERSION */ # include "buf0lru.h" /* for buf_LRU_file_restore() */ -/** Log sequence number immediately after startup */ +#ifdef WITH_WSREP +extern my_bool wsrep_recovery; +#endif /* WITH_WSREP */ + /** Log sequence number immediately after startup */ UNIV_INTERN ib_uint64_t srv_start_lsn; /** Log sequence number at shutdown */ UNIV_INTERN ib_uint64_t srv_shutdown_lsn; @@ -2058,6 +2061,10 @@ innobase_start_or_create_for_mysql(void) os_thread_create(&srv_monitor_thread, NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); +#ifdef WITH_WSREP + /* Don't start the LRU thread when recovery is on */ + if (!wsrep_recovery) { +#endif /* WITH_WSREP */ /* Create the thread which automaticaly dumps/restore buffer pool */ os_thread_create(&srv_LRU_dump_restore_thread, NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS); @@ -2066,6 +2073,9 @@ innobase_start_or_create_for_mysql(void) synchronously */ if (srv_auto_lru_dump && srv_blocking_lru_restore) buf_LRU_file_restore(); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ srv_is_being_started = FALSE; From 527ce30cf3aa517816d9bd87dc99c1f6967cf7f5 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sat, 15 Jun 2013 16:15:45 +0300 Subject: [PATCH 063/294] References: MDEV-4572 - merge with lp:codership-mysql/5.5-23 revisions 3874..3878 --- scripts/mysqld_safe.sh | 74 +++++++++++- scripts/wsrep_sst_common.sh | 7 ++ scripts/wsrep_sst_mysqldump.sh | 2 +- scripts/wsrep_sst_rsync.sh | 36 +++++- scripts/wsrep_sst_xtrabackup.sh | 197 ++++++++++++++++++++++++++++---- sql/tztime.cc | 3 + support-files/mysql.server.sh | 17 ++- 7 files changed, 307 insertions(+), 29 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 7db2a5605e1..d9c8e192d89 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -18,6 +18,8 @@ niceness=0 nowatch=0 mysqld_ld_preload= mysqld_ld_library_path= +flush_caches=0 +numa_interleave=0 # Initial logging status: error log is not open, and not using syslog logging=init @@ -85,6 +87,10 @@ Usage: $0 [OPTIONS] --syslog Log messages to syslog with 'logger' --skip-syslog Log messages to error log (default) --syslog-tag=TAG Pass -t "mysqld-TAG" to 'logger' + --flush-caches Flush and purge buffers/caches before + starting the server + --numa-interleave Run mysqld with its memory interleaved + on all NUMA nodes All other options are passed to the mysqld program. @@ -225,9 +231,11 @@ wsrep_recover_position() { [ "$euid" = "0" ] && chown $user $wr_logfile chmod 600 $wr_logfile - log_notice "WSREP: Running position recovery with --log_error=$wr_logfile" + log_notice "WSREP: Running position recovery with --log_error=$wr_logfile \ + --pid-file="$DATADIR/`@HOSTNAME@`-recover.pid"" - eval_log_error $mysqld_cmd --log_error=$wr_logfile --wsrep-recover + eval_log_error "$mysqld_cmd --log_error=$wr_logfile --wsrep-recover \ + --pid-file="$DATADIR/`@HOSTNAME@`-recover.pid"" local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" if [ -z "$rp" ]; then @@ -312,6 +320,8 @@ parse_arguments() { --syslog-tag=*) syslog_tag="$val" ;; --timezone=*) TZ="$val"; export TZ; ;; --wsrep[-_]urls=*) wsrep_urls="$val"; ;; + --flush-caches) flush_caches=1 ;; + --numa-interleave) numa_interleave=1 ;; --wsrep[-_]provider=*) if test -n "$val" && test "$val" != "none" then @@ -834,6 +844,41 @@ mysqld daemon not started" fi fi +# +# Flush and purge buffers/caches. +# + +if @TARGET_LINUX@ && test $flush_caches -eq 1 +then + # Locate sync, ensure it exists. + if ! my_which sync > /dev/null 2>&1 + then + log_error "sync command not found, required for --flush-caches" + exit 1 + # Flush file system buffers. + elif ! sync + then + # Huh, the sync() function is always successful... + log_error "sync failed, check if sync is properly installed" + fi + + # Locate sysctl, ensure it exists. + if ! my_which sysctl > /dev/null 2>&1 + then + log_error "sysctl command not found, required for --flush-caches" + exit 1 + # Purge page cache, dentries and inodes. + elif ! sysctl -q -w vm.drop_caches=3 + then + log_error "sysctl failed, check the error message for details" + exit 1 + fi +elif test $flush_caches -eq 1 +then + log_error "--flush-caches is not supported on this platform" + exit 1 +fi + # # Uncomment the following lines if you want all tables to be automatically # checked and repaired during startup. You should add sensible key_buffer @@ -854,6 +899,31 @@ fi cmd="`mysqld_ld_preload_text`$NOHUP_NICENESS" +# +# Set mysqld's memory interleave policy. +# + +if @TARGET_LINUX@ && test $numa_interleave -eq 1 +then + # Locate numactl, ensure it exists. + if ! my_which numactl > /dev/null 2>&1 + then + log_error "numactl command not found, required for --numa-interleave" + exit 1 + # Attempt to run a command, ensure it works. + elif ! numactl --interleave=all true + then + log_error "numactl failed, check if numactl is properly installed" + fi + + # Launch mysqld with numactl. + cmd="$cmd numactl --interleave=all" +elif test $numa_interleave -eq 1 +then + log_error "--numa-interleave is not supported on this platform" + exit 1 +fi + for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \ "--datadir=$DATADIR" "--plugin-dir=$plugin_dir" "$USER_OPTION" do diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 017f4877fd6..44c97fdb5f4 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -86,6 +86,8 @@ shift done readonly WSREP_SST_OPT_BYPASS +SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" + wsrep_log() { # echo everything to stderr so that it gets into common error log @@ -104,3 +106,8 @@ wsrep_log_info() wsrep_log "[INFO] $*" } +wsrep_cleanup_progress_file() +{ + rm -f $SST_PROGRESS_FILE 2>/dev/null +} + diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 4434792240d..cf4f55df98e 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -117,5 +117,5 @@ else wsrep_log_info "Bypassing state dump." echo $SET_START_POSITION | $MYSQL fi - +wsrep_cleanup_progress_file # diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 583d70fda5e..af2d41f2659 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -33,6 +33,9 @@ cleanup_joiner() rm -rf "$MAGIC_FILE" rm -rf "$RSYNC_PID" wsrep_log_info "Joiner cleanup done." + if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + wsrep_cleanup_progress_file + fi } check_pid() @@ -89,11 +92,13 @@ then # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') # New filter - exclude everything except dirs (schemas) and innodb files - FILTER=(-f '- lost+found' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') + FILTER=(-f '- lost+found' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') + # first, the normal directories, so that we can detect incompatible protocol RC=0 rsync --archive --no-times --ignore-times --inplace --delete --quiet \ - $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA" \ + --no-recursive --dirs \ + $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA/" \ rsync://$WSREP_SST_OPT_ADDR || RC=$? [ $RC -ne 0 ] && wsrep_log_error "rsync returned code $RC:" @@ -114,6 +119,30 @@ then [ $RC -ne 0 ] && exit $RC + # then, we parallelize the transfer of database directories, use . so that pathconcatenation works + pushd "$WSREP_SST_OPT_DATA" 1>/dev/null + + count=$(grep -c processor /proc/cpuinfo) + + find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -i -0 -P $count \ + rsync --archive --no-times --ignore-times --inplace --delete --quiet \ + $WHOLE_FILE_OPT "$WSREP_SST_OPT_DATA"/{}/ \ + rsync://$WSREP_SST_OPT_ADDR/{} || RC=$? + + popd 1>/dev/null + + [ $RC -ne 0 ] && wsrep_log_error "find/rsync returned code $RC:" + + case $RC in + 0) RC=0 # Success + ;; + *) RC=255 # unknown error + ;; + esac + + [ $RC -ne 0 ] && exit $RC + + else # BYPASS wsrep_log_info "Bypassing state dump." STATE="$WSREP_SST_OPT_GTID" @@ -128,6 +157,7 @@ then elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ] then + touch $SST_PROGRESS_FILE MYSQLD_PID=$WSREP_SST_OPT_PARENT MODULE="rsync_sst" @@ -201,7 +231,7 @@ EOF # this message should cause joiner to abort echo "rsync process ended without creating '$MAGIC_FILE'" fi - + wsrep_cleanup_progress_file # cleanup_joiner else wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'" diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index f9bddd7bd4e..68e8c0309fb 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -22,12 +22,13 @@ cleanup_joiner() { -#set -x local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') wsrep_log_info "Killing nc pid $PID" [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : rm -f "$MAGIC_FILE" -#set +x + if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + wsrep_cleanup_progress_file + fi } check_pid() @@ -87,6 +88,7 @@ rm -f "${MAGIC_FILE}" if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then + encrypt=0 # UUID=$6 # SEQNO=$7 @@ -97,10 +99,9 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then + TMPDIR="/tmp" - TMPDIR=${TMPDIR:-"/tmp"} - - INNOBACKUPEX_ARGS="--galera-info --stream=tar + INNOBACKUPEX_ARGS="--galera-info --stream=xbstream --defaults-file=${WSREP_SST_OPT_CONF} --socket=${WSREP_SST_OPT_SOCKET}" @@ -110,10 +111,39 @@ then if [ ${#AUTH[*]} -eq 2 ]; then INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" - fi + else + # Empty password, used for testing, debugging etc. + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=" + fi set +e + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then + wsrep_log_info "Encryption enabled in my.cnf - NOT SUPPORTED - look at lp:1190343" + #encrypt=1 + fi + if [[ $encrypt -eq 1 ]];then + + ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) + ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) + ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) + + if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then + wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" + exit 3 + fi + + if [[ -n $ekey ]];then + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey" + else + if [[ ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Key file not readable" + exit 3 + fi + INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile" + fi + fi + ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ 2> ${DATA}/innobackup.backup.log | \ ${NC_BIN} ${REMOTEIP} ${NC_PORT} @@ -155,6 +185,15 @@ then elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] then + touch $SST_PROGRESS_FILE + + sencrypted=1 + encrypt=0 + ekey="" + ealgo="" + ekeyfile="" + ecode=0 + MODULE="xtrabackup_sst" rm -f ${DATA}/xtrabackup_* @@ -169,23 +208,58 @@ then wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & -# trap "exit 32" HUP PIPE -# trap "exit 3" INT TERM - trap cleanup_joiner HUP PIPE INT TERM + trap "exit 32" HUP PIPE + trap "exit 3" INT TERM + trap cleanup_joiner EXIT + + # There is no metadata in the stream to indicate that it is encrypted + # So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then + # it means encryption is being used + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then + #wsrep_log_info "Encryption enabled in my.cnf, decrypting the stream/backup" + wsrep_log_error "Encryption enabled in my.cnf - NOT SUPPORTED - look at lp:1190343" + #encrypt=1 + fi set +e - ${NC_BIN} -dl ${NC_PORT} | tar xfi - -C ${DATA} 1>&2 - RC=( "${PIPESTATUS[@]}" ) + if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then + + + ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) + ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) + ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) + + if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then + wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" + exit 3 + fi + + if [[ -n $ekey ]];then + ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA} 1>&2 + RC=( "${PIPESTATUS[@]}" ) + else + if [[ ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Key file not readable" + exit 3 + fi + ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA} 1>&2 + RC=( "${PIPESTATUS[@]}" ) + fi + else + ${NC_BIN} -dl ${NC_PORT} | xbstream -x -C ${DATA} 1>&2 + RC=( "${PIPESTATUS[@]}" ) + fi set -e wait %% # join wait_for_nc thread - if [ ${RC[0]} -ne 0 -o ${RC[1]} -ne 0 ]; - then - wsrep_log_error "Error while getting st data from donor node: " \ - "${RC[0]}, ${RC[1]}" - exit 32 - fi + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while getting st data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done if [ ! -r "${MAGIC_FILE}" ] then @@ -196,24 +270,105 @@ then if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null then - wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." >&2 + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." exit 32 fi if [ ! -r "${IST_FILE}" ] then + wsrep_log_info "Removing existing ib_logfile files" rm -f ${DATA}/ib_logfile* - ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \ - --ibbackup=xtrabackup ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log + rebuild="" + + + # Decrypt only if not encrypted in stream. + # NOT USED NOW. + # Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url + # is implemented + + if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then + ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) + ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) + ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) + + # Decrypt the files if any + find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do + if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then + wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" + exit 3 + fi + input=$line + output=${input%.xbcrypt} + + if [[ -n $ekey ]];then + xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output + else + if [[ ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Key file not readable" + exit 3 + fi + xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output + fi + done + + if [[ $? = 0 ]];then + find ${DATA} -type f -name '*.xbcrypt' -delete + fi + fi + + # Rebuild indexes for compact backups + if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then + wsrep_log_info "Index compaction detected" + rebuild="--rebuild-indexes" + fi + + if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then + + wsrep_log_info "Compressed qpress files found" + + if [[ ! -x `which qpress` ]];then + wsrep_log_error "qpress not found in PATH" + exit 22 + fi + + + set +e + + wsrep_log_info "Removing existing ibdata1 file" + rm -f ${DATA}/ibdata1 + + # Decompress the qpress files + find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $(grep -c processor /proc/cpuinfo) -n 2 qpress -d + extcode=$? + + set -e + + if [[ $extcode -eq 0 ]];then + wsrep_log_info "Removing qpress files after decompression" + find ${DATA} -type f -name '*.qp' -delete + if [[ $? -ne 0 ]];then + wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" + fi + else + wsrep_log_error "Decompression failed. Exit code: $extcode" + exit 22 + fi + fi + + ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \ + ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log if [ $? -ne 0 ]; then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" >&2 + wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" exit 22 fi fi cat "${MAGIC_FILE}" # output UUID:seqno + #Cleanup not required here since EXIT trap should be called + #wsrep_cleanup_progress_file + else wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}" exit 22 # EINVAL diff --git a/sql/tztime.cc b/sql/tztime.cc index 95a1001485b..21f5f27f3df 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2557,6 +2557,9 @@ main(int argc, char **argv) return 1; } + // Replicate MyISAM DDL for this session, cf. lp:1161432 + printf("SET SESSION wsrep_replicate_myisam=ON;\n"); + if (argc == 2) { root_name_end= strmake_buf(fullname, argv[1]); diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 545831f93fc..0879288fe6c 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -52,6 +52,7 @@ datadir= # 0 means don't wait at all # Negative numbers mean to wait indefinitely service_startup_timeout=900 +startup_sleep=1 # Lock directory for RedHat / SuSE. lockdir='/var/lock/subsys' @@ -157,6 +158,7 @@ wait_for_pid () { pid="$2" # process ID of the program operating on the pid-file pid_file_path="$3" # path to the PID file. + sst_progress_file=$datadir/sst_in_progress i=0 avoid_race_condition="by checking again" @@ -194,9 +196,14 @@ wait_for_pid () { fi fi + if test -e $sst_progress_file && [ $startup_sleep -ne 100 ];then + echo $echo_n "SST in progress, setting sleep higher" + startup_sleep=100 + fi + echo $echo_n ".$echo_c" i=`expr $i + 1` - sleep 1 + sleep $startup_sleep done @@ -411,10 +418,16 @@ case "$mode" in fi exit $r ;; + 'boostrap') + # Bootstrap the cluster, start the first node + # that initiate the cluster + echo $echo_n "Bootstrapping cluster)" + $0 start $other_args --wsrep-new-cluster + ;; *) # usage basename=`basename "$0"` - echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest} [ MySQL server options ]" + echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest|bootstrap} [ MySQL server options ]" exit 1 ;; esac From 1c09bbfe3dedb0b11ebbfc5eb4b774f44b321d9a Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sat, 15 Jun 2013 16:16:38 +0300 Subject: [PATCH 064/294] References lp:1087368 - merged fix from wsrep-5.5 branch. Note this is compatible only with new wsrep provider #23 libraries, which understand 'bootstrap' address in connecting. --- mysys/default.c | 37 +++++++++++++++++++++++++++++++++++++ sql/wsrep_mysqld.cc | 13 +++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index fa9576d16f2..9fa377e881d 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -91,6 +91,40 @@ static my_bool defaults_already_read= FALSE; /* The only purpose of this global array is to hold full name of my.cnf * which seems to be otherwise unavailable */ char wsrep_defaults_file[FN_REFLEN + 10]={0,}; +/* Command-line only option to start a new wsrep service instance */ +#define WSREP_NEW_CLUSTER1 "--wsrep-new-cluster" +#define WSREP_NEW_CLUSTER2 "--wsrep_new_cluster" +/* This one is set to true when --wsrep-new-cluster is found in the command + * line arguments */ +my_bool wsrep_new_cluster= FALSE; +/* Finds and removes --wsrep-new-cluster from the arguments list. + * Returns true if found. */ +static my_bool find_wsrep_new_cluster (int* argc, char* argv[]) +{ + my_bool ret= FALSE; + int i; + + for (i= *argc - 1; i > 0; i--) + { + if (!strcmp(argv[i], WSREP_NEW_CLUSTER1) || + !strcmp(argv[i], WSREP_NEW_CLUSTER2)) + { + ret= TRUE; + *argc -= 1; + if (*argc == i) + { // last argument, just zero it up + argv[i]= NULL; + } + else + { // not the last argument, copy the last one over and zero that up. + argv[i]= argv[*argc]; + argv[*argc]= NULL; + } + } + } + + return ret; +} #endif /* WITH_WREP */ /* Which directories are searched for options (and in which order) */ @@ -529,6 +563,9 @@ int my_load_defaults(const char *conf_file, const char **groups, init_alloc_root(&alloc,512,0); if ((dirs= init_default_directories(&alloc)) == NULL) goto err; +#ifdef WITH_WSREP + wsrep_new_cluster= find_wsrep_new_cluster(argc, argv[0]); +#endif /* WITH_WSREP */ /* Check if the user doesn't want any default option processing --no-defaults is always the first option diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index e653d790747..790cf45def4 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -409,7 +409,6 @@ static void wsrep_init_position() } } - int wsrep_init() { int rcode= -1; @@ -651,6 +650,8 @@ void wsrep_stop_replication(THD *thd) } +extern my_bool wsrep_new_cluster; + bool wsrep_start_replication() { wsrep_status_t rcode; @@ -674,11 +675,19 @@ bool wsrep_start_replication() return true; } + /* Note 'bootstrap' address is not officially supported in wsrep API #23 + but it can be back ported from #24 provider to get sneak preview of + bootstrap command + */ + const char* cluster_address = + wsrep_new_cluster ? "bootstrap" : wsrep_cluster_address; + wsrep_new_cluster= FALSE; + WSREP_INFO("Start replication"); if ((rcode = wsrep->connect(wsrep, wsrep_cluster_name, - wsrep_cluster_address, + cluster_address, wsrep_sst_donor))) { if (-ESOCKTNOSUPPORT == rcode) From 6793d7f1146639f03e3d860bcd668ba2e2d028eb Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sun, 16 Jun 2013 20:38:02 +0300 Subject: [PATCH 065/294] References lp:1134892 - WSREP_DEBUG_PRINT was left on by mistake --- storage/innobase/handler/ha_innodb.cc | 1 - storage/xtradb/handler/ha_innodb.cc | 1 - 2 files changed, 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bf47908282c..af52be63e20 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7224,7 +7224,6 @@ wsrep_append_foreign_key( foreign->foreign_table->name) : foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); -#define WSREP_DEBUG_PRINT #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index c93f031ff71..29efd7d237c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8187,7 +8187,6 @@ wsrep_append_foreign_key( foreign->foreign_table->name) : foreign->foreign_table->name, sizeof(cache_key) - 1); cache_key_len = strlen(cache_key); -#define WSREP_DEBUG_PRINT #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", From 862c6b219e672a39d24db6555084ad6e3a1cbbfd Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 19 Jun 2013 10:35:40 +0300 Subject: [PATCH 066/294] References lp:1191778 - merged xtrabackup SST fixes from PXC --- scripts/wsrep_sst_xtrabackup.sh | 141 +++++++++++++++----------------- 1 file changed, 67 insertions(+), 74 deletions(-) diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 68e8c0309fb..16f29e6e358 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -1,6 +1,5 @@ #!/bin/bash -ue - -# Copyright (C) 2011 Percona Inc +# Copyright (C) 2013 Percona Inc # # 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,9 +16,46 @@ # MA 02110-1301 USA. # This is a reference script for Percona XtraBackup-based state snapshot tansfer +# Dependencies: (depending on configuration) +# xbcrypt for encryption/decryption. +# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till +# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. +# my_print_defaults to extract values from my.cnf. +# netcat for transfer. +# xbstream for streaming. . $(dirname $0)/wsrep_sst_common +ealgo="" +ekey="" +ekeyfile="" +encrypt=0 + +get_keys() +{ + # There is no metadata in the stream to indicate that it is encrypted + # So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then + # it means encryption is being used + if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then + return + fi + wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343" + ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) + ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) + ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) + + if [[ -z $ealgo ]];then + wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" + exit 3 + fi + + if [[ -z $ekey && ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Either key or keyfile must be readable" + exit 3 + fi + encrypt=1 +} + cleanup_joiner() { local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') @@ -27,6 +63,7 @@ cleanup_joiner() [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : rm -f "$MAGIC_FILE" if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + wsrep_log_info "Removing the sst_in_progress file" wsrep_cleanup_progress_file fi } @@ -88,7 +125,6 @@ rm -f "${MAGIC_FILE}" if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then - encrypt=0 # UUID=$6 # SEQNO=$7 @@ -116,34 +152,17 @@ then INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=" fi - set +e - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then - wsrep_log_info "Encryption enabled in my.cnf - NOT SUPPORTED - look at lp:1190343" - #encrypt=1 - fi + get_keys if [[ $encrypt -eq 1 ]];then - - ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) - ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) - ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) - - if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then - wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" - exit 3 - fi - if [[ -n $ekey ]];then INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey" else - if [[ ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Key file not readable" - exit 3 - fi INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile" fi fi + set +e ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ 2> ${DATA}/innobackup.backup.log | \ ${NC_BIN} ${REMOTEIP} ${NC_PORT} @@ -177,7 +196,16 @@ then echo "continue" # now server can resume updating data echo "${STATE}" > "${MAGIC_FILE}" echo "1" > "${DATA}/${IST_FILE}" - (cd ${DATA}; tar cf - ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + get_keys + if [[ $encrypt -eq 1 ]];then + if [[ -n $ekey ]];then + (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + else + (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + fi + else + (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + fi rm -f ${DATA}/${IST_FILE} fi @@ -185,14 +213,12 @@ then elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] then + [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" touch $SST_PROGRESS_FILE sencrypted=1 - encrypt=0 - ekey="" - ealgo="" - ekeyfile="" ecode=0 + declare -a RC MODULE="xtrabackup_sst" @@ -212,51 +238,28 @@ then trap "exit 3" INT TERM trap cleanup_joiner EXIT - # There is no metadata in the stream to indicate that it is encrypted - # So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then - # it means encryption is being used - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then - #wsrep_log_info "Encryption enabled in my.cnf, decrypting the stream/backup" - wsrep_log_error "Encryption enabled in my.cnf - NOT SUPPORTED - look at lp:1190343" - #encrypt=1 - fi - + get_keys set +e if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then - - - ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) - ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) - ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) - - if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then - wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" - exit 3 - fi - if [[ -n $ekey ]];then - ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA} 1>&2 - RC=( "${PIPESTATUS[@]}" ) + ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA} else - if [[ ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Key file not readable" - exit 3 - fi - ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA} 1>&2 - RC=( "${PIPESTATUS[@]}" ) + ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA} fi else - ${NC_BIN} -dl ${NC_PORT} | xbstream -x -C ${DATA} 1>&2 - RC=( "${PIPESTATUS[@]}" ) + ${NC_BIN} -dl ${NC_PORT} | xbstream -x -C ${DATA} fi + RC=( "${PIPESTATUS[@]}" ) set -e wait %% # join wait_for_nc thread for ecode in "${RC[@]}";do if [[ $ecode -ne 0 ]];then - wsrep_log_error "Error while getting st data from donor node: " \ + wsrep_log_error "Error while getting data from donor node: " \ "exit codes: ${RC[@]}" + wsrep_log_error "Data directory ${DATA} needs to be empty for SST:" \ + "Manual intervention required in that case" exit 32 fi done @@ -276,37 +279,24 @@ then if [ ! -r "${IST_FILE}" ] then + rebuild="" wsrep_log_info "Removing existing ib_logfile files" rm -f ${DATA}/ib_logfile* - rebuild="" - # Decrypt only if not encrypted in stream. # NOT USED NOW. # Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url # is implemented - + #get_keys if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then - ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) - ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) - ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) - # Decrypt the files if any find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do - if [[ -z $ealgo || (-z $ekey && -z $ekeyfile) ]];then - wsrep_log_error "FATAL: Encryption parameters empty from my.cnf, bailing out" - exit 3 - fi input=$line output=${input%.xbcrypt} if [[ -n $ekey ]];then xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output else - if [[ ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Key file not readable" - exit 3 - fi xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output fi done @@ -331,7 +321,6 @@ then exit 22 fi - set +e wsrep_log_info "Removing existing ibdata1 file" @@ -355,6 +344,8 @@ then fi fi + wsrep_log_info "Preparing the backup at ${DATA}" + ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \ ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log if [ $? -ne 0 ]; @@ -362,6 +353,8 @@ then wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" exit 22 fi + else + wsrep_log_info "Running IST" fi cat "${MAGIC_FILE}" # output UUID:seqno From 93ed851cc63ce2510c26c656e55e0e1dc28f99f9 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Thu, 20 Jun 2013 21:51:11 +0300 Subject: [PATCH 067/294] References lp:1193079 - bumped wsrep version to 7.5 --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 3337a2a93df..608b33b31a1 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7.3") +SET(WSREP_PATCH_VERSION "7.5") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) From 7cf10ddf8ca7044278b4aa1cf5a5525675cd101d Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 5 Aug 2013 18:01:05 +0300 Subject: [PATCH 068/294] References lp:1208493 https://mariadb.atlassian.net/browse/MDEV-4830 Enabling slave applier thread to send COND_thread_count --- sql/sql_parse.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c8be6be541f..7fe8be00125 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8431,13 +8431,11 @@ void wsrep_replication_process(THD *thd) break; } - if (thd->killed != KILL_CONNECTION) - { - mysql_mutex_lock(&LOCK_thread_count); - wsrep_close_applier(thd); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - } + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + wsrep_return_from_bf_mode(thd, &shadow); DBUG_VOID_RETURN; } From 551ad1cf6f80ad1fab35746eee304d733baa9adf Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 7 Aug 2013 00:17:16 +0300 Subject: [PATCH 069/294] Merged FreeBSD compatibility changes (up to revision 3893 in lp:~codership/codership-mysql/5.5-23) --- .bzrignore | 3 + cmake/install_macros.cmake | 24 +++++ cmake/os/FreeBSD.cmake | 3 + scripts/mysqld_safe.sh | 5 +- scripts/wsrep_sst_rsync.sh | 64 ++++++++---- scripts/wsrep_sst_xtrabackup.sh | 179 ++++++++++++++++++++++++++------ sql/wsrep_utils.cc | 2 + 7 files changed, 222 insertions(+), 58 deletions(-) mode change 100644 => 100755 scripts/wsrep_sst_rsync.sh diff --git a/.bzrignore b/.bzrignore index 8f44e83369a..858b00cf5c5 100644 --- a/.bzrignore +++ b/.bzrignore @@ -72,6 +72,9 @@ RelWithDebInfo .vimrc ac_available_languages_fragment BitKeeper/ +build_debug +build_install +build_release client/*.ds? client/completion_hash.cpp client/decimal.c diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 14e43ee5e95..f9ff1f5cf31 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -13,8 +13,30 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +if(APPLE) + LIST(APPEND CMAKE_CXX_LINK_EXECUTABLE "dsymutil ") + LIST(APPEND CMAKE_C_LINK_EXECUTABLE "dsymutil ") + LIST(APPEND CMAKE_CXX_CREATE_SHARED_LIBRARY "dsymutil ") + LIST(APPEND CMAKE_C_CREATE_SHARED_LIBRARY "dsymutil ") + LIST(APPEND CMAKE_CXX_CREATE_SHARED_MODULE "dsymutil ") + LIST(APPEND CMAKE_C_CREATE_SHARED_MODULE "dsymutil ") +ENDIF() + GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake) +MACRO (INSTALL_DSYM_DIRECTORIES targets) + IF(APPLE) + FOREACH(target ${targets}) + GET_TARGET_PROPERTY(location ${target} LOCATION) + GET_TARGET_PROPERTY(type ${target} TYPE) + # It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */ + STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location}) + IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY") + INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${INSTALL_LOCATION} COMPONENT Debuginfo) + ENDIF() + ENDFOREACH() + ENDIF() +ENDMACRO() FUNCTION (INSTALL_DEBUG_SYMBOLS) IF(MSVC) @@ -31,6 +53,7 @@ FUNCTION (INSTALL_DEBUG_SYMBOLS) MESSAGE(FATAL_ERROR "No INSTALL_LOCATION passed to INSTALL_DEBUG_SYMBOLS") ENDIF() SET(targets ${ARG_DEFAULT_ARGS}) + FOREACH(target ${targets}) GET_TARGET_PROPERTY(type ${target} TYPE) GET_TARGET_PROPERTY(location ${target} LOCATION) @@ -252,6 +275,7 @@ FUNCTION(MYSQL_INSTALL_TARGETS) INSTALL(TARGETS ${TARGETS} DESTINATION ${ARG_DESTINATION} ${COMP}) INSTALL_DEBUG_SYMBOLS(${TARGETS} ${COMP} INSTALL_LOCATION ${ARG_DESTINATION}) + INSTALL_DSYM_DIRECTORIES("${TARGETS}") ENDFUNCTION() diff --git a/cmake/os/FreeBSD.cmake b/cmake/os/FreeBSD.cmake index 27afe679f25..32c39c48531 100644 --- a/cmake/os/FreeBSD.cmake +++ b/cmake/os/FreeBSD.cmake @@ -38,3 +38,6 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 4 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "i386") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=i686") ENDIF() + +SET(HAVE_SYS_TIMEB_H CACHE INTERNAL "") + diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index d9c8e192d89..43a8508c7c0 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -241,7 +241,8 @@ wsrep_recover_position() { if [ -z "$rp" ]; then local skipped="$(grep WSREP $wr_logfile | grep 'skipping position recovery')" if [ -z "$skipped" ]; then - log_error "WSREP: Failed to recover position: " `cat $wr_logfile`; + log_error "WSREP: Failed to recover position: +'`cat $wr_logfile`'" ret=1 else log_notice "WSREP: Position recovery skipped" @@ -253,7 +254,7 @@ wsrep_recover_position() { wsrep_start_position_opt="--wsrep_start_position=$start_pos" fi - rm $wr_logfile + [ $ret -eq 0 ] && rm $wr_logfile return $ret } diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh old mode 100644 new mode 100755 index af2d41f2659..7cd232e0887 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -20,6 +20,8 @@ RSYNC_PID= RSYNC_CONF= +OS=$(uname) +[ "$OS" == "Darwin" ] && export -n LD_LIBRARY_PATH . $(dirname $0)/wsrep_sst_common @@ -50,14 +52,32 @@ check_pid_and_port() local rsync_pid=$(cat $pid_file) local rsync_port=$2 - check_pid $pid_file && \ - netstat -anpt 2>/dev/null | \ - grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null + if [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ]; then + # no netstat --program(-p) option in Darwin and FreeBSD + check_pid $pid_file && \ + lsof -i -Pn 2>/dev/null | \ + grep "(LISTEN)" | grep ":$rsync_port" | grep -w '^rsync[[:space:]]\+'"$rsync_pid" >/dev/null + else + check_pid $pid_file && \ + netstat -lnpt 2>/dev/null | \ + grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null + fi } MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" rm -rf "$MAGIC_FILE" +# Old filter - include everything except selected +# FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ +# --exclude '*.conf' --exclude core --exclude 'galera.*' \ +# --exclude grastate.txt --exclude '*.pem' \ +# --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') + +# New filter - exclude everything except dirs (schemas) and innodb files +FILTER=(-f '- lost+found' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') +# Old versions of rsync have a bug transferring filter rules to daemon, so specify filter rules directly to daemon +FILTER_DAEMON="- lost+found + /ib_lru_dump + /ibdata* + ib_logfile* + */ -! */*" + if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then @@ -85,21 +105,12 @@ then sync - # Old filter - include everything except selected - # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ - # --exclude '*.conf' --exclude core --exclude 'galera.*' \ - # --exclude grastate.txt --exclude '*.pem' \ - # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') - - # New filter - exclude everything except dirs (schemas) and innodb files - FILTER=(-f '- lost+found' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') - # first, the normal directories, so that we can detect incompatible protocol RC=0 rsync --archive --no-times --ignore-times --inplace --delete --quiet \ --no-recursive --dirs \ $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA/" \ - rsync://$WSREP_SST_OPT_ADDR || RC=$? + rsync://$WSREP_SST_OPT_ADDR-with_filter || RC=$? [ $RC -ne 0 ] && wsrep_log_error "rsync returned code $RC:" @@ -122,9 +133,11 @@ then # then, we parallelize the transfer of database directories, use . so that pathconcatenation works pushd "$WSREP_SST_OPT_DATA" 1>/dev/null - count=$(grep -c processor /proc/cpuinfo) + count=1 + [ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo) + [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu) - find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -i -0 -P $count \ + find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -I{} -0 -P $count \ rsync --archive --no-times --ignore-times --inplace --delete --quiet \ $WHOLE_FILE_OPT "$WSREP_SST_OPT_DATA"/{}/ \ rsync://$WSREP_SST_OPT_ADDR/{} || RC=$? @@ -151,7 +164,7 @@ then echo "continue" # now server can resume updating data echo "$STATE" > "$MAGIC_FILE" - rsync -aqc "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR + rsync --archive --quiet --checksum "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR echo "done $STATE" @@ -180,7 +193,7 @@ then fi trap "exit 32" HUP PIPE - trap "exit 3" INT TERM + trap "exit 3" INT TERM ABRT trap cleanup_joiner EXIT MYUID=$(id -u) @@ -190,12 +203,19 @@ then cat << EOF > "$RSYNC_CONF" pid file = $RSYNC_PID use chroot = no +[$MODULE-with_filter] + path = $WSREP_SST_OPT_DATA + read only = no + timeout = 300 + uid = $MYUID + gid = $MYGID + filter = $FILTER_DAEMON [$MODULE] - path = $WSREP_SST_OPT_DATA - read only = no - timeout = 300 - uid = $MYUID - gid = $MYGID + path = $WSREP_SST_OPT_DATA + read only = no + timeout = 300 + uid = $MYUID + gid = $MYGID EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 16f29e6e358..3eb747f50c3 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -15,14 +15,25 @@ # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston # MA 02110-1301 USA. -# This is a reference script for Percona XtraBackup-based state snapshot tansfer -# Dependencies: (depending on configuration) -# xbcrypt for encryption/decryption. -# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till -# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. -# my_print_defaults to extract values from my.cnf. -# netcat for transfer. -# xbstream for streaming. +############################################################################################################# +# This is a reference script for Percona XtraBackup-based state snapshot transfer # +# Dependencies: (depending on configuration) # +# xbcrypt for encryption/decryption. # +# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till # +# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. # +# my_print_defaults to extract values from my.cnf. # +# netcat for transfer. # +# xbstream/tar for streaming. (and xtrabackup ofc) # +# # +# Currently only option in cnf is read specifically for SST # +# [sst] # +# streamfmt=tar|xbstream # +# # +# Default is tar till lp:1193240 is fixed # +# You need to use xbstream for encryption, compression etc., however, # +# lp:1193240 requires you to manually cleanup the directory prior to SST # +# # +############################################################################################################# . $(dirname $0)/wsrep_sst_common @@ -30,6 +41,13 @@ ealgo="" ekey="" ekeyfile="" encrypt=0 +nproc=1 +ecode=0 +XTRABACKUP_PID="" + +sfmt="tar" +strmcmd="" +declare -a RC get_keys() { @@ -39,6 +57,11 @@ get_keys() if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then return fi + if [[ $sfmt == 'tar' ]];then + wsrep_log_info "NOTE: Encryption cannot be enabled with tar format" + return + fi + wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343" ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) @@ -56,10 +79,58 @@ get_keys() encrypt=1 } +read_cnf() +{ + sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2) + if [[ $sfmt == 'xbstream' ]];then + wsrep_log_info "Streaming with xbstream" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240" + strmcmd="xbstream -x -C ${DATA}" + elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then + strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}" + else + wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" + exit 22 + fi + else + sfmt="tar" + wsrep_log_info "Streaming with tar" + wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar." + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240." + strmcmd="tar xfi - -C ${DATA}" + elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then + strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}" + else + wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" + exit 22 + fi + + fi +} + +get_proc() +{ + set +e + nproc=$(grep -c processor /proc/cpuinfo) + [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 + set -e +} + cleanup_joiner() { + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') - wsrep_log_info "Killing nc pid $PID" + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Killing nc pid $PID" + else + wsrep_log_info "Killing nc pid $PID" + fi [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : rm -f "$MAGIC_FILE" if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then @@ -74,6 +145,24 @@ check_pid() [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 } +cleanup_donor() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + local pid=$XTRABACKUP_PID + if check_pid "$pid" + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + fi + + rm -f "$pid" + rm -f ${DATA}/${IST_FILE} +} + kill_xtrabackup() { #set -x @@ -123,12 +212,11 @@ IST_FILE="xtrabackup_ist" MAGIC_FILE="${DATA}/${INFO_FILE}" rm -f "${MAGIC_FILE}" +read_cnf + if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then - -# UUID=$6 -# SEQNO=$7 -# BYPASS=$8 + trap cleanup_donor EXIT NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') @@ -137,7 +225,7 @@ then then TMPDIR="/tmp" - INNOBACKUPEX_ARGS="--galera-info --stream=xbstream + INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt --defaults-file=${WSREP_SST_OPT_CONF} --socket=${WSREP_SST_OPT_SOCKET}" @@ -152,7 +240,6 @@ then INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=" fi - get_keys if [[ $encrypt -eq 1 ]];then if [[ -n $ekey ]];then @@ -162,6 +249,8 @@ then fi fi + wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}" + set +e ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ 2> ${DATA}/innobackup.backup.log | \ @@ -182,31 +271,37 @@ then # innobackupex implicitly writes PID to fixed location in ${TMPDIR} XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" - if check_pid "${XTRABACKUP_PID}" - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - exit 22 - fi - - rm -f "${XTRABACKUP_PID}" else # BYPASS + wsrep_log_info "Bypassing the SST for IST" STATE="${WSREP_SST_OPT_GTID}" echo "continue" # now server can resume updating data echo "${STATE}" > "${MAGIC_FILE}" echo "1" > "${DATA}/${IST_FILE}" get_keys + pushd ${DATA} 1>/dev/null + set +e if [[ $encrypt -eq 1 ]];then if [[ -n $ekey ]];then - (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT} else - (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT} fi - else - (cd ${DATA}; xbstream -c ${INFO_FILE} ${IST_FILE}) | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + else + $strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT} fi - rm -f ${DATA}/${IST_FILE} + RC=( "${PIPESTATUS[@]}" ) + set -e + popd 1>/dev/null + + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while streaming data to joiner node: " \ + "exit codes: ${RC[@]}" + exit 1 + fi + done + #rm -f ${DATA}/${IST_FILE} fi echo "done ${WSREP_SST_OPT_GTID}" @@ -217,8 +312,7 @@ then touch $SST_PROGRESS_FILE sencrypted=1 - ecode=0 - declare -a RC + nthreads=1 MODULE="xtrabackup_sst" @@ -247,11 +341,21 @@ then ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA} fi else - ${NC_BIN} -dl ${NC_PORT} | xbstream -x -C ${DATA} + ${NC_BIN} -dl ${NC_PORT} | $strmcmd fi RC=( "${PIPESTATUS[@]}" ) set -e + if [[ $sfmt == 'xbstream' ]];then + # Special handling till lp:1193240 is fixed" + if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then + wsrep_log_error "Xbstream failed" + wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \ + "Manual intervention required in that case" + exit 32 + fi + fi + wait %% # join wait_for_nc thread for ecode in "${RC[@]}";do @@ -279,6 +383,7 @@ then if [ ! -r "${IST_FILE}" ] then + wsrep_log_info "Proceeding with SST" rebuild="" wsrep_log_info "Removing existing ib_logfile files" rm -f ${DATA}/ib_logfile* @@ -306,10 +411,15 @@ then fi fi + get_proc + # Rebuild indexes for compact backups if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then wsrep_log_info "Index compaction detected" - rebuild="--rebuild-indexes" + nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2) + [[ -z $nthreads ]] && nthreads=$nproc + wsrep_log_info "Rebuilding with $nthreads threads" + rebuild="--rebuild-indexes --rebuild-threads=$nthreads" fi if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then @@ -327,7 +437,8 @@ then rm -f ${DATA}/ibdata1 # Decompress the qpress files - find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $(grep -c processor /proc/cpuinfo) -n 2 qpress -d + wsrep_log_info "Decompression with $nproc threads" + find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d extcode=$? set -e @@ -354,7 +465,7 @@ then exit 22 fi else - wsrep_log_info "Running IST" + wsrep_log_info "${IST_FILE} received from donor: Running IST" fi cat "${MAGIC_FILE}" # output UUID:seqno diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 392fb65d82c..19ffb101841 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -358,6 +358,8 @@ size_t guess_ip (char* buf, size_t buf_len) #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; +#elif defined(__APPLE__) || defined(__FreeBSD__) + const char cmd[] = "route -nv get 8.8.8.8 | tail -n1 | awk '{print $5}'"; #else char *cmd; #error "OS not supported" From 2db87f65167c389c191336672e7ae1ddc65c8436 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 21 Aug 2013 16:37:22 +0300 Subject: [PATCH 070/294] References MDEV-4404 - Added log message to catch information of log event corruption --- sql/rpl_record.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 99bf8a82004..705886fd8d1 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -304,6 +304,10 @@ unpack_row(Relay_log_info const *rli, uint16 const metadata= tabledef->field_metadata(i); #ifndef DBUG_OFF uchar const *const old_pack_ptr= pack_ptr; +#else +#if WITH_WSREP + uchar const *const old_pack_ptr= pack_ptr; +#endif #endif pack_ptr= f->unpack(f->ptr, pack_ptr, row_buffer_end, metadata); DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;" @@ -313,6 +317,17 @@ unpack_row(Relay_log_info const *rli, (int) (pack_ptr - old_pack_ptr))); if (!pack_ptr) { + /* Debug message to troubleshoot bug: + https://mariadb.atlassian.net/browse/MDEV-4404 + */ + WSREP_WARN("ROW event unpack field: %s metadata: 0x%x;" + " pack_ptr: 0x%lx; conv_table %p conv_field %p table %s" + " row_buffer_end: 0x%lx", + f->field_name, metadata, + (ulong) old_pack_ptr, conv_table, conv_field, + (table_found) ? "found" : "not found", (ulong)row_buffer_end + ); + rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, "Could not read field '%s' of table '%s.%s'", f->field_name, table->s->db.str, From fca065f95c3f62b0f6ec8448f7dcda40d73eb433 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Wed, 21 Aug 2013 17:17:30 +0300 Subject: [PATCH 071/294] Merged with lp:~codership/codership-mysql/5.5-23, up to revision 3903 --- Docs/README-wsrep | 7 ++--- scripts/wsrep_sst_common.sh | 12 ++++++--- sql/sql_class.cc | 4 +++ sql/sql_class.h | 3 +++ sql/sql_parse.cc | 25 ++++++++++++----- sql/sql_table.cc | 49 ++++++++++++++++++++++++++++++++++ sql/wsrep_check_opts.cc | 2 +- sql/wsrep_hton.cc | 7 ++++- sql/wsrep_mysqld.cc | 19 ++++++++----- sql/wsrep_sst.cc | 11 +++++--- sql/wsrep_var.cc | 10 +++++++ storage/innobase/row/row0upd.c | 1 + storage/xtradb/row/row0upd.c | 1 + support-files/mysql.spec.sh | 5 +++- support-files/wsrep.cnf.sh | 2 +- 15 files changed, 132 insertions(+), 26 deletions(-) diff --git a/Docs/README-wsrep b/Docs/README-wsrep index 025379764b2..422ec52f48a 100644 --- a/Docs/README-wsrep +++ b/Docs/README-wsrep @@ -377,11 +377,12 @@ the other cluster members by transferring state snapshot from one of them. The options below govern how this happens and should be set up before attempting to join or start a cluster. -wsrep_sst_method=mysqldump +wsrep_sst_method=rsync What method to use to copy database state to a newly joined node. Supported methods: - - mysqldump: slow (except for small datasets) but most tested. - - rsync: much faster on large datasets. + - mysqldump: slow (except for small datasets) but allows for upgrade + between major MySQL versions or InnoDB features. + - rsync: much faster on large datasets (default). - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. - xtrabackup: very fast and practically non-blocking SST method based on Percona's xtrabackup tool. diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 44c97fdb5f4..30303de0779 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Codership Oy +# Copyright (C) 2012 Codership Oy # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ set -u WSREP_SST_OPT_BYPASS=0 +WSREP_SST_OPT_DATA="" while [ $# -gt 0 ]; do case "$1" in @@ -86,7 +87,12 @@ shift done readonly WSREP_SST_OPT_BYPASS -SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" +if [ -n "$WSREP_SST_OPT_DATA" ] +then + SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" +else + SST_PROGRESS_FILE="" +fi wsrep_log() { @@ -108,6 +114,6 @@ wsrep_log_info() wsrep_cleanup_progress_file() { - rm -f $SST_PROGRESS_FILE 2>/dev/null + [ -n "$SST_PROGRESS_FILE" ] && rm -f "$SST_PROGRESS_FILE" 2>/dev/null } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2469f2dd3b1..0e371adfe56 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1116,6 +1116,8 @@ THD::THD() wsrep_status_vars = 0; wsrep_mysql_replicated = 0; wsrep_bf_thd = NULL; + wsrep_TOI_pre_query = NULL; + wsrep_TOI_pre_query_len = 0; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1477,6 +1479,8 @@ void THD::init(void) wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_mysql_replicated = 0; wsrep_bf_thd = NULL; + wsrep_TOI_pre_query = NULL; + wsrep_TOI_pre_query_len = 0; #endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; diff --git a/sql/sql_class.h b/sql/sql_class.h index f6391f82b02..f1932cfe8c7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2381,6 +2381,9 @@ public: wsrep_stats_var* wsrep_status_vars; int wsrep_mysql_replicated; THD* wsrep_bf_thd; + const char* wsrep_TOI_pre_query; /* a query to apply before + the actual TOI query */ + size_t wsrep_TOI_pre_query_len; #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 657239d5b0e..2962b6bfbba 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2893,12 +2893,6 @@ case SQLCOM_PREPARE: if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->variables.option_bits|= OPTION_KEEP_LOG; /* regular create */ -#ifdef WITH_WSREP - if (!thd->is_current_stmt_binlog_format_row() || - !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) - WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, - NULL) -#endif /* WITH_WSREP */ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) { /* CREATE TABLE ... LIKE ... */ @@ -2907,6 +2901,12 @@ case SQLCOM_PREPARE: } else { +#ifdef WITH_WSREP + if (!thd->is_current_stmt_binlog_format_row() || + !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, + NULL) +#endif /* WITH_WSREP */ /* Regular CREATE TABLE */ res= mysql_create_table(thd, create_table, &create_info, &alter_info); @@ -8260,6 +8260,15 @@ wsrep_status_t wsrep_apply_cb(void* const ctx, #endif /* WSREP_PROC_INFO */ if (WSREP_OK != rcode) wsrep_write_rbr_buf(thd, buf, buf_len); + TABLE *tmp; + while ((tmp = thd->temporary_tables)) + { + WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", + thd->thread_id, + (tmp->s) ? tmp->s->db.str : "void", + (tmp->s) ? tmp->s->table_name.str : "void"); + close_temporary_table(thd, tmp, 1, 1); + } return rcode; } @@ -8447,6 +8456,10 @@ void wsrep_replication_process(THD *thd) mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); + if (thd->temporary_tables) + { + WSREP_DEBUG("Applier %lu, has temporary tables at exit", thd->thread_id); + } wsrep_return_from_bf_mode(thd, &shadow); DBUG_VOID_RETURN; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7d87b0b22db..332f9d1b80f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4752,6 +4752,49 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, uint not_used; DBUG_ENTER("mysql_create_like_table"); +#ifdef WITH_WSREP + if (!thd->wsrep_applier) + { + TABLE *tmp_table; + bool is_tmp_table= FALSE; + + for (tmp_table= thd->temporary_tables; tmp_table; tmp_table=tmp_table->next) + { + if (!strcmp(src_table->db, tmp_table->s->db.str) && + !strcmp(src_table->table_name, tmp_table->s->table_name.str)) + { + is_tmp_table= TRUE; + break; + } + } + if (!is_tmp_table) + { + WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL); + } + else + { + TABLE_LIST tbl; + bzero((void*) &tbl, sizeof(tbl)); + tbl.db= src_table->db; + tbl.table_name= tbl.alias= src_table->table_name; + tbl.table= tmp_table; + char buf[2048]; + String query(buf, sizeof(buf), system_charset_info); + query.length(0); // Have to zero it since constructor doesn't + + (void) store_create_info(thd, &tbl, &query, NULL, TRUE); + WSREP_DEBUG("TMP TABLE: %s", query.ptr()); + + thd->wsrep_TOI_pre_query= query.ptr(); + thd->wsrep_TOI_pre_query_len= query.length(); + + WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL); + + thd->wsrep_TOI_pre_query= NULL; + thd->wsrep_TOI_pre_query_len= 0; + } + } +#endif /* We the open source table to get its description in HA_CREATE_INFO @@ -4899,6 +4942,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, err: DBUG_RETURN(res); +#ifdef WITH_WSREP + error: + thd->wsrep_TOI_pre_query= NULL; + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ + } diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc index 5764be39093..ce8a46c6bd5 100644 --- a/sql/wsrep_check_opts.cc +++ b/sql/wsrep_check_opts.cc @@ -40,7 +40,7 @@ static struct opt opts[] = { { "wsrep_slave_threads", "1" }, // mysqld.cc { "bind_address", "0.0.0.0" }, // mysqld.cc - { "wsrep_sst_method","mysqldump" }, // mysqld.cc + { "wsrep_sst_method", "rsync" }, // mysqld.cc { "wsrep_sst_receive_address","AUTO"}, // mysqld.cc { "binlog_format", "ROW" }, // mysqld.cc { "wsrep_provider", "none" }, // mysqld.cc diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 8b682d579d8..bd934031fc3 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -75,7 +75,12 @@ void wsrep_register_hton(THD* thd, bool all) if (i->ht()->db_type == DB_TYPE_INNODB) { trans_register_ha(thd, all, wsrep_hton); - thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + + /* follow innodb read/write settting */ + if (i->is_trx_read_write()) + { + thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + } break; } } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 790cf45def4..f6ff3eecbcb 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -983,16 +983,23 @@ int wsrep_to_buf_helper( if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, 65536, MYF(MY_WME))) return 1; - Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); + int ret(0); + /* if there is prepare query, add event for it */ + if (thd->wsrep_TOI_pre_query) + { + Query_log_event ev(thd, thd->wsrep_TOI_pre_query, + thd->wsrep_TOI_pre_query_len, + FALSE, FALSE, FALSE, 0); + if (ev.write(&tmp_io_cache)) ret= 1; + } - Format_description_log_event *tmp_fd = new Format_description_log_event(4); - tmp_fd->checksum_alg = binlog_checksum_options; - tmp_fd->write(&tmp_io_cache); - delete tmp_fd; - + /* append the actual query */ + Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); if (ev.write(&tmp_io_cache)) ret= 1; + if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; + close_cached_file(&tmp_io_cache); return ret; } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 5aca1de6d0e..204a937ea8f 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -45,8 +45,9 @@ extern const char wsrep_defaults_file[]; #define WSREP_SST_OPT_BYPASS "--bypass" #define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_RSYNC "rsync" #define WSREP_SST_SKIP "skip" -#define WSREP_SST_DEFAULT WSREP_SST_MYSQLDUMP +#define WSREP_SST_DEFAULT WSREP_SST_RSYNC #define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_SST_AUTH_MASK "********" @@ -691,9 +692,11 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_PORT" '%s' " WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_DATA" '%s' " WSREP_SST_OPT_GTID" '%s:%lld'" "%s", - user, pswd, host, port, mysqld_port, mysqld_unix_port, uuid_str, + user, pswd, host, port, mysqld_port, mysqld_unix_port, + mysql_real_data_home, uuid_str, (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); WSREP_DEBUG("Running: '%s'", cmd_str); @@ -747,8 +750,8 @@ static int sst_flush_tables(THD* thd) else { /* make sure logs are flushed after global read lock acquired */ - err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG, - (TABLE_LIST*) 0, ¬_used); + err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG, + (TABLE_LIST*) 0, ¬_used); } if (err) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index b051254f3ff..8fa81376337 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -236,7 +236,17 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider); + /* 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. + + Note: releasing LOCK_global_system_variables may cause race condition, if + there can be several concurrent clients changing wsrep_provider + */ + mysql_mutex_unlock(&LOCK_global_system_variables); wsrep_stop_replication(thd); + mysql_mutex_lock(&LOCK_global_system_variables); + wsrep_deinit(); char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index ba0a70d2c48..cc0ac9d9613 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -52,6 +52,7 @@ Created 12/27/1996 Heikki Tuuri #include "eval0eval.h" #include "buf0lru.h" #ifdef WITH_WSREP +#include "ha_prototypes.h" extern my_bool wsrep_debug; #endif diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index ff63a8801ce..6898eb9cfcd 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -52,6 +52,7 @@ Created 12/27/1996 Heikki Tuuri #include "eval0eval.h" #include "buf0lru.h" #ifdef WITH_WSREP +#include "ha_prototypes.h" extern my_bool wsrep_debug; #endif diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index d40c96fad19..a1b32bdeed0 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -300,11 +300,14 @@ documentation and the manual for more information. %package -n MySQL-server%{product_suffix} %if %{defined with_wsrep} Version: %{mysql_version} -#Release: %{wsrep_version}.%{release} %endif Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases +%if %{defined with_wsrep} +Requires: %{distro_requires} rsync +%else Requires: %{distro_requires} +%endif %if %{defined susever} Provides: msqlormysql MySQL MySQL-server Conflicts: mysql mysql-server mysql-advanced mysql-server-advanced diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh index 507f83324b9..756d4f6783b 100644 --- a/support-files/wsrep.cnf.sh +++ b/support-files/wsrep.cnf.sh @@ -108,7 +108,7 @@ wsrep_notify_cmd= ## # State Snapshot Transfer method -wsrep_sst_method=mysqldump +wsrep_sst_method=rsync # Address which donor should send State Snapshot to. # Should be the address of THIS node. DON'T SET IT TO DONOR ADDRESS!!! From c942889d41e38eedc93bcf9106e9583b9015af47 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Fri, 23 Aug 2013 12:21:00 +0300 Subject: [PATCH 072/294] References: lp:1206129 - Merged revision 3904 from lp:~codership/codership-mysql/5.5-23 enable LOAD DATA transaction splitting Added new global variable: wsrep_load_data_splitting to control if splitting is wanted or not --- sql/sys_vars.cc | 5 +++++ sql/wsrep_mysqld.cc | 3 ++- sql/wsrep_mysqld.h | 2 ++ storage/innobase/handler/ha_innodb.cc | 32 ++++++++++++++++++++++++++- storage/xtradb/handler/ha_innodb.cc | 32 ++++++++++++++++++++++++++- 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5eb86c13ad5..84c971c67ba 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3834,6 +3834,11 @@ static Sys_var_ulong Sys_wsrep_mysql_replication_bundle( GLOBAL_VAR(wsrep_mysql_replication_bundle), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1000), DEFAULT(0), BLOCK_SIZE(1)); +static Sys_var_mybool Sys_wsrep_load_data_splitting( + "wsrep_load_data_splitting", "To commit LOAD DATA " + "transaction after every 10K rows inserted", + GLOBAL_VAR(wsrep_load_data_splitting), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); #endif /* WITH_WSREP */ static Sys_var_charptr Sys_ignore_db_dirs( diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index f6ff3eecbcb..4cf7fb38b81 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -48,7 +48,8 @@ ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery my_bool wsrep_replicate_myisam = 0; // enable myisam replication my_bool wsrep_log_conflicts = 0; // -ulong wsrep_mysql_replication_bundle = 0; +ulong wsrep_mysql_replication_bundle = 0; +my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals /* * End configuration options diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index bb1695563cf..33fbf2f3bff 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -97,6 +97,8 @@ extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; +extern ulong wsrep_mysql_replication_bundle; +extern my_bool wsrep_load_data_splitting; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 80bd2aadcb5..c0a21d521c9 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -130,6 +130,9 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, wsrep_key_part_t* key, size_t* key_len); +extern handlerton * wsrep_hton; +extern handlerton * binlog_hton; +extern void wsrep_cleanup_transaction(THD *thd); #endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; @@ -5608,7 +5611,8 @@ ha_innobase::write_row( || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP - || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) + || (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD) #endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { @@ -5651,6 +5655,20 @@ no_commit: */ ; } else if (src_table == prebuilt->table) { +#ifdef WITH_WSREP + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + + binlog_hton->commit(binlog_hton, user_thd, 1); + + wsrep_cleanup_transaction(user_thd); +#endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -5661,6 +5679,18 @@ no_commit: /* We will need an IX lock on the destination table. */ prebuilt->sql_stat_start = TRUE; } else { +#ifdef WITH_WSREP + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + binlog_hton->commit(binlog_hton, user_thd, 1); + wsrep_cleanup_transaction(user_thd); +#endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index cbd29255f1d..f0e3999414c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -147,6 +147,9 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, wsrep_key_part_t* key, size_t* key_len); +extern handlerton * wsrep_hton; +extern handlerton * binlog_hton; +extern void wsrep_cleanup_transaction(THD *thd); #endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; @@ -6533,7 +6536,8 @@ ha_innobase::write_row( || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP - || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) + || (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD) #endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { @@ -6576,6 +6580,20 @@ no_commit: */ ; } else if (src_table == prebuilt->table) { +#ifdef WITH_WSREP + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + + binlog_hton->commit(binlog_hton, user_thd, 1); + + wsrep_cleanup_transaction(user_thd); +#endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -6586,6 +6604,18 @@ no_commit: /* We will need an IX lock on the destination table. */ prebuilt->sql_stat_start = TRUE; } else { +#ifdef WITH_WSREP + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_ROLLBACK: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + binlog_hton->commit(binlog_hton, user_thd, 1); + wsrep_cleanup_transaction(user_thd); +#endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ From f68a7611d10083d72e358915f8fbe1258b7b7946 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 27 Aug 2013 09:06:04 +0300 Subject: [PATCH 073/294] References lp:1216904 - guaranteeing native "create table like.." processing when running without wsrep provider Merged the fix from lp:~codership/codership-mysql/5.5-23, rev 3906 --- sql/sql_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 332f9d1b80f..f08506181de 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4753,7 +4753,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, DBUG_ENTER("mysql_create_like_table"); #ifdef WITH_WSREP - if (!thd->wsrep_applier) + if (WSREP(thd) && !thd->wsrep_applier) { TABLE *tmp_table; bool is_tmp_table= FALSE; From 39f82b4e6ebed949ba17fe4884d96471574c1da1 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 27 Aug 2013 23:40:49 +0300 Subject: [PATCH 074/294] References: MDEV-4953 Calling ha_start_of_new_statement() for all table handlers under partition engine. This will enable innodb transactions to be declared as read/write. --- sql/ha_partition.h | 7 +++++++ sql/table.cc | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/sql/ha_partition.h b/sql/ha_partition.h index ebf9dcdb842..ac2a233427d 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1171,6 +1171,13 @@ public: DBUG_ASSERT(h == m_file[i]->ht); return h; } +#ifdef WITH_WSREP + void wsrep_reset_files() + { + for (uint i=0; i < m_tot_parts; i++) + m_file[i]->ha_start_of_new_statement(); + } +#endif /* WITH_WSREP */ }; #endif /* HA_PARTITION_INCLUDED */ diff --git a/sql/table.cc b/sql/table.cc index 7635e03ad6b..eea905805f8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -40,6 +40,9 @@ #include "sql_select.h" #include "sql_derived.h" #include "mdl.h" // MDL_wait_for_graph_visitor +#ifdef WITH_WSREP +#include "ha_partition.h" +#endif /* WITH_WSREP */ /* INFORMATION_SCHEMA name */ LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; @@ -3930,6 +3933,12 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) insert_values= 0; fulltext_searched= 0; file->ha_start_of_new_statement(); +#ifdef WITH_WSREP + if (file->ht->db_type == DB_TYPE_PARTITION_DB) + { + ((ha_partition*)file)->wsrep_reset_files(); + } +#endif reginfo.impossible_range= 0; created= TRUE; From c3d635bdc3becb736473a8f1f2a8c5ff886fe450 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 18 Sep 2013 14:59:51 +0200 Subject: [PATCH 075/294] cmake error on osx --- cmake/install_macros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index edf6af24f6a..bac824a477f 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -32,7 +32,7 @@ MACRO (INSTALL_DSYM_DIRECTORIES targets) # It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */ STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location}) IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY") - INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${INSTALL_LOCATION} COMPONENT Debuginfo) + INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${ARG_DESTINATION} COMPONENT Debuginfo) ENDIF() ENDFOREACH() ENDIF() From 427daab74f22450c11b5f517d4ae5a041ac61811 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 18 Sep 2013 20:55:58 +0200 Subject: [PATCH 076/294] fix broken (after merge) galera deb packaging --- cmake/install_macros.cmake | 4 ++-- debian/dist/Debian/mariadb-galera-server-5.5.files | 8 ++++---- debian/dist/Debian/rules | 2 +- debian/dist/Ubuntu/mariadb-galera-server-5.5.files | 8 ++++---- debian/dist/Ubuntu/rules | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index bac824a477f..b7e27ba5667 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -174,9 +174,9 @@ FUNCTION(INSTALL_DOCUMENTATION) ENDIF() IF(RPM) - SET(destination "${destination}/MariaDB-${group}-${VERSION}") + SET(destination "${destination}/MariaDB-Galera-${group}-${VERSION}") ELSEIF(DEB) - SET(destination "${destination}/mariadb-${group}-${MAJOR_VERSION}.${MINOR_VERSION}") + SET(destination "${destination}/mariadb-galera-${group}-${MAJOR_VERSION}.${MINOR_VERSION}") ENDIF() INSTALL(FILES ${files} DESTINATION ${destination} COMPONENT ${ARG_COMPONENT}) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files index 2a7da7b27bf..63f363fb2dc 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files @@ -1,4 +1,3 @@ -usr/README-wsrep usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so @@ -43,9 +42,10 @@ usr/bin/wsrep_sst_common usr/bin/wsrep_sst_mysqldump usr/bin/wsrep_sst_rsync usr/bin/wsrep_sst_xtrabackup -usr/share/doc/mariadb-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-server-5.5/INFO_SRC -usr/share/doc/mariadb-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-galera-server-5.5/INFO_SRC +usr/share/doc/mariadb-galera-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/README-wsrep usr/share/lintian/overrides/mariadb-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index 75a5ee57db2..dcd1b346a82 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -177,7 +177,7 @@ install: build $(TMP)/usr/share/mysql/mysql-log-rotate \ $(TMP)/usr/share/mysql/mysql.server \ $(TMP)/usr/share/mysql/binary-configure - nm -n $(BUILDDIR)/sql/mysqld |gzip -9 > $(TMP)/usr/share/doc/mariadb-server-5.5/mysqld.sym.gz + nm -n $(BUILDDIR)/sql/mysqld |gzip -9 > $(TMP)/usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz install -m 0755 debian/additions/echo_stderr $(TMP)/usr/share/mysql/ install -m 0755 debian/additions/debian-start $(TMP)/etc/mysql/ install -m 0755 debian/additions/debian-start.inc.sh $(TMP)/usr/share/mysql/ diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files index 2f2e233e5e3..ecea1184ac4 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files @@ -1,4 +1,3 @@ -usr/README-wsrep usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so @@ -45,9 +44,10 @@ usr/bin/wsrep_sst_common usr/bin/wsrep_sst_mysqldump usr/bin/wsrep_sst_rsync usr/bin/wsrep_sst_xtrabackup -usr/share/doc/mariadb-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-server-5.5/INFO_SRC -usr/share/doc/mariadb-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-galera-server-5.5/INFO_SRC +usr/share/doc/mariadb-galera-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/README-wsrep usr/share/lintian/overrides/mariadb-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 18f67812ec6..fc1d840d924 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -177,7 +177,7 @@ install: build $(TMP)/usr/share/mysql/mysql-log-rotate \ $(TMP)/usr/share/mysql/mysql.server \ $(TMP)/usr/share/mysql/binary-configure - nm -n $(BUILDDIR)/sql/mysqld |gzip -9 > $(TMP)/usr/share/doc/mariadb-server-5.5/mysqld.sym.gz + nm -n $(BUILDDIR)/sql/mysqld |gzip -9 > $(TMP)/usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz install -m 0755 debian/additions/echo_stderr $(TMP)/usr/share/mysql/ install -m 0755 debian/additions/debian-start $(TMP)/etc/mysql/ install -m 0755 debian/additions/debian-start.inc.sh $(TMP)/usr/share/mysql/ From 77fae5af0065664c3b90eebc4a0dbc4bd48efa3a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Sep 2013 09:21:17 +0200 Subject: [PATCH 077/294] updated test results --- mysql-test/r/mysqld--help.result | 7 ++++++- mysql-test/suite/sys_vars/r/all_vars.result | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 46fffb1c6df..47d66b5057d 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -878,6 +878,10 @@ The following options may be given as the first argument: To use a workaround forbad autoincrement value --wsrep-forced-binlog-format=name binlog format to take effect over user's choice + --wsrep-load-data-splitting + To commit LOAD DATA transaction after every 10K rows + inserted + (Defaults to on; use --skip-wsrep-load-data-splitting to disable.) --wsrep-log-conflicts To log multi-master conflicts --wsrep-max-ws-rows=# @@ -1180,6 +1184,7 @@ wsrep-dbug-option wsrep-debug FALSE wsrep-drupal-282555-workaround FALSE wsrep-forced-binlog-format NONE +wsrep-load-data-splitting TRUE wsrep-log-conflicts FALSE wsrep-max-ws-rows 131072 wsrep-max-ws-size 1073741824 @@ -1197,7 +1202,7 @@ wsrep-slave-threads 1 wsrep-sst-auth (No default value) wsrep-sst-donor wsrep-sst-donor-rejects-queries FALSE -wsrep-sst-method mysqldump +wsrep-sst-method rsync wsrep-sst-receive-address AUTO wsrep-start-position 00000000-0000-0000-0000-000000000000:-1 diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index b61a8aabf08..f18fad9815d 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -22,6 +22,7 @@ wsrep_dbug_option wsrep_debug wsrep_drupal_282555_workaround wsrep_forced_binlog_format +wsrep_load_data_splitting wsrep_log_conflicts wsrep_max_ws_rows wsrep_max_ws_size From c72126e043c42ccbc3e0e138dc3aef3950959158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 26 Sep 2013 16:43:49 +0300 Subject: [PATCH 078/294] Merge revisions 3907--3914 from lp:~codership/codership-mysql/5.5-23 ------------------------------------------------------------ revno: 3914 3kB/s | committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Thu 2013-09-12 15:00:46 +0400 message: References lp:1217653 - fix index-id evaluation of FOREIGN KEY, when referenced table without PRIMARY KEY ------------------------------------------------------------ revno: 3913 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Wed 2013-09-11 13:58:02 +0400 message: References lp:1217653 - fix index-id evaluation of FOREIGN KEY, when referenced table without PRIMARY KEY ------------------------------------------------------------ revno: 3912 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Fri 2013-09-06 13:13:48 +0300 message: References: lp:1212955 - releasing MDL after failed BEGIN and "SET AUTOCOMMIT" ------------------------------------------------------------ revno: 3911 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Wed 2013-09-04 10:52:31 +0300 message: References: lp:1123233 - avoiding to set wsrep_seqno_changed for replaying transactions Note, also missing transactions don't declare seqno_changed anymore. Earlier they would have caused crash at wsrep_cleanup_transaction phase. ------------------------------------------------------------ revno: 3910 [merge] committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Tue 2013-09-03 15:27:02 +0400 message: References lp:1049599 - expose desync functionality to the client ------------------------------------------------------------ revno: 3909 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Tue 2013-09-03 09:41:08 +0300 message: References: lp:1123233 - rollback for transaction which has not appended key information ------------------------------------------------------------ revno: 3908 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Sun 2013-09-01 13:29:12 +0400 message: lp:1201893 - fix command for default IP address ------------------------------------------------------------ revno: 3907 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Thu 2013-08-29 12:16:42 +0300 message: References: lp:1212955 - releasing transactional MDL locks after commit failures (e.g. certification failure). --- sql/mysqld.cc | 8 ++++-- sql/sql_parse.cc | 24 +++++++++++++++++ sql/sys_vars.cc | 11 ++++++++ sql/wsrep_hton.cc | 26 +++++++++++++----- sql/wsrep_mysqld.cc | 1 + sql/wsrep_mysqld.h | 6 +++++ sql/wsrep_utils.cc | 2 +- sql/wsrep_var.cc | 39 +++++++++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 4 ++- storage/xtradb/handler/ha_innodb.cc | 4 ++- 10 files changed, 113 insertions(+), 12 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f7327aec99a..1777507d3bd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -713,6 +713,7 @@ 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; int wsrep_replaying= 0; static void wsrep_close_threads(THD* thd); #endif @@ -788,7 +789,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst, key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init, - key_LOCK_wsrep_slave_threads; + key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync; #endif PSI_mutex_key key_RELAYLOG_LOCK_index; @@ -867,6 +868,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0}, { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL}, #endif { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} }; @@ -2072,6 +2074,7 @@ static void clean_up_mutexes() (void) mysql_mutex_destroy(&LOCK_wsrep_replaying); (void) mysql_cond_destroy(&COND_wsrep_replaying); (void) mysql_mutex_destroy(&LOCK_wsrep_slave_threads); + (void) mysql_mutex_destroy(&LOCK_wsrep_desync); #endif mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); @@ -4148,6 +4151,8 @@ static int init_thread_environment() 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); #endif return 0; } @@ -9190,4 +9195,3 @@ template class I_List; template class I_List; template class I_List_iterator; #endif - diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8808aa9cc6a..df11e4bdc8a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2412,7 +2412,11 @@ mysql_execute_command(THD *thd) thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); /* Commit the normal transaction if one is active. */ if (trans_commit_implicit(thd)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id); goto error; + } /* Release metadata locks acquired in this transaction. */ thd->mdl_context.release_transactional_locks(); } @@ -4134,7 +4138,11 @@ end_with_restore_list: case SQLCOM_BEGIN: if (trans_begin(thd, lex->start_transaction_opt)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id); goto error; + } my_ok(thd); break; case SQLCOM_COMMIT: @@ -4148,7 +4156,11 @@ end_with_restore_list: (thd->variables.completion_type == 2 && lex->tx_release != TVL_NO)); if (trans_commit(thd)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id); goto error; + } thd->mdl_context.release_transactional_locks(); /* Begin transaction with the same isolation level. */ if (tx_chain) @@ -4181,7 +4193,11 @@ end_with_restore_list: (thd->variables.completion_type == 2 && lex->tx_release != TVL_NO)); if (trans_rollback(thd)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id); goto error; + } thd->mdl_context.release_transactional_locks(); /* Begin transaction with the same isolation level. */ if (tx_chain) @@ -4725,7 +4741,11 @@ create_sp_error: break; case SQLCOM_XA_COMMIT: if (trans_xa_commit(thd)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id); goto error; + } thd->mdl_context.release_transactional_locks(); /* We've just done a commit, reset transaction @@ -4736,7 +4756,11 @@ create_sp_error: break; case SQLCOM_XA_ROLLBACK: if (trans_xa_rollback(thd)) + { + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id); goto error; + } thd->mdl_context.release_transactional_locks(); /* We've just done a rollback, reset transaction diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 84c971c67ba..5b4cc4ddb64 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2534,6 +2534,8 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) if (trans_commit_stmt(thd) || trans_commit(thd)) { thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; + thd->mdl_context.release_transactional_locks(); + WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id); return true; } /* @@ -3808,6 +3810,15 @@ static Sys_var_enum Sys_wsrep_OSU_method( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0)); +static PolyLock_mutex PLock_wsrep_desync(&LOCK_wsrep_desync); +static Sys_var_mybool Sys_wsrep_desync ( + "wsrep_desync", "To desynchronize the node from the cluster", + GLOBAL_VAR(wsrep_desync), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + &PLock_wsrep_desync, NOT_IN_BINLOG, + ON_CHECK(wsrep_desync_check), + ON_UPDATE(wsrep_desync_update)); + static Sys_var_enum Sys_wsrep_forced_binlog_format( "wsrep_forced_binlog_format", "binlog format to take effect over user's choice", GLOBAL_VAR(wsrep_forced_binlog_format), diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index bd934031fc3..3756f54ab48 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -331,9 +331,17 @@ wsrep_run_wsrep_commit( } if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_handle.trx_id) { - WSREP_WARN("SQL statement was ineffective: %s\n => Skipping replication", thd->query()); - } - else if (!rcode) + WSREP_WARN("SQL statement was ineffective, THD: %lu, buf: %d\n" + "QUERY: %s\n" + " => Skipping replication", + thd->thread_id, data_len, thd->query()); + if (wsrep_debug) + { + wsrep_write_rbr_buf(thd, rbr_data, data_len); + } + rcode = WSREP_TRX_FAIL; + } + else if (!rcode) { rcode = wsrep->pre_commit( wsrep, @@ -343,13 +351,14 @@ wsrep_run_wsrep_commit( data_len, (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, &thd->wsrep_trx_seqno); - if (rcode == WSREP_TRX_MISSING) { + switch (rcode) { + case WSREP_TRX_MISSING: WSREP_WARN("Transaction missing in provider, thd: %ld, SQL: %s", thd->thread_id, thd->query()); wsrep_write_rbr_buf(thd, rbr_data, data_len); - rcode = WSREP_OK; - } else if (rcode == WSREP_BF_ABORT) { + break; + case WSREP_BF_ABORT: mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_conflict_state = MUST_REPLAY; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -358,8 +367,11 @@ wsrep_run_wsrep_commit( WSREP_DEBUG("replaying increased: %d, thd: %lu", wsrep_replaying, thd->thread_id); mysql_mutex_unlock(&LOCK_wsrep_replaying); + break; + default: + thd->wsrep_seqno_changed = true; + break; } - thd->wsrep_seqno_changed = true; } else { WSREP_ERROR("I/O error reading from thd's binlog iocache: " "errno=%d, io cache code=%d", my_errno, cache->error); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 4cf7fb38b81..2196a7b050c 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -50,6 +50,7 @@ my_bool wsrep_replicate_myisam = 0; // enable myisam replication my_bool wsrep_log_conflicts = 0; // ulong wsrep_mysql_replication_bundle = 0; my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals +my_bool wsrep_desync = 0; // desynchronize the node from the cluster /* * End configuration options diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 33fbf2f3bff..607014e3fa9 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -93,6 +93,7 @@ extern long wsrep_max_protocol_version; extern long wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; extern ulong wsrep_OSU_method_options; +extern my_bool wsrep_desync; extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; extern my_bool wsrep_log_conflicts; @@ -173,6 +174,9 @@ extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_slave_threads_check CHECK_ARGS; 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_before_SE(); // initialize wsrep before storage // engines (true) or after (false) extern int wsrep_init(); @@ -349,6 +353,7 @@ extern long wsrep_max_ws_rows; extern int wsrep_to_isolation; extern my_bool wsrep_certify_nonPK; extern mysql_mutex_t LOCK_wsrep_slave_threads; +extern mysql_mutex_t LOCK_wsrep_desync; extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready; @@ -363,6 +368,7 @@ 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; struct TABLE_LIST; int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 19ffb101841..53d0f7c449e 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -359,7 +359,7 @@ size_t guess_ip (char* buf, size_t buf_len) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; #elif defined(__APPLE__) || defined(__FreeBSD__) - const char cmd[] = "route -nv get 8.8.8.8 | tail -n1 | awk '{print $5}'"; + const char cmd[] = "/sbin/route -nv get 8.8.8.8 | tail -n1 | awk '{print $(NF)}'"; #else char *cmd; #error "OS not supported" diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 8fa81376337..94ac902506f 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -470,6 +470,45 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) } return false; } + +bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) +{ + bool new_wsrep_desync = var->value->val_bool(); + if (wsrep_desync == new_wsrep_desync) { + if (new_wsrep_desync) { + push_warning (thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_VALUE_FOR_VAR, + "'wsrep_desync' is already ON."); + } else { + push_warning (thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_VALUE_FOR_VAR, + "'wsrep_desync' is already OFF."); + } + } + return 0; +} + +bool wsrep_desync_update (sys_var *self, THD* thd, enum_var_type type) +{ + wsrep_status_t ret(WSREP_WARNING); + if (wsrep_desync) { + ret = wsrep->desync (wsrep); + if (ret != WSREP_OK) { + WSREP_WARN ("SET desync failed %d for %s", ret, thd->query()); + my_error (ER_CANNOT_USER, MYF(0), "'desync'", thd->query()); + return true; + } + } else { + ret = wsrep->resync (wsrep); + if (ret != WSREP_OK) { + WSREP_WARN ("SET resync failed %d for %s", ret, thd->query()); + my_error (ER_CANNOT_USER, MYF(0), "'resync'", thd->query()); + return true; + } + } + return false; +} + /* * Status variables stuff below */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 61acf1cd73a..b291f0957b8 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7234,8 +7234,10 @@ wsrep_append_foreign_key( UT_LIST_GET_FIRST(foreign->foreign_table->indexes); int i = 0; while (idx != NULL && idx != idx_target) { + if (innobase_strcasecmp (idx->name, innobase_index_reserve_name) != 0) { + i++; + } idx = UT_LIST_GET_NEXT(indexes, idx); - i++; } ut_a(idx); key[0] = (char)i; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 654b9d644c8..617c29a6536 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -8268,8 +8268,10 @@ wsrep_append_foreign_key( UT_LIST_GET_FIRST(foreign->foreign_table->indexes); int i = 0; while (idx != NULL && idx != idx_target) { + if (innobase_strcasecmp (idx->name, innobase_index_reserve_name) != 0) { + i++; + } idx = UT_LIST_GET_NEXT(indexes, idx); - i++; } ut_a(idx); key[0] = (char)i; From ac5d1d761adaae3200559f64b61d6ecd5b005f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 26 Sep 2013 17:51:01 +0300 Subject: [PATCH 079/294] Merged revisions 3916--3921 from lp:~codership/codership-mysql/5.5-23 ------------------------------------------------------------ revno: 3921 fixes bug: https://launchpad.net/bugs/1228149 committer: Alexey Yurchenko branch nick: 5.5-23 timestamp: Mon 2013-09-23 18:29:42 +0300 message: References lp:1228149 - fixing typos. ------------------------------------------------------------ revno: 3920 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Fri 2013-09-20 15:43:18 +0400 message: References lp:1201893 - remove setenv("WSREP_LOG_DIR") from ha_innodb.cc ------------------------------------------------------------ revno: 3919 tags: wsrep_23.7.6 fixes bug: https://launchpad.net/bugs/1087368 committer: Alexey Yurchenko branch nick: 5.5-23 timestamp: Thu 2013-09-19 06:00:43 +0300 message: References lp:1087368 - fix to preserve the order of options in case --wsrep-new-cluster is i n the middle of option list ------------------------------------------------------------ revno: 3918 committer: Alexey Yurchenko branch nick: 5.5-23\ timestamp: Wed 2013-09-18 23:22:55 +0300 message: bumped wsrep patch version number to 7.6 ------------------------------------------------------------ revno: 3917 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Wed 2013-09-18 20:11:39 +0400 message: References lp:1218944 - wsrep_sst_rsync now recognizes log_group_home_dir ------------------------------------------------------------ revno: 3916 fixes bug: https://launchpad.net/bugs/1224775 committer: Alexey Yurchenko branch nick: 5.5-23 timestamp: Sun 2013-09-15 21:29:57 +0300 message: References lp:1224775 - reworked wsrep_recover to create temporary log file in $DATADIR. Plus cleaned up that function slightly. --- cmake/wsrep.cmake | 2 +- mysys/default.c | 12 +--- scripts/mysqld_safe.sh | 3 - scripts/wsrep_sst_rsync.sh | 103 ++++++++++++++++++---------------- support-files/mysql.server.sh | 4 +- 5 files changed, 61 insertions(+), 63 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 608b33b31a1..6a4e9a21049 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7.5") +SET(WSREP_PATCH_VERSION "7.6") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/mysys/default.c b/mysys/default.c index f5939acc923..8ed1a454490 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -111,15 +111,9 @@ static my_bool find_wsrep_new_cluster (int* argc, char* argv[]) { ret= TRUE; *argc -= 1; - if (*argc == i) - { // last argument, just zero it up - argv[i]= NULL; - } - else - { // not the last argument, copy the last one over and zero that up. - argv[i]= argv[*argc]; - argv[*argc]= NULL; - } + /* preserve the order of remaining arguments */ + memmove(&argv[i], &argv[i + 1], (*argc - i)*sizeof(argv[i])); + argv[*argc]= NULL; } } diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 43a8508c7c0..3b758f77eec 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -947,9 +947,6 @@ have_sleep=1 # maximum number of wsrep restarts max_wsrep_restarts=0 -# maximum number of wsrep restarts -max_wsrep_restarts=0 - while true do rm -f "$pid_file" # Some extra safety diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 7cd232e0887..b3535480c67 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -67,6 +67,15 @@ check_pid_and_port() MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" rm -rf "$MAGIC_FILE" +SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P) +WSREP_LOG_DIR=${WSREP_LOG_DIR:-$($SCRIPT_DIR/my_print_defaults --defaults-file "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \ + | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' | cut -b 29- )} +if [ -n "${WSREP_LOG_DIR:-""}" ]; then + WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P) +else + WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P) +fi + # Old filter - include everything except selected # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ # --exclude '*.conf' --exclude core --exclude 'galera.*' \ @@ -74,9 +83,8 @@ rm -rf "$MAGIC_FILE" # --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') # New filter - exclude everything except dirs (schemas) and innodb files -FILTER=(-f '- lost+found' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /ib_logfile*' -f '+ */' -f '-! */*') -# Old versions of rsync have a bug transferring filter rules to daemon, so specify filter rules directly to daemon -FILTER_DAEMON="- lost+found + /ib_lru_dump + /ibdata* + ib_logfile* + */ -! */*" +FILTER=(-f '- /lost+found' -f '- /.fseventsd' -f '- /.Trashes' + -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /*/' -f '- /*') if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then @@ -107,54 +115,58 @@ then # first, the normal directories, so that we can detect incompatible protocol RC=0 - rsync --archive --no-times --ignore-times --inplace --delete --quiet \ - --no-recursive --dirs \ + rsync --owner --group --perms --links --specials \ + --ignore-times --inplace --dirs --delete --quiet \ $WHOLE_FILE_OPT "${FILTER[@]}" "$WSREP_SST_OPT_DATA/" \ - rsync://$WSREP_SST_OPT_ADDR-with_filter || RC=$? + rsync://$WSREP_SST_OPT_ADDR >&2 || RC=$? - [ $RC -ne 0 ] && wsrep_log_error "rsync returned code $RC:" + if [ "$RC" -ne 0 ]; then + wsrep_log_error "rsync returned code $RC:" - case $RC in - 0) RC=0 # Success - ;; - 12) RC=71 # EPROTO - wsrep_log_error \ - "rsync server on the other end has incompatible protocol. " \ - "Make sure you have the same version of rsync on all nodes." - ;; - 22) RC=12 # ENOMEM - ;; - *) RC=255 # unknown error - ;; - esac + case $RC in + 12) RC=71 # EPROTO + wsrep_log_error \ + "rsync server on the other end has incompatible protocol. " \ + "Make sure you have the same version of rsync on all nodes." + ;; + 22) RC=12 # ENOMEM + ;; + *) RC=255 # unknown error + ;; + esac + exit $RC + fi - [ $RC -ne 0 ] && exit $RC + # second, we transfer InnoDB log files + rsync --owner --group --perms --links --specials \ + --ignore-times --inplace --dirs --delete --quiet \ + $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '- **' "$WSREP_LOG_DIR/" \ + rsync://$WSREP_SST_OPT_ADDR-log_dir >&2 || RC=$? + + if [ $RC -ne 0 ]; then + wsrep_log_error "rsync innodb_log_group_home_dir returned code $RC:" + exit 255 # unknown error + fi # then, we parallelize the transfer of database directories, use . so that pathconcatenation works - pushd "$WSREP_SST_OPT_DATA" 1>/dev/null + pushd "$WSREP_SST_OPT_DATA" >/dev/null count=1 [ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo) [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu) find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -I{} -0 -P $count \ - rsync --archive --no-times --ignore-times --inplace --delete --quiet \ - $WHOLE_FILE_OPT "$WSREP_SST_OPT_DATA"/{}/ \ - rsync://$WSREP_SST_OPT_ADDR/{} || RC=$? + rsync --owner --group --perms --links --specials \ + --ignore-times --inplace --recursive --delete --quiet \ + $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ + rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$? - popd 1>/dev/null - - [ $RC -ne 0 ] && wsrep_log_error "find/rsync returned code $RC:" - - case $RC in - 0) RC=0 # Success - ;; - *) RC=255 # unknown error - ;; - esac - - [ $RC -ne 0 ] && exit $RC + popd >/dev/null + if [ $RC -ne 0 ]; then + wsrep_log_error "find/rsync returned code $RC:" + exit 255 # unknown error + fi else # BYPASS wsrep_log_info "Bypassing state dump." @@ -203,19 +215,14 @@ then cat << EOF > "$RSYNC_CONF" pid file = $RSYNC_PID use chroot = no -[$MODULE-with_filter] - path = $WSREP_SST_OPT_DATA - read only = no - timeout = 300 - uid = $MYUID - gid = $MYGID - filter = $FILTER_DAEMON +read only = no +timeout = 300 +uid = $MYUID +gid = $MYGID [$MODULE] path = $WSREP_SST_OPT_DATA - read only = no - timeout = 300 - uid = $MYUID - gid = $MYGID +[$MODULE-log_dir] + path = $WSREP_LOG_DIR EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 63c449b2228..911924c7ee2 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -424,10 +424,10 @@ case "$mode" in fi exit $r ;; - 'boostrap') + 'bootstrap') # Bootstrap the cluster, start the first node # that initiate the cluster - echo $echo_n "Bootstrapping cluster)" + echo $echo_n "Bootstrapping the cluster" $0 start $other_args --wsrep-new-cluster ;; *) From 8ad1b5b1086b6791b95a33c664184bfb56993d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Sep 2013 13:01:14 +0300 Subject: [PATCH 080/294] Updated test results because of new system variables and a new lock variable. --- mysql-test/r/mysqld--help.result | 2 ++ mysql-test/suite/perfschema/r/all_instances.result | 1 + mysql-test/suite/sys_vars/r/all_vars.result | 1 + 3 files changed, 4 insertions(+) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 47d66b5057d..5262b01e08a 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -874,6 +874,7 @@ The following options may be given as the first argument: --wsrep-dbug-option=name DBUG options to provider library --wsrep-debug To enable debug level logging + --wsrep-desync To desynchronize the node from the cluster --wsrep-drupal-282555-workaround To use a workaround forbad autoincrement value --wsrep-forced-binlog-format=name @@ -1182,6 +1183,7 @@ wsrep-convert-LOCK-to-trx FALSE wsrep-data-home-dir wsrep-dbug-option wsrep-debug FALSE +wsrep-desync FALSE wsrep-drupal-282555-workaround FALSE wsrep-forced-binlog-format NONE wsrep-load-data-splitting TRUE diff --git a/mysql-test/suite/perfschema/r/all_instances.result b/mysql-test/suite/perfschema/r/all_instances.result index 34144dfecb1..bc3008dc771 100644 --- a/mysql-test/suite/perfschema/r/all_instances.result +++ b/mysql-test/suite/perfschema/r/all_instances.result @@ -68,6 +68,7 @@ wait/synch/mutex/sql/LOCK_thread_count wait/synch/mutex/sql/LOCK_user_conn wait/synch/mutex/sql/LOCK_user_locks wait/synch/mutex/sql/LOCK_uuid_short_generator +wait/synch/mutex/sql/LOCK_wsrep_desync wait/synch/mutex/sql/LOCK_wsrep_ready wait/synch/mutex/sql/LOCK_wsrep_replaying wait/synch/mutex/sql/LOCK_wsrep_rollback diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index f18fad9815d..adfd9f3bbe6 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -20,6 +20,7 @@ wsrep_convert_lock_to_trx wsrep_data_home_dir wsrep_dbug_option wsrep_debug +wsrep_desync wsrep_drupal_282555_workaround wsrep_forced_binlog_format wsrep_load_data_splitting From decd08408b7802543cd953c2f6b396e70ee865d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Sep 2013 17:07:44 +0300 Subject: [PATCH 081/294] Fix merge error. --- debian/dist/Debian/control | 2 -- debian/dist/Ubuntu/control | 2 -- 2 files changed, 4 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 9276d122105..d2962c0cd7a 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -11,8 +11,6 @@ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria Package: mariadb-galera-server-5.5 -Conflicts: mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33), - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index eeb55109766..7234fdb8bfb 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -11,8 +11,6 @@ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria Package: mariadb-galera-server-5.5 -Conflicts: mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33), - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl From 370a67679cc886f512d1f076a00a29e68abed900 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 27 Sep 2013 22:32:49 +0200 Subject: [PATCH 082/294] revert the change for auto-rpm-packages for plugins. galera tree should only build galera-server package --- cmake/plugin.cmake | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index afc359d1d09..b06d6ac9ca3 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -207,17 +207,7 @@ MACRO(MYSQL_ADD_PLUGIN) SET_TARGET_PROPERTIES(${target} PROPERTIES OUTPUT_NAME "${ARG_MODULE_OUTPUT_NAME}") # Install dynamic library - IF(ARG_COMPONENT) - IF(RPM AND NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT}) - SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT} PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB-server" PARENT_SCOPE) - - # workarounds for cmake issues #13248 and #12864: - SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_PROVIDES "cmake_bug_13248" PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_OBSOLETES "cmake_bug_13248" PARENT_SCOPE) - ENDIF() - ELSE() + IF(NOT ARG_COMPONENT) SET(ARG_COMPONENT Server) ENDIF() MYSQL_INSTALL_TARGETS(${target} DESTINATION ${INSTALL_PLUGINDIR} COMPONENT ${ARG_COMPONENT}) From 239dcdaa909cba065b9e6c83e59baef25a35eb58 Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Sun, 29 Sep 2013 23:53:10 +0300 Subject: [PATCH 083/294] References lp:1232890 - Rows_log_event type cast only for row events --- sql/sql_parse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index df11e4bdc8a..30c496561ac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8222,11 +8222,11 @@ static inline wsrep_status_t wsrep_apply_rbr( DBUG_RETURN(WSREP_FATAL); } - if (ev->get_type_code() != TABLE_MAP_EVENT && + if ((ev->get_type_code() == WRITE_ROWS_EVENT || + ev->get_type_code() == UPDATE_ROWS_EVENT || + ev->get_type_code() == DELETE_ROWS_EVENT) && ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)) { - // TODO: combine with commit on higher level common for the query ws - thd->wsrep_rli->cleanup_context(thd, 0); if (error == 0) From 4e00dd68612806e03494921bb573de470fa3e64b Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Mon, 30 Sep 2013 23:14:31 +0300 Subject: [PATCH 084/294] References: lp:1233353 - releasing explicit MDL locks for BF aborted transactions --- sql/mdl.cc | 7 ++++++- sql/mdl.h | 3 +++ sql/sql_base.cc | 6 ++++-- sql/sql_parse.cc | 3 +++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sql/mdl.cc b/sql/mdl.cc index 32a4d8cbbf5..fe8efd3e6cd 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -2737,7 +2737,12 @@ void MDL_context::release_locks_stored_before(enum_mdl_duration duration, DBUG_VOID_RETURN; } - +#ifdef WITH_WSREP +void MDL_context::release_explicit_locks() +{ + release_locks_stored_before(MDL_EXPLICIT, NULL); +} +#endif /** Release all explicit locks in the context which correspond to the same name/object as this lock request. diff --git a/sql/mdl.h b/sql/mdl.h index a951ef40d83..50a2c2d815a 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -678,6 +678,9 @@ public: void release_statement_locks(); void release_transactional_locks(); +#ifdef WITH_WSREP + void release_explicit_locks(); +#endif void rollback_to_savepoint(const MDL_savepoint &mdl_savepoint); inline THD *get_thd() const { return m_thd; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8d25e100bd1..9fc92f20556 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9433,11 +9433,13 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, { mysql_mutex_assert_owner(&LOCK_open); } - +#ifdef WITH_WSREP + /* if thd was BF aborted, exclusive locks were canceled */ +#else DBUG_ASSERT(remove_type == TDC_RT_REMOVE_UNUSED || thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, MDL_EXCLUSIVE)); - +#endif /* WITH_WSREP */ key_length= create_table_def_key(key, db, table_name); if ((share= (TABLE_SHARE*) my_hash_search(&table_def_cache,(uchar*) key, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 30c496561ac..fdb042f3737 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8049,6 +8049,9 @@ static void wsrep_client_rollback(THD *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 (%ld)", thd->thread_id); From 20afd6b1c3f39e6ae9cfb4e2e63a2ae0028a99fe Mon Sep 17 00:00:00 2001 From: Seppo Jaakola Date: Tue, 1 Oct 2013 00:28:54 +0300 Subject: [PATCH 085/294] References lp:587170 - merged fix in from wsrep-5.5-23 branch This branch is now in position 3924 in wsrep-5.5-23 --- sql/wsrep_mysqld.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 2196a7b050c..14bc3e54845 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -714,7 +714,7 @@ bool wsrep_start_replication() uint64_t caps = wsrep->capabilities (wsrep); wsrep_incremental_data_collection = - (caps & WSREP_CAP_WRITE_SET_INCREMENTS); + !!(caps & WSREP_CAP_WRITE_SET_INCREMENTS); char* opts= wsrep->options_get(wsrep); if (opts) @@ -1254,6 +1254,12 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (!ret) { thd->wsrep_exec_mode= TOTAL_ORDER; + /* It makes sense to set auto_increment_* to defaults in TOI operations */ + if (wsrep_auto_increment_control) + { + thd->variables.auto_increment_offset = 1; + thd->variables.auto_increment_increment = 1; + } } } return ret; From eb29ce250aaefb359cc9d85419931560f3d74aca Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 22 Nov 2013 14:30:00 -0500 Subject: [PATCH 086/294] MDEV-3895 Version naming for MariaDB-Galera builds This patch fixes both the reported issues : (1) Included '-wsrep' to the server version information. > select @@version; +-----------------------------+ | @@version | +-----------------------------+ | 5.5.33a-MariaDB-wsrep-debug | +-----------------------------+ (2) The @@version_comment would no longer have XXXX in the wsrep version information in case cmake couldn't determine the current bzr revision. --- cmake/wsrep.cmake | 28 +++++++++++++++++++++------- sql/mysqld.cc | 5 ++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 6a4e9a21049..cae3a7d6ad9 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -1,4 +1,5 @@ # Copyright (c) 2011, Codership Oy . +# Copyright (c) 2013, Monty Program Ab. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,20 +20,25 @@ # Set the patch version SET(WSREP_PATCH_VERSION "7.6") -# Obtain patch revision number +# Obtain patch revision number: +# The script tries to probe the bzr revision number using $ENV{WSREP_REV}, and +# "bzr revno" if the WSREP_REV is not defined. In case both fail, the revision +# information is not appended to the wsrep patch version. + +# 1: $ENV{WSREP_REV} SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) + +# 2: bzr revno IF(NOT WSREP_PATCH_REVNO) EXECUTE_PROCESS( COMMAND bzr revno OUTPUT_VARIABLE WSREP_PATCH_REVNO RESULT_VARIABLE RESULT ) + STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_PATCH_REVNO "${WSREP_PATCH_REVNO}") #FILE(WRITE "wsrep_config" "Debug: WSREP_PATCH_REVNO result: ${RESULT}\n") ENDIF() -IF(NOT WSREP_PATCH_REVNO) - SET(WSREP_PATCH_REVNO "XXXX") -ENDIF() # Obtain wsrep API version EXECUTE_PROCESS( @@ -43,9 +49,17 @@ EXECUTE_PROCESS( #FILE(WRITE "wsrep_config" "Debug: WSREP_API_VERSION result: ${RESULT}\n") STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_API_VERSION "${WSREP_API_VERSION}") -SET(WSREP_VERSION - "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" -) +IF(NOT WSREP_PATCH_REVNO) + MESSAGE(WARNING "Could not determine bzr revision number, WSREP_VERSION will " + "not contain the revision number.") + SET(WSREP_VERSION + "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}" + ) +ELSE() + SET(WSREP_VERSION + "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}.r${WSREP_PATCH_REVNO}" + ) +ENDIF() OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ON) IF (WITH_WSREP) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1777507d3bd..3b0009b5ca9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2008, 2012, Monty Program Ab + Copyright (c) 2008, 2013, Monty Program Ab 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 @@ -8867,6 +8867,9 @@ void set_server_version(void) #ifdef EMBEDDED_LIBRARY end= strmov(end, "-embedded"); #endif +#ifdef WITH_WSREP + end= strmov(end, "-wsrep"); +#endif #ifndef DBUG_OFF if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug")) end= strmov(end, "-debug"); From 0e248e62bdaf881f8b07b97e361d44ee30933bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 25 Nov 2013 11:09:48 +0200 Subject: [PATCH 087/294] Merged revisions 2925--3929 from from lp:~codership/codership-mysql/5.5-23 ------------------------------------------------------------ revno: 3929 [merge] fixes bug: https://launchpad.net/bugs/1243150 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Wed 2013-10-23 20:05:01 +0300 message: 8kB/s - References lp:1243150 - initial wsrep hton cleanups * Removed wsrep_seqno_changed boolean * wsrep_cleanup_transaction() is now called explicitly whenever it is clear that transaction has come to an end * wsrep_trans_cache_is_empty() now checks from cache_mngr recardless of command type * Separated call to wsrep->post_commit() to own function, called from transaction.cc whenever appropriate * wsrep_thd_is_brute_force() now investigates only thd->wsrep_exec_mode * More comments and debug time assertions * Debug code to check that wsrep position stored in InnoDB is monotinically increasing. Enabled with UNIV_DEBUG ------------------------------------------------------------ revno: 3928 fixes bug: https://launchpad.net/bugs/1237889 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Tue 2013-10-22 22:01:20 +0300 message: References lp:1237889 - reverting fix in r3926, it broke crash recovery ------------------------------------------------------------ revno: 3927 fixes bug: https://launchpad.net/bugs/1240040 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Tue 2013-10-15 14:46:15 +0300 message: References lp:1240040 - added WSREP_MYSQL_DB as a key for DROP VIEW ------------------------------------------------------------ revno: 3926 fixes bug: https://launchpad.net/bugs/1237889 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Thu 2013-10-10 14:22:58 +0300 message: References lp:1237889 - register wsrep hton only if thd->wsrep_exec_mode == LO CAL_STATE ------------------------------------------------------------ revno: 3925 fixes bug: https://launchpad.net/bugs/1235635 committer: Alexey Yurchenko branch nick: 5.5-23 timestamp: Sat 2013-10-05 18:03:06 +0300 message: References lp:1235635 - fixed the warning by initializing c_lock to NULL. --- sql/handler.cc | 15 +-- sql/log.cc | 15 +-- sql/sql_class.cc | 15 +-- sql/sql_class.h | 13 --- sql/sql_parse.cc | 24 ++-- sql/transaction.cc | 19 +++ sql/wsrep_hton.cc | 204 ++++++++++++++++++++++++--------- sql/wsrep_mysqld.cc | 35 ++++-- sql/wsrep_mysqld.h | 6 +- storage/innobase/trx/trx0sys.c | 37 ++++++ storage/xtradb/trx/trx0sys.c | 37 ++++++ 11 files changed, 291 insertions(+), 129 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index a98870d93f2..4666d4c8ad2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1218,11 +1218,7 @@ int ha_commit_trans(THD *thd, bool all) { /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) -#ifdef WITH_WSREP - thd->transaction.cleanup(thd); -#else - thd->transaction.cleanup(); -#endif /* WITH_WSREP */ + thd->transaction.cleanup(); DBUG_RETURN(0); } @@ -1459,11 +1455,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) } /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) -#ifdef WITH_WSREP - thd->transaction.cleanup(thd); -#else thd->transaction.cleanup(); -#endif /* WITH_WSREP */ #ifdef WITH_WSREP if (WSREP(thd)) thd_proc_info(thd, tmp_info); #endif /* WITH_WSREP */ @@ -1541,11 +1533,8 @@ int ha_rollback_trans(THD *thd, bool all) } /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) -#ifdef WITH_WSREP - thd->transaction.cleanup(thd); -#else thd->transaction.cleanup(); -#endif /* WITH_WSREP */ + if (all) thd->transaction_rollback_request= FALSE; diff --git a/sql/log.cc b/sql/log.cc index c2604891d2d..0fb6cd18690 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -526,20 +526,9 @@ IO_CACHE * get_trans_log(THD * thd) bool wsrep_trans_cache_is_empty(THD *thd) { - bool res= TRUE; - - if (thd_sql_command((const THD*) thd) != SQLCOM_SELECT) - res= FALSE; - else - { - binlog_cache_mngr *const cache_mngr= + binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - if (cache_mngr) - { - res= cache_mngr->trx_cache.empty(); - } - } - return res; + return (!cache_mngr || cache_mngr->trx_cache.empty()); } void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f4c393dae0f..61ed8c014b8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -811,7 +811,7 @@ extern "C" const char *wsrep_thd_exec_mode_str(THD *thd) (!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 == TOTAL_ORDER) ? "total order" : (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void"; } @@ -875,7 +875,7 @@ extern "C" my_thread_id wsrep_thd_thread_id(THD *thd) } extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd) { - return (thd) ? thd->wsrep_trx_seqno : -1; + return (thd) ? thd->wsrep_trx_seqno : WSREP_SEQNO_UNDEFINED; } extern "C" query_id_t wsrep_thd_query_id(THD *thd) { @@ -1000,6 +1000,7 @@ THD::THD() wsrep_applier(is_applier), wsrep_applier_closing(FALSE), wsrep_client_thread(0), + wsrep_trx_seqno(WSREP_SEQNO_UNDEFINED), #endif m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) @@ -1108,7 +1109,6 @@ THD::THD() //wsrep_retry_autocommit= ::wsrep_retry_autocommit; wsrep_retry_counter = 0; wsrep_PA_safe = true; - wsrep_seqno_changed = false; wsrep_retry_query = NULL; wsrep_retry_query_len = 0; wsrep_retry_command = COM_CONNECT; @@ -1470,12 +1470,10 @@ void THD::init(void) wsrep_conflict_state= NO_CONFLICT; wsrep_query_state= QUERY_IDLE; wsrep_last_query_id= 0; - wsrep_trx_seqno= 0; wsrep_converted_lock_session= false; wsrep_retry_counter= 0; wsrep_rli= NULL; wsrep_PA_safe= true; - wsrep_seqno_changed= false; wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_mysql_replicated = 0; wsrep_bf_thd = NULL; @@ -2117,13 +2115,6 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= FALSE; -#ifdef WITH_WSREP - if (TOTAL_ORDER == wsrep_exec_mode) - { - wsrep_exec_mode = LOCAL_STATE; - } - //wsrep_trx_seqno = 0; -#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY if (rli_slave) diff --git a/sql/sql_class.h b/sql/sql_class.h index 1d5ac115fff..3d2442b7922 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -985,9 +985,6 @@ struct st_savepoint { /** State of metadata locks before this savepoint was set. */ MDL_savepoint mdl_savepoint; }; -#ifdef WITH_WSREP -void wsrep_cleanup_transaction(THD *thd); // THD.transactions.cleanup calls it -#endif enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY}; extern const char *xa_state_names[]; @@ -1865,11 +1862,7 @@ public: */ CHANGED_TABLE_LIST* changed_tables; MEM_ROOT mem_root; // Transaction-life memory allocation pool -#ifdef WITH_WSREP - void cleanup(THD *thd) -#else void cleanup() -#endif { DBUG_ENTER("thd::cleanup"); changed_tables= 0; @@ -1883,11 +1876,6 @@ public: if (!xid_state.rm_error) xid_state.xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); -#ifdef WITH_WSREP - // Todo: convert into a plugin method - // wsrep's post-commit. LOCAL_COMMIT designates wsrep's commit was ok - if (WSREP(thd)) wsrep_cleanup_transaction(thd); -#endif /* WITH_WSREP */ DBUG_VOID_RETURN; } my_bool is_active() @@ -2367,7 +2355,6 @@ public: Relay_log_info* wsrep_rli; bool wsrep_converted_lock_session; wsrep_trx_handle_t wsrep_trx_handle; - bool wsrep_seqno_changed; #ifdef WSREP_PROC_INFO char wsrep_info[128]; /* string for dynamic proc info */ #endif /* WSREP_PROC_INFO */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fdb042f3737..156acd9c2f7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4705,7 +4705,7 @@ create_sp_error: if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); break; } @@ -6164,6 +6164,9 @@ void wsrep_replay_transaction(THD *thd) unireg_abort(1); break; } + + wsrep_cleanup_transaction(thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); wsrep_replaying--; WSREP_DEBUG("replaying decreased: %d, thd: %lu", @@ -8567,21 +8570,24 @@ void wsrep_rollback_process(THD *thd) extern "C" int wsrep_thd_is_brute_force(void *thd_ptr) { + /* + Brute force: + Appliers and replaying are running in REPL_RECV mode. TOI statements + in TOTAL_ORDER mode. Locally committing transaction that has got + past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode. + + Everything else is running in LOCAL_STATE and should not be considered + brute force. + */ if (thd_ptr) { switch (((THD *)thd_ptr)->wsrep_exec_mode) { - case LOCAL_STATE: - { - if (((THD *)thd_ptr)->wsrep_conflict_state== REPLAYING) - { - return 1; - } - return 0; - } + case LOCAL_STATE: return 0; case REPL_RECV: return 1; case TOTAL_ORDER: return 2; case LOCAL_COMMIT: return 3; } } + DBUG_ASSERT(0); return 0; } extern "C" diff --git a/sql/transaction.cc b/sql/transaction.cc index 37f3b5847a6..7976adf38a5 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -142,6 +142,9 @@ bool trans_begin(THD *thd, uint flags) #endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= test(ha_commit_trans(thd, TRUE)); +#ifdef WITH_WSREP + wsrep_post_commit(thd, TRUE); +#endif /* WITH_WSREP */ } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -194,6 +197,9 @@ bool trans_commit(THD *thd) #endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit_trans(thd, TRUE); +#ifdef WITH_WSREP + wsrep_post_commit(thd, TRUE); +#endif /* WITH_WSREP */ if (res) /* if res is non-zero, then ha_commit_trans has rolled back the @@ -240,6 +246,9 @@ bool trans_commit_implicit(THD *thd) #endif /* WITH_WSREP */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= test(ha_commit_trans(thd, TRUE)); +#ifdef WITH_WSREP + wsrep_post_commit(thd, TRUE); +#endif /* WITH_WSREP */ } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -324,7 +333,14 @@ bool trans_commit_stmt(THD *thd) #endif /* WITH_WSREP */ res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) +#ifdef WITH_WSREP + { +#endif /* WITH_WSREP */ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; +#ifdef WITH_WSREP + wsrep_post_commit(thd, FALSE); + } +#endif /* WITH_WSREP */ } if (res) @@ -737,6 +753,9 @@ bool trans_xa_commit(THD *thd) int r= ha_commit_trans(thd, TRUE); if ((res= test(r))) my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); +#ifdef WITH_WSREP + wsrep_post_commit(thd, TRUE); +#endif /* WITH_WSREP */ } else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE) { diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 3756f54ab48..203f0888550 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -32,34 +32,15 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd); enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); /* - a post-commit cleanup on behalf of wsrep. Can't be a part of hton struct. - Is called by THD::transactions.cleanup() + Cleanup after local transaction commit/rollback, replay or TOI. */ void wsrep_cleanup_transaction(THD *thd) { - if (thd->thread_id == 0) return; - if (thd->wsrep_exec_mode == LOCAL_COMMIT) - { - if (thd->variables.wsrep_on && - thd->wsrep_conflict_state != MUST_REPLAY) - { - if (thd->wsrep_seqno_changed) - { - if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) - { - DBUG_PRINT("wsrep", ("set committed fail")); - WSREP_WARN("set committed fail: %llu %d", - (long long)thd->real_id, thd->stmt_da->status()); - } - } - //else - //WSREP_DEBUG("no trx handle for %s", thd->query()); - thd_binlog_trx_reset(thd); - thd->wsrep_seqno_changed = false; - } - thd->wsrep_exec_mode= LOCAL_STATE; - } - thd->wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; + if (wsrep_emulate_bin_log) thd_binlog_trx_reset(thd); + thd->wsrep_trx_handle.trx_id= WSREP_UNDEFINED_TRX_ID; + thd->wsrep_trx_seqno= WSREP_SEQNO_UNDEFINED; + thd->wsrep_exec_mode= LOCAL_STATE; + return; } /* @@ -67,25 +48,63 @@ void wsrep_cleanup_transaction(THD *thd) */ 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) { - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; - for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) + if (thd->wsrep_exec_mode != TOTAL_ORDER) { - if (i->ht()->db_type == DB_TYPE_INNODB) + THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; + for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) { - trans_register_ha(thd, all, wsrep_hton); - - /* follow innodb read/write settting */ - if (i->is_trx_read_write()) + if (i->ht()->db_type == DB_TYPE_INNODB) { - thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + trans_register_ha(thd, all, wsrep_hton); + + /* follow innodb read/write settting */ + if (i->is_trx_read_write()) + { + thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); + } + break; } - 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 (thd->wsrep_exec_mode == LOCAL_COMMIT) + { + DBUG_ASSERT(thd->wsrep_trx_seqno != WSREP_SEQNO_UNDEFINED); + if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("set committed fail")); + WSREP_WARN("set committed fail: %llu %d", + (long long)thd->real_id, thd->stmt_da->status()); + } + wsrep_cleanup_transaction(thd); + } +} + /* wsrep exploits binlog's caches even if binlogging itself is not activated. In such case connection close needs calling @@ -97,7 +116,13 @@ static int wsrep_close_connection(handlerton* hton, THD* thd) { DBUG_ENTER("wsrep_close_connection"); - if (thd_get_ha_data(thd, binlog_hton) != NULL) + + 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); } @@ -113,10 +138,17 @@ wsrep_close_connection(handlerton* hton, THD* thd) */ static int wsrep_prepare(handlerton *hton, THD *thd, bool all) { -#ifndef DBUG_OFF - //wsrep_seqno_t old = thd->wsrep_trx_seqno; -#endif 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_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))) @@ -138,12 +170,26 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all) 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) return 0; int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); 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) return 0; int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); return rcode; @@ -152,6 +198,12 @@ static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) 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_wsrep_thd); if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) @@ -162,25 +214,54 @@ static int wsrep_rollback(handlerton *hton, THD *thd, bool all) WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", (long long)thd->real_id, thd->query()); } + wsrep_cleanup_transaction(thd); } - - int rcode = 0; - if (!wsrep_emulate_bin_log) - { - if (all) thd_binlog_trx_reset(thd); - } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - DBUG_RETURN(rcode); + 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_wsrep_thd); + 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->post_rollback(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("setting rollback fail")); + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + (long long)thd->real_id, thd->query()); + } + wsrep_cleanup_transaction(thd); + } + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); DBUG_RETURN(0); } + extern Rpl_filter* binlog_filter; extern my_bool opt_log_slave_updates; extern void wsrep_write_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); @@ -305,9 +386,6 @@ wsrep_run_wsrep_commit( } if (data_len == 0) { - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_exec_mode = LOCAL_COMMIT; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); if (thd->stmt_da->is_ok() && thd->stmt_da->affected_rows() > 0 && !binlog_filter->is_on()) @@ -356,9 +434,11 @@ wsrep_run_wsrep_commit( WSREP_WARN("Transaction missing in provider, thd: %ld, SQL: %s", thd->thread_id, thd->query()); wsrep_write_rbr_buf(thd, rbr_data, data_len); - rcode = WSREP_OK; + rcode = WSREP_TRX_FAIL; break; case WSREP_BF_ABORT: + WSREP_DEBUG("thd %lu seqno %lld BF aborted by provider, will replay", + thd->thread_id, (long long)thd->wsrep_trx_seqno); mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_conflict_state = MUST_REPLAY; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -369,7 +449,6 @@ wsrep_run_wsrep_commit( mysql_mutex_unlock(&LOCK_wsrep_replaying); break; default: - thd->wsrep_seqno_changed = true; break; } } else { @@ -387,7 +466,24 @@ wsrep_run_wsrep_commit( mysql_mutex_lock(&thd->LOCK_wsrep_thd); switch(rcode) { case 0: - thd->wsrep_exec_mode = LOCAL_COMMIT; + /* + 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 %lu seqno %lld: conflict state %d after post commit", + thd->thread_id, + (long long)thd->wsrep_trx_seqno, + thd->wsrep_conflict_state); + } + thd->wsrep_exec_mode= LOCAL_COMMIT; + DBUG_ASSERT(thd->wsrep_trx_seqno != WSREP_SEQNO_UNDEFINED); /* Override XID iff it was generated by mysql */ if (thd->transaction.xid_state.xid.get_my_xid()) { @@ -396,10 +492,10 @@ wsrep_run_wsrep_commit( thd->wsrep_trx_seqno); } DBUG_PRINT("wsrep", ("replicating commit success")); - break; - case WSREP_TRX_FAIL: case WSREP_BF_ABORT: + DBUG_ASSERT(thd->wsrep_trx_seqno != WSREP_SEQNO_UNDEFINED); + case WSREP_TRX_FAIL: WSREP_DEBUG("commit failed for reason: %d", rcode); DBUG_PRINT("wsrep", ("replicating commit fail")); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 14bc3e54845..d09ca660501 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1144,14 +1144,14 @@ static void wsrep_TOI_end(THD *thd) { wsrep_status_t ret; wsrep_to_isolation--; WSREP_DEBUG("TO END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void") - if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { + thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); + if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { WSREP_DEBUG("TO END: %lld", (long long)thd->wsrep_trx_seqno); - } - else { - WSREP_WARN("TO isolation end failed for: %d, sql: %s", - ret, (thd->query()) ? thd->query() : "void"); - } + } + else { + WSREP_WARN("TO isolation end failed for: %d, sql: %s", + ret, (thd->query()) ? thd->query() : "void"); + } } static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) @@ -1222,14 +1222,20 @@ static void wsrep_RSU_end(THD *thd) return; } thd->variables.wsrep_on = 1; - return; } int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list) { + + /* + No isolation for applier or replaying threads. + */ + if (thd->wsrep_exec_mode == REPL_RECV) return 0; + int ret= 0; mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", @@ -1239,6 +1245,9 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); + DBUG_ASSERT(thd->wsrep_trx_seqno == WSREP_SEQNO_UNDEFINED); + if (wsrep_debug && thd->mdl_context.has_locks()) { WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", @@ -1265,14 +1274,16 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, return ret; } -void wsrep_to_isolation_end(THD *thd) { - if (thd->wsrep_exec_mode==TOTAL_ORDER) +void wsrep_to_isolation_end(THD *thd) +{ + if (thd->wsrep_exec_mode == TOTAL_ORDER) { switch(wsrep_OSU_method_options) { - case WSREP_OSU_TOI: return wsrep_TOI_end(thd); - case WSREP_OSU_RSU: return wsrep_RSU_end(thd); + case WSREP_OSU_TOI: wsrep_TOI_end(thd); break; + case WSREP_OSU_RSU: wsrep_RSU_end(thd); break; } + wsrep_cleanup_transaction(thd); } } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 607014e3fa9..cbc3f4cf3d1 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -33,7 +33,7 @@ class THD; LOCAL_STATE, REPL_RECV, TOTAL_ORDER, - LOCAL_COMMIT, + LOCAL_COMMIT }; enum wsrep_query_state { QUERY_IDLE, @@ -311,7 +311,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); class Ha_trx_info; struct THD_TRANS; void wsrep_register_hton(THD* thd, bool all); - +void wsrep_post_commit(THD* thd, bool all); void wsrep_replication_process(THD *thd); void wsrep_rollback_process(THD *thd); void wsrep_brute_force_killer(THD *thd); @@ -374,7 +374,7 @@ struct TABLE_LIST; int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list); void wsrep_to_isolation_end(THD *thd); - +void wsrep_cleanup_transaction(THD *thd); void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow*); int wsrep_to_buf_helper( diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 911fd0ca877..7ea746ff7eb 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -795,6 +795,24 @@ trx_sys_print_mysql_binlog_offset(void) #ifdef WITH_WSREP +#ifdef UNIV_DEBUG +static long long trx_sys_cur_xid_seqno = -1; +static unsigned char trx_sys_cur_xid_uuid[16]; + +long long read_wsrep_xid_seqno(const XID* xid) +{ + long long seqno; + memcpy(&seqno, xid->data + 24, sizeof(long long)); + return seqno; +} + +void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf) +{ + memcpy(buf, xid->data + 8, 16); +} + +#endif /* UNIV_DEBUG */ + void trx_sys_update_wsrep_checkpoint( const XID* xid, /*!< in: transaction XID */ @@ -802,6 +820,25 @@ trx_sys_update_wsrep_checkpoint( { trx_sysf_t* sys_header; +#ifdef UNIV_DEBUG + { + /* Check that seqno is monotonically increasing */ + unsigned char xid_uuid[16]; + long long xid_seqno = read_wsrep_xid_seqno(xid); + read_wsrep_xid_uuid(xid, xid_uuid); + if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8)) + { + ut_ad(xid_seqno > trx_sys_cur_xid_seqno); + trx_sys_cur_xid_seqno = xid_seqno; + } + else + { + memcpy(trx_sys_cur_xid_uuid, xid_uuid, 16); + } + trx_sys_cur_xid_seqno = xid_seqno; + } +#endif /* UNIV_DEBUG */ + ut_ad(xid && mtr); ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index d5d4590a23e..f75a81c731b 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -966,6 +966,24 @@ trx_sys_print_mysql_binlog_offset(void) #ifdef WITH_WSREP +#ifdef UNIV_DEBUG +static long long trx_sys_cur_xid_seqno = -1; +static unsigned char trx_sys_cur_xid_uuid[16]; + +long long read_wsrep_xid_seqno(const XID* xid) +{ + long long seqno; + memcpy(&seqno, xid->data + 24, sizeof(long long)); + return seqno; +} + +void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf) +{ + memcpy(buf, xid->data + 8, 16); +} + +#endif /* UNIV_DEBUG */ + void trx_sys_update_wsrep_checkpoint( const XID* xid, /*!< in: transaction XID */ @@ -973,6 +991,25 @@ trx_sys_update_wsrep_checkpoint( { trx_sysf_t* sys_header; +#ifdef UNIV_DEBUG + { + /* Check that seqno is monotonically increasing */ + unsigned char xid_uuid[16]; + long long xid_seqno = read_wsrep_xid_seqno(xid); + read_wsrep_xid_uuid(xid, xid_uuid); + if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8)) + { + ut_ad(xid_seqno > trx_sys_cur_xid_seqno); + trx_sys_cur_xid_seqno = xid_seqno; + } + else + { + memcpy(trx_sys_cur_xid_uuid, xid_uuid, 16); + } + trx_sys_cur_xid_seqno = xid_seqno; + } +#endif /* UNIV_DEBUG */ + ut_ad(xid && mtr); ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); From 4f85baab95f50448930a8c9915f7178aa121e66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 25 Nov 2013 14:04:49 +0200 Subject: [PATCH 088/294] Merged revisions 3931--3942 from from lp:~codership/codership-mysql/5.5-23. ------------------------------------------------------------ revno: 3942 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Thu 2013-11-07 17:37:10 +0200 message: References: lp:1248921 - checking if index is foreign earlier to adhere to lat ch order protocol ------------------------------------------------------------ revno: 3941 fixes bug: https://launchpad.net/bugs/1248908 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Thu 2013-11-07 14:31:04 +0200 message: References lp:1248908 - Fixed access to trx sys header Pass trx sys header as argument for trx_sys_update_wsrep_checkpoint() and trx_sys_update_mysql_binlog_offset() to avoid successive calls to trx_sysf_get(). ------------------------------------------------------------ revno: 3940 fixes bug: https://launchpad.net/bugs/1244100 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Tue 2013-11-05 15:31:12 +0200 message: References lp:1244100 - assign value for check_purge before return ------------------------------------------------------------ revno: 3939 fixes bug: https://launchpad.net/bugs/1247978 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Tue 2013-11-05 01:01:36 +0200 message: References lp:1247978 - force release transactional MDL locks if wsrep is on a nd no active transaction at the end of mysql_execute_command() ------------------------------------------------------------ revno: 3938 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Sun 2013-11-03 20:48:06 +0400 message: References lp:1232789 - fix FLUSH STATUS zeroes up wsrep_cluster_size and wsre p_local_index ------------------------------------------------------------ revno: 3937 5kB/s - committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Sun 2013-11-03 17:06:31 +0400 message: References lp:587170 - reset auto_increment_* vars to defaults for TOI operati ons ------------------------------------------------------------ revno: 3936 committer: Vladislav Klyachin branch nick: 5.5-23 timestamp: Sun 2013-11-03 00:10:45 +0400 message: References lp:1072839 - fix for memory leaks with wsrep variables ------------------------------------------------------------ revno: 3935 committer: Seppo Jaakola branch nick: wsrep-5.5-23 timestamp: Wed 2013-10-30 14:34:32 +0200 message: References: lp:1246257 - skipping replication for CREATE TEMPORARY TABLE LIKE. .. constructs ------------------------------------------------------------ revno: 3934 6kB/s \ fixes bug: https://launchpad.net/bugs/1241760 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Mon 2013-10-28 11:01:53 +0200 message: References lp:1241760 - save thd->db to wsrep_thd_shadow before replay ------------------------------------------------------------ revno: 3933 fixes bug: https://launchpad.net/bugs/1206129 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Sun 2013-10-27 18:15:12 +0200 message: References lp:1206129 - check binlog_hton->commit() return value, call wsrep_p ost_commit() instead of wsrep_cleanup_transaction() ------------------------------------------------------------ revno: 3932 fixes bug: https://launchpad.net/bugs/1244661 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Sun 2013-10-27 13:14:02 +0200 message: References lp:1244661 - added wsrep_register_hton() to trans_rollback_implicit () ------------------------------------------------------------ revno: 3931 fixes bug: https://launchpad.net/bugs/1244667 committer: Teemu Ollakka branch nick: 5.5-23 timestamp: Sun 2013-10-27 11:08:49 +0200 message: References lp:1244667 - restore thd->server_status after replay --- sql/log.cc | 1 + sql/mdl.h | 7 +++++ sql/mysqld.cc | 4 +-- sql/sql_alter.cc | 21 ++++++++----- sql/sql_class.h | 2 ++ sql/sql_parse.cc | 26 +++++++++++++++- sql/sql_table.cc | 13 +++++++- sql/sys_vars.cc | 10 +++---- sql/transaction.cc | 1 - storage/innobase/handler/ha_innodb.cc | 14 +++++---- storage/innobase/include/trx0sys.h | 9 ++++-- storage/innobase/row/row0upd.c | 43 ++++++++++++++++++++++----- storage/innobase/trx/trx0sys.c | 19 +++++++----- storage/innobase/trx/trx0trx.c | 12 ++++++-- storage/xtradb/handler/ha_innodb.cc | 14 +++++---- storage/xtradb/include/trx0sys.h | 6 ++-- storage/xtradb/row/row0upd.c | 43 ++++++++++++++++++++++----- storage/xtradb/trx/trx0sys.c | 14 +++++---- storage/xtradb/trx/trx0trx.c | 6 ++-- 19 files changed, 198 insertions(+), 67 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 0fb6cd18690..64174a9a454 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5555,6 +5555,7 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge) #ifdef WITH_WSREP if (WSREP_ON && wsrep_to_isolation) { + *check_purge= false; WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d", wsrep_to_isolation); DBUG_RETURN(0); diff --git a/sql/mdl.h b/sql/mdl.h index 50a2c2d815a..1363a07e7ab 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -666,6 +666,13 @@ public: m_tickets[MDL_EXPLICIT].is_empty()); } +#ifdef WITH_WSREP + inline bool has_transactional_locks() const + { + return !m_tickets[MDL_TRANSACTION].is_empty(); + } +#endif /* WITH_WSREP */ + MDL_savepoint mdl_savepoint() { return MDL_savepoint(m_tickets[MDL_STATEMENT].front(), diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3b0009b5ca9..2bcd946c672 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7924,8 +7924,8 @@ SHOW_VAR status_vars[]= { {"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}, - {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG}, + {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH}, + {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH}, {"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}, diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 00691633aa8..75d27016317 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -102,15 +102,20 @@ bool Alter_table_statement::execute(THD *thd) #ifdef WITH_WSREP TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); - if ((!thd->is_current_stmt_binlog_format_row() || - !find_temporary_table(thd, first_table)) && - wsrep_to_isolation_begin(thd, - lex->name.str ? select_lex->db : NULL, - lex->name.str ? lex->name.str : NULL, - first_table)) + if (!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, first_table)) { - WSREP_WARN("ALTER TABLE isolation failure"); - DBUG_RETURN(TRUE); + if (wsrep_to_isolation_begin(thd, + lex->name.str ? select_lex->db : NULL, + lex->name.str ? lex->name.str : NULL, + first_table)) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } + + thd->variables.auto_increment_offset = 1; + thd->variables.auto_increment_increment = 1; } #endif /* WITH_WSREP */ result= mysql_alter_table(thd, select_lex->db, lex->name.str, diff --git a/sql/sql_class.h b/sql/sql_class.h index 3d2442b7922..4a84c91c228 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -52,6 +52,8 @@ struct wsrep_thd_shadow { enum wsrep_exec_mode wsrep_exec_mode; Vio *vio; ulong tx_isolation; + char *db; + size_t db_length; }; #endif class Reprepare_observer; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 156acd9c2f7..df1493c8cb1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2906,6 +2906,9 @@ case SQLCOM_PREPARE: else { #ifdef WITH_WSREP + /* in STATEMENT format, we probably have to replicate also temporary + tables, like mysql replication does + */ if (!thd->is_current_stmt_binlog_format_row() || !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, @@ -4985,7 +4988,22 @@ finish: { thd->mdl_context.release_statement_locks(); } - WSREP_TO_ISOLATION_END + WSREP_TO_ISOLATION_END; + +#ifdef WITH_WSREP + /* + Force release of transactional locks if not in active MST and wsrep is on. + */ + if (WSREP(thd) && + ! thd->in_sub_stmt && + ! thd->in_active_multi_stmt_transaction() && + thd->mdl_context.has_transactional_locks()) + { + WSREP_DEBUG("Forcing release of transactional locks for thd %lu", + thd->thread_id); + thd->mdl_context.release_transactional_locks(); + } +#endif /* WITH_WSREP */ DBUG_RETURN(res || thd->is_error()); } @@ -8423,6 +8441,10 @@ void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) shadow->tx_isolation = thd->variables.tx_isolation; thd->variables.tx_isolation = ISO_READ_COMMITTED; thd->tx_isolation = ISO_READ_COMMITTED; + + shadow->db = thd->db; + shadow->db_length = thd->db_length; + thd->reset_db(NULL, 0); } void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) @@ -8431,6 +8453,8 @@ void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) thd->wsrep_exec_mode = shadow->wsrep_exec_mode; thd->net.vio = shadow->vio; thd->variables.tx_isolation = shadow->tx_isolation; + + thd->reset_db(shadow->db, shadow->db_length); } void wsrep_replication_process(THD *thd) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 06c5b51a438..bd1b4c600fc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4778,12 +4778,23 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, break; } } - if (!is_tmp_table) + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { + /* CREATE TEMPORARY TABLE LIKE must be skipped from replication */ + WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s", + thd->query()); + } + else if (!is_tmp_table) + { + /* this is straight CREATE TABLE LIKE... eith no tmp tables */ WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL); } else { + /* here we have CREATE TABLE LIKE + the temporary table definition will be needed in slaves to + enable the create to succeed + */ TABLE_LIST tbl; bzero((void*) &tbl, sizeof(tbl)); tbl.db= src_table->db; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5b4cc4ddb64..88dee072b89 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3645,7 +3645,7 @@ static Sys_var_charptr Sys_wsrep_data_home_dir( static Sys_var_charptr Sys_wsrep_cluster_name( "wsrep_cluster_name", "Name for the cluster", - GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_cluster_name), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_cluster_name_check), @@ -3663,13 +3663,13 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", - GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_name), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_charptr Sys_wsrep_node_address ( "wsrep_node_address", "Node address", - GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_address), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_node_address_check), @@ -3677,7 +3677,7 @@ static Sys_var_charptr Sys_wsrep_node_address ( static Sys_var_charptr Sys_wsrep_node_incoming_address( "wsrep_node_incoming_address", "Client connection address", - GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), NO_MUTEX_GUARD, NOT_IN_BINLOG); @@ -3769,7 +3769,7 @@ static Sys_var_mybool Sys_wsrep_on ( static Sys_var_charptr Sys_wsrep_start_position ( "wsrep_start_position", "global transaction position to start from ", - GLOBAL_VAR(wsrep_start_position), + PREALLOCATED GLOBAL_VAR(wsrep_start_position), CMD_LINE(REQUIRED_ARG, OPT_WSREP_START_POSITION), IN_FS_CHARSET, DEFAULT(wsrep_start_position), NO_MUTEX_GUARD, NOT_IN_BINLOG, diff --git a/sql/transaction.cc b/sql/transaction.cc index 7976adf38a5..2d1c94e6b52 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -298,7 +298,6 @@ bool trans_rollback(THD *thd) DBUG_RETURN(test(res)); } - /** Commit the single statement transaction. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b291f0957b8..8e9b7827779 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5688,9 +5688,9 @@ no_commit: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - - wsrep_cleanup_transaction(user_thd); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -5711,8 +5711,9 @@ no_commit: case WSREP_TRX_ERROR: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - wsrep_cleanup_transaction(user_thd); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ @@ -12748,7 +12749,8 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) if (wsrep_is_wsrep_xid(xid)) { mtr_t mtr; mtr_start(&mtr); - trx_sys_update_wsrep_checkpoint(xid, &mtr); + trx_sysf_t* sys_header = trx_sysf_get(&mtr); + trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); return 0; } else { diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 21e4f961b7c..b8f1973d9c5 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -309,6 +309,9 @@ trx_sys_update_mysql_binlog_offset( ib_int64_t offset, /*!< in: position in that log file */ ulint field, /*!< in: offset of the MySQL log info field in the trx sys header */ +#ifdef WITH_WSREP + trx_sysf_t* sys_header, /*!< in: trx sys header */ +#endif /* WITH_WSREP */ mtr_t* mtr); /*!< in: mtr */ /*****************************************************************//** Prints to stderr the MySQL binlog offset info in the trx system header if @@ -321,8 +324,10 @@ trx_sys_print_mysql_binlog_offset(void); /** Update WSREP checkpoint XID in sys header. */ void trx_sys_update_wsrep_checkpoint( - const XID* xid, /*!< in: WSREP XID */ - mtr_t* mtr); /*!< in: mtr */ + const XID* xid, /*!< in: WSREP XID */ + trx_sysf_t* sys_header, /*!< in: sys_header */ + mtr_t* mtr); /*!< in: mtr */ + void /** Read WSREP checkpoint XID from sys header. */ trx_sys_read_wsrep_checkpoint( diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 856947b62c4..186be33d2bd 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -1727,10 +1727,16 @@ row_upd_sec_index_entry( trx_t* trx = thr_get_trx(thr); ulint mode = BTR_MODIFY_LEAF; enum row_search_result search_result; +#ifdef WITH_WSREP + ibool foreign; +#endif /* WITH_WSREP */ index = node->index; referenced = row_upd_index_is_referenced(index, trx); +#ifdef WITH_WSREP + foreign = wsrep_row_upd_index_is_foreign(index, trx); +#endif /* WITH_WSREP */ heap = mem_heap_create(1024); @@ -1814,15 +1820,16 @@ row_upd_sec_index_entry( index, offsets, thr, &mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - wsrep_row_upd_index_is_foreign(index, trx) + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == + QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + foreign ) { ulint* offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, - &heap); + rec, index, NULL, + ULINT_UNDEFINED, &heap); err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); @@ -1996,6 +2003,9 @@ row_upd_clust_rec_by_insert( que_thr_t* thr, /*!< in: query thread */ ibool referenced,/*!< in: TRUE if index may be referenced in a foreign key constraint */ +#ifdef WITH_WSREP + ibool foreign, /*!< in: TRUE if index is foreign key index */ +#endif /* WITH_WSREP */ mtr_t* mtr) /*!< in/out: mtr; gets committed here */ { mem_heap_t* heap; @@ -2092,7 +2102,7 @@ err_exit: if (!referenced && !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && ((upd_node_t*)parent)->cascade_node == node) && - wsrep_row_upd_index_is_foreign(index, trx) + foreign ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); @@ -2313,6 +2323,9 @@ row_upd_del_mark_clust_rec( ibool referenced, /*!< in: TRUE if index may be referenced in a foreign key constraint */ +#ifdef WITH_WSREP + ibool foreign,/*!< in: TRUE if index is foreign key index */ +#endif /* WITH_WSREP */ mtr_t* mtr) /*!< in: mtr; gets committed here */ { btr_pcur_t* pcur; @@ -2360,7 +2373,7 @@ row_upd_del_mark_clust_rec( !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && ((upd_node_t*)parent)->cascade_node == node) && thr_get_trx(thr) && - wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)) + foreign ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); @@ -2409,11 +2422,17 @@ row_upd_clust_step( ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets; ibool referenced; +#ifdef WITH_WSREP + ibool foreign; +#endif /* WITH_WSREP */ rec_offs_init(offsets_); index = dict_table_get_first_index(node->table); referenced = row_upd_index_is_referenced(index, thr_get_trx(thr)); +#ifdef WITH_WSREP + foreign = wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)); +#endif /* WITH_WSREP */ pcur = node->pcur; @@ -2483,7 +2502,11 @@ row_upd_clust_step( if (node->is_delete) { err = row_upd_del_mark_clust_rec( +#ifdef WITH_WSREP + node, index, offsets, thr, referenced, foreign, mtr); +#else node, index, offsets, thr, referenced, mtr); +#endif /* WITH_WSREP */ if (err == DB_SUCCESS) { node->state = UPD_NODE_UPDATE_ALL_SEC; @@ -2534,7 +2557,11 @@ exit_func: externally! */ err = row_upd_clust_rec_by_insert( +#ifdef WITH_WSREP + node, index, thr, referenced, foreign, mtr); +#else node, index, thr, referenced, mtr); +#endif /* WITH_WSREP */ if (err != DB_SUCCESS) { diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 7ea746ff7eb..a0fcc2b2370 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -695,10 +695,14 @@ trx_sys_update_mysql_binlog_offset( ib_int64_t offset, /*!< in: position in that log file */ ulint field, /*!< in: offset of the MySQL log info field in the trx sys header */ +#ifdef WITH_WSREP + trx_sysf_t* sys_header, /*!< in: trx sys header */ +#endif /* WITH_WSREP */ mtr_t* mtr) /*!< in: mtr */ { +#ifndef WITH_WSREP trx_sysf_t* sys_header; - +#endif /* !WITH_WSREP */ if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) { /* We cannot fit the name to the 512 bytes we have reserved */ @@ -706,7 +710,9 @@ trx_sys_update_mysql_binlog_offset( return; } +#ifndef WITH_WSREP sys_header = trx_sysf_get(mtr); +#endif /* !WITH_WSREP */ if (mach_read_from_4(sys_header + field + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD) @@ -815,10 +821,10 @@ void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf) void trx_sys_update_wsrep_checkpoint( - const XID* xid, /*!< in: transaction XID */ - mtr_t* mtr) /*!< in: mtr */ + const XID* xid, /*!< in: transaction XID */ + trx_sysf_t* sys_header, /*!< in: sys_header */ + mtr_t* mtr) /*!< in: mtr */ { - trx_sysf_t* sys_header; #ifdef UNIV_DEBUG { @@ -839,10 +845,9 @@ trx_sys_update_wsrep_checkpoint( } #endif /* UNIV_DEBUG */ - ut_ad(xid && mtr); + ut_ad(xid && mtr && sys_header); ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); - sys_header = trx_sysf_get(mtr); if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_MAGIC_N_FLD) != TRX_SYS_WSREP_XID_MAGIC_N) { @@ -890,7 +895,7 @@ trx_sys_read_wsrep_checkpoint(XID* xid) != TRX_SYS_WSREP_XID_MAGIC_N) { memset(xid, 0, sizeof(*xid)); xid->formatID = -1; - trx_sys_update_wsrep_checkpoint(xid, &mtr); + trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); return; } diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index d7fea8f4091..ce43c80e826 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -826,6 +826,9 @@ trx_write_serialisation_history( /*============================*/ trx_t* trx) /*!< in: transaction */ { +#ifdef WITH_WSREP + trx_sysf_t* sys_header; +#endif /* WITH_WSREP */ mtr_t mtr; trx_rseg_t* rseg; @@ -876,10 +879,11 @@ trx_write_serialisation_history( mutex_exit(&rseg->mutex); #ifdef WITH_WSREP + sys_header = trx_sysf_get(&mtr); /* Update latest MySQL wsrep XID in trx sys header. */ if (wsrep_is_wsrep_xid(&trx->xid)) { - trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + trx_sys_update_wsrep_checkpoint(&trx->xid, sys_header, &mtr); } #endif /* WITH_WSREP */ @@ -893,7 +897,11 @@ trx_write_serialisation_history( trx_sys_update_mysql_binlog_offset( trx->mysql_log_file_name, trx->mysql_log_offset, - TRX_SYS_MYSQL_LOG_INFO, &mtr); + TRX_SYS_MYSQL_LOG_INFO, +#ifdef WITH_WSREP + sys_header, +#endif /* WITH_WSREP */ + &mtr); trx->mysql_log_file_name = NULL; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 617c29a6536..8c56cd2a189 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6643,9 +6643,9 @@ no_commit: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - - wsrep_cleanup_transaction(user_thd); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -6666,8 +6666,9 @@ no_commit: case WSREP_TRX_ERROR: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - wsrep_cleanup_transaction(user_thd); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ @@ -14005,7 +14006,8 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) if (wsrep_is_wsrep_xid(xid)) { mtr_t mtr; mtr_start(&mtr); - trx_sys_update_wsrep_checkpoint(xid, &mtr); + trx_sysf_t* sys_header = trx_sysf_get(&mtr); + trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); return 0; } else { diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h index fbc828f9d63..69457a4c9b1 100644 --- a/storage/xtradb/include/trx0sys.h +++ b/storage/xtradb/include/trx0sys.h @@ -359,8 +359,10 @@ trx_sys_print_mysql_binlog_offset(void); /** Update WSREP checkpoint XID in sys header. */ void trx_sys_update_wsrep_checkpoint( - const XID* xid, /*!< in: WSREP XID */ - mtr_t* mtr); /*!< in: mtr */ + const XID* xid, /*!< in: WSREP XID */ + trx_sysf_t* sys_header, /*!< in: sys_header */ + mtr_t* mtr); /*!< in: mtr */ + void /** Read WSREP checkpoint XID from sys header. */ trx_sys_read_wsrep_checkpoint( diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 445a580e1e8..06c12f8eb2d 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -1745,10 +1745,16 @@ row_upd_sec_index_entry( trx_t* trx = thr_get_trx(thr); ulint mode = BTR_MODIFY_LEAF; enum row_search_result search_result; +#ifdef WITH_WSREP + ibool foreign; +#endif /* WITH_WSREP */ index = node->index; referenced = row_upd_index_is_referenced(index, trx); +#ifdef WITH_WSREP + foreign = wsrep_row_upd_index_is_foreign(index, trx); +#endif /* WITH_WSREP */ heap = mem_heap_create(1024); @@ -1833,15 +1839,16 @@ row_upd_sec_index_entry( index, offsets, thr, &mtr); } #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - wsrep_row_upd_index_is_foreign(index, trx) + if (err == DB_SUCCESS && !referenced && + !(parent && que_node_get_type(parent) == + QUE_NODE_UPDATE && + ((upd_node_t*)parent)->cascade_node == node) && + foreign ) { ulint* offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, - &heap); + rec, index, NULL, + ULINT_UNDEFINED, &heap); err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); @@ -2015,6 +2022,9 @@ row_upd_clust_rec_by_insert( que_thr_t* thr, /*!< in: query thread */ ibool referenced,/*!< in: TRUE if index may be referenced in a foreign key constraint */ +#ifdef WITH_WSREP + ibool foreign, /*!< in: TRUE if index is foreign key index */ +#endif /* WITH_WSREP */ mtr_t* mtr) /*!< in/out: mtr; gets committed here */ { mem_heap_t* heap; @@ -2113,7 +2123,7 @@ err_exit: if (!referenced && !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && ((upd_node_t*)parent)->cascade_node == node) && - wsrep_row_upd_index_is_foreign(index, trx) + foreign ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); @@ -2339,6 +2349,9 @@ row_upd_del_mark_clust_rec( ibool referenced, /*!< in: TRUE if index may be referenced in a foreign key constraint */ +#ifdef WITH_WSREP + ibool foreign,/*!< in: TRUE if index is foreign key index */ +#endif /* WITH_WSREP */ mtr_t* mtr) /*!< in: mtr; gets committed here */ { btr_pcur_t* pcur; @@ -2386,7 +2399,7 @@ row_upd_del_mark_clust_rec( !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && ((upd_node_t*)parent)->cascade_node == node) && thr_get_trx(thr) && - wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)) + foreign ) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); @@ -2435,11 +2448,17 @@ row_upd_clust_step( ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets; ibool referenced; +#ifdef WITH_WSREP + ibool foreign; +#endif /* WITH_WSREP */ rec_offs_init(offsets_); index = dict_table_get_first_index(node->table); referenced = row_upd_index_is_referenced(index, thr_get_trx(thr)); +#ifdef WITH_WSREP + foreign = wsrep_row_upd_index_is_foreign(index, thr_get_trx(thr)); +#endif /* WITH_WSREP */ pcur = node->pcur; @@ -2510,7 +2529,11 @@ row_upd_clust_step( if (node->is_delete) { err = row_upd_del_mark_clust_rec( +#ifdef WITH_WSREP + node, index, offsets, thr, referenced, foreign, mtr); +#else node, index, offsets, thr, referenced, mtr); +#endif /* WITH_WSREP */ if (err == DB_SUCCESS) { node->state = UPD_NODE_UPDATE_ALL_SEC; @@ -2561,7 +2584,11 @@ exit_func: externally! */ err = row_upd_clust_rec_by_insert( +#ifdef WITH_WSREP + node, index, thr, referenced, foreign, mtr); +#else node, index, thr, referenced, mtr); +#endif /* WITH_WSREP */ if (err != DB_SUCCESS) { diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index f75a81c731b..0730907bbe1 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -868,6 +868,9 @@ trx_sys_update_mysql_binlog_offset( mtr_t* mtr) /*!< in: mtr */ { const char* file_name; +#ifndef WITH_WSREP + trx_sysf_t* sys_header; +#endif /* !WITH_WSREP */ if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) { @@ -986,10 +989,10 @@ void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf) void trx_sys_update_wsrep_checkpoint( - const XID* xid, /*!< in: transaction XID */ - mtr_t* mtr) /*!< in: mtr */ + const XID* xid, /*!< in: transaction XID */ + trx_sysf_t* sys_header, /*!< in: sys_header */ + mtr_t* mtr) /*!< in: mtr */ { - trx_sysf_t* sys_header; #ifdef UNIV_DEBUG { @@ -1010,10 +1013,9 @@ trx_sys_update_wsrep_checkpoint( } #endif /* UNIV_DEBUG */ - ut_ad(xid && mtr); + ut_ad(xid && mtr && sys_header); ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); - sys_header = trx_sysf_get(mtr); if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_MAGIC_N_FLD) != TRX_SYS_WSREP_XID_MAGIC_N) { @@ -1061,7 +1063,7 @@ trx_sys_read_wsrep_checkpoint(XID* xid) != TRX_SYS_WSREP_XID_MAGIC_N) { memset(xid, 0, sizeof(*xid)); xid->formatID = -1; - trx_sys_update_wsrep_checkpoint(xid, &mtr); + trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); return; } diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index fe806f880b0..f1809188c00 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -1064,10 +1064,11 @@ trx_write_serialisation_history( mutex_exit(&rseg->mutex); #ifdef WITH_WSREP + sys_header = trx_sysf_get(&mtr); /* Update latest MySQL wsrep XID in trx sys header. */ if (wsrep_is_wsrep_xid(&trx->xid)) { - trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + trx_sys_update_wsrep_checkpoint(&trx->xid, sys_header, &mtr); } #endif /* WITH_WSREP */ @@ -1085,7 +1086,8 @@ trx_write_serialisation_history( sys_header, trx->mysql_log_file_name, trx->mysql_log_offset, - TRX_SYS_MYSQL_LOG_INFO, &mtr); + TRX_SYS_MYSQL_LOG_INFO, + &mtr); trx->mysql_log_file_name = NULL; } From 88f0e0ebeeca6194b73e20747cbc004970aeb26c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 25 Nov 2013 12:40:08 -0500 Subject: [PATCH 089/294] MDEV-4108 Compilation warnings with RelWithDebInfo only present in the Galera tree Fix for some compiler warnings. --- mysys/my_getopt.c | 3 --- sql/handler.cc | 7 +++++++ sql/sql_parse.cc | 2 +- sql/sql_table.cc | 6 ++---- storage/innobase/lock/lock0lock.c | 2 +- storage/xtradb/lock/lock0lock.c | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index f4a0f58511b..dd16e535eda 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -840,7 +840,6 @@ static int findopt(char *optpat, uint length, { uint count; const struct my_option *opt= *opt_res; - my_bool is_prefix= FALSE; DBUG_ENTER("findopt"); for (count= 0; opt->name; opt++) @@ -856,8 +855,6 @@ static int findopt(char *optpat, uint length, /* We only need to know one prev */ count= 1; *ffname= opt->name; - if (opt->name[length]) - is_prefix= TRUE; } else if (strcmp(*ffname, opt->name)) { diff --git a/sql/handler.cc b/sql/handler.cc index 028b4488573..9cadfb2cf3f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1297,7 +1297,9 @@ int ha_commit_trans(THD *thd, bool all) */ err= ht->prepare(ht, thd, all); status_var_increment(thd->status_var.ha_prepare_count); + if (err) + { #ifdef WITH_WSREP if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) { @@ -1309,9 +1311,14 @@ int ha_commit_trans(THD *thd, bool all) } } else + { /* not wsrep hton, bail to native mysql behavior */ #endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); +#ifdef WITH_WSREP + } /* End of else */ +#endif + } if (err) goto err; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0e993418b99..7933d95de68 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8220,7 +8220,7 @@ static inline wsrep_status_t wsrep_apply_rbr( if (!ev) { WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", - (long long)thd->wsrep_trx_seqno, buf_len); + (long long)thd->wsrep_trx_seqno, (long int) buf_len); rcode= 1; goto error; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6613b5c8da2..7a5b84488d7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6368,10 +6368,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error= 0; break; } -#ifdef WITH_WSREP - bool do_log_write(true); -#endif /* WITH_WSREP */ - if (error == HA_ERR_WRONG_COMMAND) + + if (error == HA_ERR_WRONG_COMMAND) { error= 0; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 9075ee212fb..5d353439484 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -2231,7 +2231,7 @@ lock_rec_lock_slow( { trx_t* trx; #ifdef WITH_WSREP - lock_t *c_lock; + lock_t *c_lock= 0; #endif lock_t* lock; diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 2bf7309152a..227f353f309 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -2211,7 +2211,7 @@ lock_rec_lock_slow( { trx_t* trx; #ifdef WITH_WSREP - lock_t *c_lock; + lock_t *c_lock= 0; #endif lock_t* lock; From 480753972a96efa2dd9f59434ed811ffe788f08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 26 Nov 2013 20:32:38 +0200 Subject: [PATCH 090/294] MDEV-4233: Galera: assertion: (lock->trx)->wait_lock == lock fails in file lock0lock.c line 796 Analysis: Assertion means that InnoDB transaction lock queue is not correctly set. Reason seams to be the fact that wrong lock is cancelled. Fix: We have selected c_lock to be cancelled. Thus we should cancel and release lock that is waiting for this lock i.e. c_lock->trx->wait_lock. --- storage/innobase/lock/lock0lock.c | 22 ++++++++++++++++++---- storage/xtradb/lock/lock0lock.c | 22 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 5d353439484..2fc16cc51f7 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -3960,11 +3960,25 @@ lock_table_create( } if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) - fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", - (ulonglong) lock->trx->id); + if (wsrep_debug) { + fprintf(stderr, "WSREP: table c_lock in wait: %llu new loc: %llu\n", + (ulonglong) c_lock->trx->id, lock->trx->id); + } + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; - lock_cancel_waiting_and_release(c_lock); + lock_cancel_waiting_and_release(c_lock->trx->wait_lock); + + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ + if (c_lock->trx->wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) { + fprintf(stderr, "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + } } #else diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 227f353f309..b63683b1eac 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -3943,11 +3943,25 @@ lock_table_create( } if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) - fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", - (ulonglong) lock->trx->id); + if (wsrep_debug) { + fprintf(stderr, "WSREP: table c_lock in wait: %llu new loc: %llu\n", + (ulonglong) c_lock->trx->id, lock->trx->id); + } + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; - lock_cancel_waiting_and_release(c_lock); + lock_cancel_waiting_and_release(c_lock->trx->wait_lock); + + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ + if (c_lock->trx->wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) { + fprintf(stderr, "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + } } #else From 21bb5cdfb59629e4d35ba6bfea4d050bf2ec5f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 27 Nov 2013 08:43:46 +0200 Subject: [PATCH 091/294] MDEV-4223: Galera: InnoDB assertion failure !mutex_own(mutex) in file sync0sync.ic line 207 Analysis: Code acquired kernel_mutex when calling wsrep_innobase_kill_one_trx. However, functions below also might take kernel mutex thus the assertion. Fix: Acquire kernel_mutex only for lock_cancel_waiting_and_release where it is really needed. --- storage/innobase/handler/ha_innodb.cc | 4 ++-- storage/xtradb/handler/ha_innodb.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c2c7301bc97..028eea45726 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12662,7 +12662,9 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, if (wait_lock) { WSREP_DEBUG("canceling wait lock"); victim_trx->was_chosen_as_deadlock_victim= TRUE; + mutex_enter(&kernel_mutex); lock_cancel_waiting_and_release(wait_lock); + mutex_exit(&kernel_mutex); } wsrep_thd_awake(bf_thd, thd, signal); @@ -12753,10 +12755,8 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { - mutex_enter(&kernel_mutex); int rcode = wsrep_innobase_kill_one_trx( bf_thd, bf_trx, victim_trx, signal); - mutex_exit(&kernel_mutex); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 2da3ead5abd..d1c6a971e4d 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13985,7 +13985,9 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) if (wait_lock) { WSREP_DEBUG("canceling wait lock"); victim_trx->was_chosen_as_deadlock_victim= TRUE; + mutex_enter(&kernel_mutex); lock_cancel_waiting_and_release(wait_lock); + mutex_exit(&kernel_mutex); } wsrep_thd_awake(bf_thd, thd, signal); @@ -14076,10 +14078,8 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { - mutex_enter(&kernel_mutex); int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, signal); - mutex_exit(&kernel_mutex); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { From 62bd131d06eaf9567e63ea1c508eb07aa758b2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 29 Nov 2013 12:27:05 +0200 Subject: [PATCH 092/294] MDEV-4235: Galera: Assertion `0' fails in tdc_remove_table on creating a trigger Analysis: There is two different THD's using the same table. Fix: In galera brute force (BF) exclusive locks are cancelled. Thus other threads could access the same table. Added additional check if this is the case, then we should not assert here. --- sql/sql_base.cc | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 84ee9b9fe12..5597ba40f90 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9457,10 +9457,22 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, { I_P_List_iterator it2(share->used_tables); while ((table= it2++)) - if (table->in_use != thd) - { - DBUG_ASSERT(0); - } +#ifdef WITH_WSREP + /* if thd was BF aborted, exclusive locks were canceled, + thus others can use table */ + + if (table->in_use != thd && + table->in_use->wsrep_bf_thd != thd && + table->in_use->wsrep_conflict_state != MUST_ABORT) + { +#endif + if (table->in_use != thd) + { + DBUG_ASSERT(0); + } +#ifdef WITH_WSREP + } +#endif } #endif /* From 6271c06a73ce1065ac53a554e42a0049bf77eb53 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 29 Nov 2013 12:50:31 -0500 Subject: [PATCH 093/294] MDEV-4222: Assertion `( ((global_system_variables.wsrep_on) && (thd && thd->variables.wsrep_on)) && wsrep_emulate_bin_log) || mysql_bin_log .is_open()' fails on SAVEPOINT with disabled wsrep_provider As wsrep_on system variable is ON by default the binlog handlerton is implicitly enabled during the server initialization phase. Later, while wsrep plugin is getting initialized, wsrep_on in corrected & turned OFF in case wsrep provider is not specified (leaving binlog in ON state!). This leads to the reported assertion. Fixed by adding another check for wsrep provider before binlog is enabled. Added a test case. --- mysql-test/suite/wsrep/r/trans.result | 9 +++++++++ mysql-test/suite/wsrep/t/trans.test | 13 +++++++++++++ sql/log.cc | 2 +- sql/mysqld.cc | 4 ++-- sql/wsrep_mysqld.cc | 6 ++---- sql/wsrep_mysqld.h | 3 +++ 6 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/trans.result create mode 100644 mysql-test/suite/wsrep/t/trans.test diff --git a/mysql-test/suite/wsrep/r/trans.result b/mysql-test/suite/wsrep/r/trans.result new file mode 100644 index 00000000000..bc225897103 --- /dev/null +++ b/mysql-test/suite/wsrep/r/trans.result @@ -0,0 +1,9 @@ +# +# MDEV-4222 : Assertion `( ((global_system_variables.wsrep_on) && +# (thd && thd->variables.wsrep_on)) && srep_emulate_bin_log) +# || mysql_bin_log .is_open()' fails on SAVEPOINT with +# disabled wsrep_provider +# +START TRANSACTION WITH CONSISTENT SNAPSHOT; +SAVEPOINT A; +End of test. diff --git a/mysql-test/suite/wsrep/t/trans.test b/mysql-test/suite/wsrep/t/trans.test new file mode 100644 index 00000000000..9278ef12072 --- /dev/null +++ b/mysql-test/suite/wsrep/t/trans.test @@ -0,0 +1,13 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-4222 : Assertion `( ((global_system_variables.wsrep_on) && +--echo # (thd && thd->variables.wsrep_on)) && srep_emulate_bin_log) +--echo # || mysql_bin_log .is_open()' fails on SAVEPOINT with +--echo # disabled wsrep_provider +--echo # + +START TRANSACTION WITH CONSISTENT SNAPSHOT; +SAVEPOINT A; + +--echo End of test. diff --git a/sql/log.cc b/sql/log.cc index 64174a9a454..850980f04f7 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1708,7 +1708,7 @@ int binlog_init(void *p) { binlog_hton= (handlerton *)p; #ifdef WITH_WSREP - if (WSREP_ON) + if (WSREP_ON && WSREP_PROVIDER_EXISTS) binlog_hton->state= SHOW_OPTION_YES; else { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 223482f36b9..80aa5c6a2f1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4909,7 +4909,7 @@ pthread_handler_t start_wsrep_THD(void *arg) void wsrep_create_rollbacker() { - if (wsrep_provider && strcasecmp(wsrep_provider, "none")) + if (WSREP_PROVIDER_EXISTS) { pthread_t hThread; /* create rollbacker */ @@ -4925,7 +4925,7 @@ void wsrep_create_appliers(long threads) { /* see wsrep_replication_start() for the logic */ if (wsrep_cluster_address && strlen(wsrep_cluster_address) && - wsrep_provider && strcasecmp(wsrep_provider, "none")) + WSREP_PROVIDER_EXISTS) { WSREP_ERROR("Trying to launch slave threads before creating " "connection at '%s'", wsrep_cluster_address); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index d09ca660501..39c8349c4f2 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -438,8 +438,7 @@ int wsrep_init() } } - if (strlen(wsrep_provider)== 0 || - !strcmp(wsrep_provider, WSREP_NONE)) + if (!WSREP_PROVIDER_EXISTS) { // enable normal operation in case no provider is specified wsrep_ready_set(TRUE); @@ -662,8 +661,7 @@ bool wsrep_start_replication() if provider is trivial, don't even try to connect, but resume local node operation */ - if (strlen(wsrep_provider)== 0 || - !strcmp(wsrep_provider, WSREP_NONE)) + if (!WSREP_PROVIDER_EXISTS) { // enable normal operation in case no provider is specified wsrep_ready_set(TRUE); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index cbc3f4cf3d1..20d356a22a9 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -286,6 +286,9 @@ extern wsrep_seqno_t wsrep_locked_seqno; if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ } +#define WSREP_PROVIDER_EXISTS \ + (wsrep_provider && strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN)) + /*! Synchronizes applier thread start with init thread */ extern void wsrep_sst_grab(); /*! Init thread waits for SST completion */ From e4f5e49cd6de1c9e4899a6e6f5c6666434e02437 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 29 Nov 2013 13:03:00 -0500 Subject: [PATCH 094/294] MDEV#4109: Galera: Valgrind warnings "blocks are still reachable" in wsrep_init_startup on MTR tests The initialization & de-initialization of wsrep plugin is solely controlled by wsrep_on system variable. Now, as wsrep_on is ON by default, the plugin gets initialized during server start. However, there would be a leakage in case wsrep_on is turned off before plugin's deinitialization (while server is shutting down) takes place, in which case the deinit routine will not be invoked. In this particular case, wsrep_on is turned off as no wsrep provider has been specified & thus the valgrind warnings. Fixed by introducing a flag which tracks and now controls the (de|)initialization of the wsrep plugin instead on wsrep_on. Added necessary asserts. main.connect [ pass ] 16534 valgrind_report [ pass ] --- sql/mysqld.cc | 3 ++- sql/wsrep_mysqld.cc | 11 +++++++++++ sql/wsrep_mysqld.h | 3 +++ sql/wsrep_var.cc | 3 ++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 80aa5c6a2f1..451269fcf56 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1751,7 +1751,8 @@ static void __cdecl kill_server(int sig_ptr) close_connections(); #ifdef WITH_WSREP - if (WSREP_ON) wsrep_deinit(); + if (wsrep_inited == 1) + wsrep_deinit(); #endif if (sig != MYSQL_KILL_SIGNAL && sig != 0) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 39c8349c4f2..2181054a34c 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -56,6 +56,11 @@ my_bool wsrep_desync = 0; // desynchronize the node from the c * End configuration options */ +/* + * Other wsrep global variables. + */ +my_bool wsrep_inited = 0; // initialized ? + static const wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; const wsrep_uuid_t* wsrep_cluster_uuid() { @@ -414,6 +419,7 @@ static void wsrep_init_position() int wsrep_init() { int rcode= -1; + DBUG_ASSERT(wsrep_inited == 0); wsrep_ready_set(FALSE); assert(wsrep_provider); @@ -442,6 +448,7 @@ int wsrep_init() { // enable normal operation in case no provider is specified wsrep_ready_set(TRUE); + wsrep_inited= 1; global_system_variables.wsrep_on = 0; return 0; } @@ -565,6 +572,8 @@ int wsrep_init() WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); free(wsrep); wsrep = NULL; + } else { + wsrep_inited= 1; } return rcode; @@ -595,6 +604,7 @@ void wsrep_init_startup (bool first) void wsrep_deinit() { + DBUG_ASSERT(wsrep_inited == 1); wsrep_unload(wsrep); wsrep= 0; provider_name[0]= '\0'; @@ -603,6 +613,7 @@ void wsrep_deinit() delete wsrep_format_desc; wsrep_format_desc= NULL; + wsrep_inited= 0; } void wsrep_recover() diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 20d356a22a9..37e72123c59 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -117,6 +117,9 @@ extern const char* wsrep_provider_vendor; extern int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); extern void wsrep_free_status(THD *thd); +// Other wsrep global variables +extern my_bool wsrep_inited; // whether wsrep is initialized ? + #define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_NODE_INCOMING_AUTO "AUTO" diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 94ac902506f..5dc9a475e0d 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -247,7 +247,8 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) wsrep_stop_replication(thd); mysql_mutex_lock(&LOCK_global_system_variables); - wsrep_deinit(); + if (wsrep_inited == 1) + wsrep_deinit(); char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider //when fails From 730466b3282bd23054f86fa7979db1a83703ef89 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 30 Nov 2013 07:46:53 -0500 Subject: [PATCH 095/294] MDEV#4138: Galera: mysqld_safe doesn't pass on wsrep_provider to mysqld In mysqld_safe script, during the processing of command line options, the supplied wsrep_provider option was not getting appended to the set of mysqld options. Hence, wsrep plugin would never receive the path for wsrep provider. Fixed by adding logic to append the wsrep_provider option to the set of mysqld options. --- scripts/mysqld_safe.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 1e84a368849..5581a3aceea 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -328,6 +328,7 @@ parse_arguments() { then wsrep_restart=1 fi + append_arg_to_args "$arg" ;; --help) usage ;; From 9379edb63d85bcb256a4e145827db9c4c76f15c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 2 Dec 2013 08:58:06 +0200 Subject: [PATCH 096/294] MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT Analysis: Currently you can set binlog_format to STATEMENT or MIXED even when they are not really supported by galera. Fix: Produce an error message if binlog_format is set to STATEMENT or MIXED and wsrep_on = ON. Added a test case for this. --- mysql-test/include/have_wsrep.inc | 4 +++ mysql-test/r/have_wsrep.require | 2 ++ mysql-test/suite/wsrep/r/binlog_format.result | 33 +++++++++++++++++++ mysql-test/suite/wsrep/t/binlog_format.opt | 1 + mysql-test/suite/wsrep/t/binlog_format.test | 24 ++++++++++++++ sql/sys_vars.cc | 20 +++++++++++ 6 files changed, 84 insertions(+) create mode 100644 mysql-test/include/have_wsrep.inc create mode 100644 mysql-test/r/have_wsrep.require create mode 100644 mysql-test/suite/wsrep/r/binlog_format.result create mode 100644 mysql-test/suite/wsrep/t/binlog_format.opt create mode 100644 mysql-test/suite/wsrep/t/binlog_format.test diff --git a/mysql-test/include/have_wsrep.inc b/mysql-test/include/have_wsrep.inc new file mode 100644 index 00000000000..f8f7e7a82fc --- /dev/null +++ b/mysql-test/include/have_wsrep.inc @@ -0,0 +1,4 @@ +-- require r/have_wsrep.require +disable_query_log; +show variables like 'wsrep_on'; +enable_query_log; diff --git a/mysql-test/r/have_wsrep.require b/mysql-test/r/have_wsrep.require new file mode 100644 index 00000000000..af32ac7dca7 --- /dev/null +++ b/mysql-test/r/have_wsrep.require @@ -0,0 +1,2 @@ +Variable_name Value +wsrep_on ON diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result new file mode 100644 index 00000000000..d87cd3bf1a8 --- /dev/null +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -0,0 +1,33 @@ +SHOW VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +SET binlog_format=STATEMENT; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' +SHOW WARNINGS; +Level Code Message +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Error 1231 Variable 'binlog_format' can't be set to the value of 'STATEMENT' +SHOW VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +SET binlog_format=MIXED; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' +SHOW WARNINGS; +Level Code Message +Warning 1105 MariaDB Galera does not support binlog format: MIXED +Error 1231 Variable 'binlog_format' can't be set to the value of 'MIXED' +SHOW VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +CREATE TABLE IF NOT EXISTS test.t2 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +SET binlog_format=ROW; +SHOW WARNINGS; +Level Code Message +SHOW VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +CREATE TABLE IF NOT EXISTS test.t3 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt new file mode 100644 index 00000000000..901ead9a41d --- /dev/null +++ b/mysql-test/suite/wsrep/t/binlog_format.opt @@ -0,0 +1 @@ +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/libgalera_smm.so --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin \ No newline at end of file diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test new file mode 100644 index 00000000000..907fae5f4fb --- /dev/null +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -0,0 +1,24 @@ +--source include/have_wsrep.inc +--source include/have_binlog_format_row.inc +# +# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT +# +SHOW VARIABLES LIKE 'binlog_format'; +-- error ER_WRONG_VALUE_FOR_VAR +SET binlog_format=STATEMENT; +SHOW WARNINGS; +SHOW VARIABLES LIKE 'binlog_format'; +CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +-- error ER_WRONG_VALUE_FOR_VAR +SET binlog_format=MIXED; +SHOW WARNINGS; +SHOW VARIABLES LIKE 'binlog_format'; +CREATE TABLE IF NOT EXISTS test.t2 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +SET binlog_format=ROW; +SHOW WARNINGS; +SHOW VARIABLES LIKE 'binlog_format'; +CREATE TABLE IF NOT EXISTS test.t3 AS SELECT * FROM information_schema.routines WHERE 1 = 0; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; + diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 98f4e644171..ef70b1e77d0 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -308,6 +308,26 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT)) return true; +#ifdef WITH_WSREP + /* MariaDB Galera does not support STATEMENT or MIXED binlog + format currently */ + if (WSREP(thd) && + (var->save_result.ulonglong_value == BINLOG_FORMAT_STMT || + var->save_result.ulonglong_value == BINLOG_FORMAT_MIXED)) + { + WSREP_DEBUG("MariaDB Galera does not support binlog format : %s", + var->save_result.ulonglong_value == BINLOG_FORMAT_STMT ? + "STATEMENT" : "MIXED"); + /* Push also warning, because error message is general */ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "MariaDB Galera does not support binlog format: %s", + var->save_result.ulonglong_value == BINLOG_FORMAT_STMT ? + "STATEMENT" : "MIXED"); + return true; + } +#endif + return false; } From eea69c57b2479192a6e5cb59e7631029edb3b35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 4 Dec 2013 13:42:17 +0200 Subject: [PATCH 097/294] Fixed additional problem with kernel_mutex. Kernel mutex is also held on lock_rec_other_has_conflicting that will also call (eventually) wsrep_innobase_kill_one_trx. Added a new parameter have_kernel_mutex to mark do we already own kernel mutex or not. --- storage/innobase/handler/ha_innodb.cc | 29 ++++++++++++++++++++---- storage/innobase/include/ha_prototypes.h | 5 ++-- storage/innobase/lock/lock0lock.c | 2 +- storage/xtradb/handler/ha_innodb.cc | 28 +++++++++++++++++++---- storage/xtradb/include/ha_prototypes.h | 5 ++-- storage/xtradb/lock/lock0lock.c | 4 ++-- 6 files changed, 56 insertions(+), 17 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 028eea45726..7cc21ce5a8e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12541,14 +12541,25 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) (long long)bf_seqno, (long long)victim_seqno); abort(); } +/*******************************************************************//** +This function is used to kill one transaction in BF. */ int -wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, ibool signal) +wsrep_innobase_kill_one_trx( + void *bf_thd_ptr, /*!< in: BF thd */ + trx_t *bf_trx, /*!< in: BF trx */ + trx_t *victim_trx, /*!< in: victim trx */ + ibool signal, /*!< in: signal to be used */ + ibool have_kernel_mutex) /*!mysql_thd; int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + if (have_kernel_mutex) { + ut_ad(mutex_own(&kernel_mutex)); + } + if (!bf_thd) bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; if (!thd) { @@ -12662,9 +12673,16 @@ wsrep_innobase_kill_one_trx(void *bf_thd_ptr, trx_t *bf_trx, trx_t *victim_trx, if (wait_lock) { WSREP_DEBUG("canceling wait lock"); victim_trx->was_chosen_as_deadlock_victim= TRUE; - mutex_enter(&kernel_mutex); + if (!have_kernel_mutex) { + mutex_enter(&kernel_mutex); + } lock_cancel_waiting_and_release(wait_lock); - mutex_exit(&kernel_mutex); + /* If we already have kernel mutex when we + arrived to this function, do not yet release + it */ + if (!have_kernel_mutex) { + mutex_exit(&kernel_mutex); + } } wsrep_thd_awake(bf_thd, thd, signal); @@ -12749,6 +12767,9 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, DBUG_ENTER("wsrep_innobase_abort_thd"); trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + + ut_ad(!mutex_own(&kernel_mutex)); + WSREP_DEBUG("abort transaction: BF: %s victim: %s", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd)); @@ -12756,7 +12777,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { int rcode = wsrep_innobase_kill_one_trx( - bf_thd, bf_trx, victim_trx, signal); + bf_thd, bf_trx, victim_trx, signal, FALSE); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 8fdc4b6265d..4ed11d8e410 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -286,9 +286,8 @@ thd_set_lock_wait_time( ulint value); /*!< in: time waited for the lock */ #ifdef WITH_WSREP -UNIV_INTERN -int -wsrep_innobase_kill_one_trx(void *bf_thd, trx_t *bf_trx, trx_t *victim_trx, ibool signal); +UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx, + ibool signal, ibool have_kernel_mutex); int wsrep_thd_is_brute_force(void *thd_ptr); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 2fc16cc51f7..6e762f65679 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1560,7 +1560,7 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) { } } wsrep_innobase_kill_one_trx( - trx->mysql_thd, trx, lock->trx, TRUE); + trx->mysql_thd, trx, lock->trx, TRUE, TRUE); } } } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d1c6a971e4d..9a40b9eef84 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13873,14 +13873,24 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) (long long)bf_seqno, (long long)victim_seqno); abort(); } +/*******************************************************************//** +This function is used to kill one transaction in BF. */ int -wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) +wsrep_innobase_kill_one_trx( + trx_t *bf_trx, /*!< in: BF trx */ + trx_t *victim_trx, /*!< in: victim trx */ + ibool signal, /*!< in: signal to be used */ + ibool have_kernel_mutex) /*!mysql_thd; THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + if (have_kernel_mutex) { + ut_ad(mutex_own(&kernel_mutex)); + } + if (!thd) { DBUG_PRINT("wsrep", ("no thd for conflicting lock")); WSREP_WARN("no THD for trx: %llu", victim_trx->id); @@ -13985,9 +13995,16 @@ wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) if (wait_lock) { WSREP_DEBUG("canceling wait lock"); victim_trx->was_chosen_as_deadlock_victim= TRUE; - mutex_enter(&kernel_mutex); + if (!have_kernel_mutex) { + mutex_enter(&kernel_mutex); + } lock_cancel_waiting_and_release(wait_lock); - mutex_exit(&kernel_mutex); + /* If we already have kernel mutex when we + arrived to this function, do not yet release + it */ + if (!have_kernel_mutex) { + mutex_exit(&kernel_mutex); + } } wsrep_thd_awake(bf_thd, thd, signal); @@ -14072,6 +14089,9 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, DBUG_ENTER("wsrep_innobase_abort_thd"); trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + + ut_ad(!mutex_own(&kernel_mutex)); + WSREP_DEBUG("abort transaction: BF: %s victim: %s", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd)); @@ -14079,7 +14099,7 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, - signal); + signal, FALSE); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index ad6bfb8c4c4..373c4956ca5 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -301,9 +301,8 @@ thd_flush_log_at_trx_commit( void* thd); #ifdef WITH_WSREP -UNIV_INTERN -int -wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal); +UNIV_INTERN int wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, + ibool signal, ibool have_kernel_mutex); int wsrep_thd_is_brute_force(void *thd_ptr); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index b63683b1eac..36188b03cec 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -1533,7 +1533,7 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) { /* cannot release lock, until our lock is in the queue*/ } else if (lock->trx != trx) { - wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE); + wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE, TRUE); } } } @@ -4245,7 +4245,7 @@ lock_table_other_has_incompatible( } else { if (bf_this && bf_other) wsrep_innobase_kill_one_trx( - (trx_t *)trx, lock->trx, TRUE); + (trx_t *)trx, lock->trx, TRUE, TRUE); return(lock); } } else { From ed26f7012640f4e1f65776f7bbc57fba5e87b0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 4 Dec 2013 13:46:28 +0200 Subject: [PATCH 098/294] MDEV-443: Galera: Server crashes on flushing tables for SST if started with character_set_server utf16 or utf32 or ucs2, and with wsrep_sst_method=rsync Analysis: In SST Galera directly calls parser using current client character set. Similarly in BF Galera uses client character set to apply. However, there are character sets that are not currently supported by the parser. Fix: If currenct client character set is one of those that is not supported by the parser, temporally set character set to latin1 before we enter parser and restore it after we have parsed. --- sql/sql_parse.cc | 23 ++++++++++++++++++++++- sql/wsrep_sst.cc | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7933d95de68..21eb62149ca 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -892,8 +892,17 @@ bool do_command(THD *thd) if (WSREP(thd)) { while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) { - return_value= dispatch_command(command, thd, 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); + } + return_value= dispatch_command(command, thd, thd->wsrep_retry_query, thd->wsrep_retry_query_len); + thd->variables.character_set_client = current_charset; } } if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING) @@ -8119,6 +8128,7 @@ static enum wsrep_status wsrep_apply_sql( { int error; enum wsrep_status ret_code= WSREP_OK; + CHARSET_INFO *current_charset = thd->variables.character_set_client; DBUG_ENTER("wsrep_bf_execute_cb"); thd->wsrep_exec_mode= REPL_RECV; @@ -8137,11 +8147,22 @@ static enum wsrep_status wsrep_apply_sql( thd->wsrep_conflict_state= NO_CONFLICT; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + 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 BF SQL apply temporally setting character set to : %s", + my_charset_latin1.csname); + } + if ((error= dispatch_command(COM_QUERY, thd, (char*)sql, sql_len))) { WSREP_WARN("BF SQL apply failed: %d, %lld", thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); + thd->variables.character_set_client = current_charset; DBUG_RETURN(WSREP_FATAL); } + thd->variables.character_set_client = current_charset; mysql_mutex_lock(&thd->LOCK_wsrep_thd); if (thd->wsrep_conflict_state!= NO_CONFLICT && diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 204a937ea8f..7afdb4909e4 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -14,6 +14,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include +#include +#include #include #include #include @@ -742,6 +745,19 @@ static int sst_flush_tables(THD* thd) int err; int not_used; + CHARSET_INFO *current_charset; + + 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 SST temporally setting character set to : %s", + my_charset_latin1.csname); + } + if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) { WSREP_ERROR("Failed to flush and lock tables"); @@ -754,6 +770,9 @@ static int sst_flush_tables(THD* thd) (TABLE_LIST*) 0, ¬_used); } + thd->variables.character_set_client = current_charset; + + if (err) { WSREP_ERROR("Failed to flush tables: %d (%s)", err, strerror(err)); @@ -796,6 +815,19 @@ static void sst_disallow_writes (THD* thd, bool yes) { 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; + + 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 SST temporally setting character set to : %s", + my_charset_latin1.csname); + } + snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", yes ? 1 : 0); @@ -803,6 +835,7 @@ static void sst_disallow_writes (THD* thd, bool yes) { WSREP_ERROR("Failed to disallow InnoDB writes"); } + thd->variables.character_set_client = current_charset; } static void* sst_donor_thread (void* a) From 329fb586568f822e6ccb6faeb2e950a644b459d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 4 Dec 2013 18:49:40 +0200 Subject: [PATCH 099/294] MDEV-5385: Debian MariaDB-Galera packages do not get built in buildbot Added missing .in files and updated CMakeLists.txt to contain galera specific files. --- CMakeLists.txt | 4 +- .../dist/Debian/mariadb-galera-server-5.5.in | 74 ++++++++++++++++++ .../dist/Ubuntu/mariadb-galera-server-5.5.in | 76 +++++++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 debian/dist/Debian/mariadb-galera-server-5.5.in create mode 100644 debian/dist/Ubuntu/mariadb-galera-server-5.5.in diff --git a/CMakeLists.txt b/CMakeLists.txt index fe721fb02bb..4f9dbbb2837 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -362,8 +362,8 @@ CONFIGURE_FILE( IF(DEB) CONFIGURE_FILE( - ${CMAKE_SOURCE_DIR}/debian/mariadb-server-5.5.files.in - ${CMAKE_SOURCE_DIR}/debian/mariadb-server-5.5.files) + ${CMAKE_SOURCE_DIR}/debian/mariadb-galera-server-5.5.files.in + ${CMAKE_SOURCE_DIR}/debian/mariadb-galera-server-5.5.files) ENDIF(DEB) # Handle the "INFO_*" files. diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.in b/debian/dist/Debian/mariadb-galera-server-5.5.in new file mode 100644 index 00000000000..eb9ba7a9a2c --- /dev/null +++ b/debian/dist/Debian/mariadb-galera-server-5.5.in @@ -0,0 +1,74 @@ +usr/lib/mysql/plugin/ha_innodb.so +usr/lib/mysql/plugin/ha_oqgraph.so +usr/lib/mysql/plugin/sphinx.so +usr/lib/mysql/plugin/auth_socket.so +usr/lib/mysql/plugin/auth_pam.so +usr/lib/mysql/plugin/semisync_master.so +usr/lib/mysql/plugin/semisync_slave.so +usr/lib/mysql/plugin/handlersocket.so +usr/lib/mysql/plugin/sql_errlog.so +usr/lib/libhsclient.so.* +etc/mysql/debian-start +etc/mysql/conf.d/mysqld_safe_syslog.cnf +usr/bin/msql2mysql +usr/bin/my_print_defaults +usr/bin/myisamchk +usr/bin/myisam_ftdump +usr/bin/myisamlog +usr/bin/myisampack +usr/bin/aria_pack +usr/bin/aria_read_log +usr/bin/aria_ftdump +usr/bin/aria_chk +usr/bin/aria_dump_log +usr/bin/mysql_convert_table_format +usr/bin/mysql_install_db +usr/bin/mysql_plugin +usr/bin/mysql_secure_installation +usr/bin/mysql_setpermission +usr/bin/mysql_tzinfo_to_sql +usr/bin/mysql_upgrade +usr/bin/mysql_zap +usr/bin/mysqlbinlog +usr/bin/mysqld_multi +usr/bin/mysqld_safe +usr/bin/mysqlhotcopy +usr/bin/perror +usr/bin/replace +usr/bin/resolve_stack_dump +usr/bin/resolveip +usr/share/doc/mariadb-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-server-5.5/INFO_SRC +usr/share/doc/mariadb-server-5.5/INFO_BIN +usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/man/man1/msql2mysql.1 +usr/share/man/man1/myisamchk.1 +usr/share/man/man1/myisam_ftdump.1 +usr/share/man/man1/myisamlog.1 +usr/share/man/man1/myisampack.1 +usr/share/man/man1/my_print_defaults.1 +usr/share/man/man1/mysqlbinlog.1 +usr/share/man/man1/mysql_convert_table_format.1 +usr/share/man/man1/mysqld_multi.1 +usr/share/man/man1/mysqld_safe.1 +usr/share/man/man1/mysqlhotcopy.1 +usr/share/man/man1/mysql_install_db.1 +usr/share/man/man1/mysql_secure_installation.1 +usr/share/man/man1/mysql_setpermission.1 +usr/share/man/man1/mysql_upgrade.1 +usr/share/man/man1/mysql_zap.1 +usr/share/man/man1/perror.1 +usr/share/man/man1/replace.1 +usr/share/man/man1/resolveip.1 +usr/share/man/man1/resolve_stack_dump.1 +usr/share/man/man1/innochecksum.1 +usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/mysql/debian-start.inc.sh +usr/share/mysql/echo_stderr +usr/share/mysql/errmsg-utf8.txt +usr/share/mysql/fill_help_tables.sql +usr/share/mysql/mysql_system_tables_data.sql +usr/share/mysql/mysql_system_tables.sql +usr/share/mysql/mysql_performance_tables.sql +usr/share/mysql/mysql_test_data_timezone.sql +@TOKUDB_DEB_FILES@ diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.in new file mode 100644 index 00000000000..4921d3fa267 --- /dev/null +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.in @@ -0,0 +1,76 @@ +usr/lib/mysql/plugin/ha_innodb.so +usr/lib/mysql/plugin/ha_oqgraph.so +usr/lib/mysql/plugin/sphinx.so +usr/lib/mysql/plugin/auth_socket.so +usr/lib/mysql/plugin/auth_pam.so +usr/lib/mysql/plugin/semisync_master.so +usr/lib/mysql/plugin/semisync_slave.so +usr/lib/mysql/plugin/handlersocket.so +usr/lib/mysql/plugin/sql_errlog.so +usr/lib/libhsclient.so.* +etc/apparmor.d/usr.sbin.mysqld +usr/share/apport/package-hooks/source_mariadb-5.5.py +etc/mysql/debian-start +etc/mysql/conf.d/mysqld_safe_syslog.cnf +usr/bin/msql2mysql +usr/bin/my_print_defaults +usr/bin/myisamchk +usr/bin/myisam_ftdump +usr/bin/myisamlog +usr/bin/myisampack +usr/bin/aria_pack +usr/bin/aria_read_log +usr/bin/aria_ftdump +usr/bin/aria_chk +usr/bin/aria_dump_log +usr/bin/mysql_convert_table_format +usr/bin/mysql_install_db +usr/bin/mysql_plugin +usr/bin/mysql_secure_installation +usr/bin/mysql_setpermission +usr/bin/mysql_tzinfo_to_sql +usr/bin/mysql_upgrade +usr/bin/mysql_zap +usr/bin/mysqlbinlog +usr/bin/mysqld_multi +usr/bin/mysqld_safe +usr/bin/mysqlhotcopy +usr/bin/perror +usr/bin/replace +usr/bin/resolve_stack_dump +usr/bin/resolveip +usr/share/doc/mariadb-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-server-5.5/INFO_SRC +usr/share/doc/mariadb-server-5.5/INFO_BIN +usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/man/man1/msql2mysql.1 +usr/share/man/man1/myisamchk.1 +usr/share/man/man1/myisam_ftdump.1 +usr/share/man/man1/myisamlog.1 +usr/share/man/man1/myisampack.1 +usr/share/man/man1/my_print_defaults.1 +usr/share/man/man1/mysqlbinlog.1 +usr/share/man/man1/mysql_convert_table_format.1 +usr/share/man/man1/mysqld_multi.1 +usr/share/man/man1/mysqld_safe.1 +usr/share/man/man1/mysqlhotcopy.1 +usr/share/man/man1/mysql_install_db.1 +usr/share/man/man1/mysql_secure_installation.1 +usr/share/man/man1/mysql_setpermission.1 +usr/share/man/man1/mysql_upgrade.1 +usr/share/man/man1/mysql_zap.1 +usr/share/man/man1/perror.1 +usr/share/man/man1/replace.1 +usr/share/man/man1/resolveip.1 +usr/share/man/man1/resolve_stack_dump.1 +usr/share/man/man1/innochecksum.1 +usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/mysql/debian-start.inc.sh +usr/share/mysql/echo_stderr +usr/share/mysql/errmsg-utf8.txt +usr/share/mysql/fill_help_tables.sql +usr/share/mysql/mysql_system_tables_data.sql +usr/share/mysql/mysql_system_tables.sql +usr/share/mysql/mysql_performance_tables.sql +usr/share/mysql/mysql_test_data_timezone.sql +@TOKUDB_DEB_FILES@ From f41ee56df7b7cd841a2d9ac6a753f752742cd2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 5 Dec 2013 14:53:22 +0200 Subject: [PATCH 100/294] MDEV-5386: Server crashes in thd_get_ha_data on maria-5.5-galera tree while running 'check testcase before test Analysis: In Galera binlog is not enabled by default in case when wsrep provider is not specified. In this case we should not call thd->binlog_flush_pending_rows_event(TRUE). Fix: Added a additional guard on galera not to call binlog function if wsrep provider is not specified and binlog is not enabled. --- sql/sql_base.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5597ba40f90..62fb340cc6e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,7 +62,7 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" - +extern handlerton *binlog_hton; #endif // WITH_WSREP bool @@ -1575,6 +1575,11 @@ void close_thread_tables(THD *thd) handled either before writing a query log event (inside binlog_query()) or when preparing a pending event. */ +#ifdef WITH_WSREP + /* In Galera binlog is not enabled by default in case when + wsrep provider is not specified. */ + if ((WSREP_ON && WSREP_PROVIDER_EXISTS) || binlog_hton->state == SHOW_OPTION_YES) +#endif (void)thd->binlog_flush_pending_rows_event(TRUE); mysql_unlock_tables(thd, thd->lock); thd->lock=0; From 8acebe6d639500d90288a34c6d0cbc217fe2f1ca Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 5 Dec 2013 10:59:18 -0500 Subject: [PATCH 101/294] MDEV#5384: Update init script in MariaDB Cluster Reduced the sleep time to 10secs. --- support-files/mysql.server.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 911924c7ee2..8da75c92a6c 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -196,9 +196,9 @@ wait_for_pid () { fi fi - if test -e $sst_progress_file && [ $startup_sleep -ne 100 ];then + if test -e $sst_progress_file && [ $startup_sleep -ne 10 ];then echo $echo_n "SST in progress, setting sleep higher" - startup_sleep=100 + startup_sleep=10 fi echo $echo_n ".$echo_c" From af2bb9de9d71dd55f2e4a36ef18ca22a018515e5 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 7 Dec 2013 12:30:53 -0500 Subject: [PATCH 102/294] Fix for a failing test. --- mysql-test/r/mysql_tzinfo_to_sql_symlink.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result index fce61687c83..1aaaa38895d 100644 --- a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result @@ -1,6 +1,7 @@ # # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above # +SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; From 3df2aa9458dae45b7b9667672da30252d1a75ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 5 Dec 2013 19:22:00 +0200 Subject: [PATCH 103/294] MDEV-5385: Debian MariaDB-Galera packages do not get built in buildbot Analysis: File names were incorrect for distribution files. Fix: Fixed file names to be same as in 5.5. --- ...db-galera-server-5.5.in => mariadb-galera-server-5.5.files.in} | 0 ...db-galera-server-5.5.in => mariadb-galera-server-5.5.files.in} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename debian/dist/Debian/{mariadb-galera-server-5.5.in => mariadb-galera-server-5.5.files.in} (100%) rename debian/dist/Ubuntu/{mariadb-galera-server-5.5.in => mariadb-galera-server-5.5.files.in} (100%) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in similarity index 100% rename from debian/dist/Debian/mariadb-galera-server-5.5.in rename to debian/dist/Debian/mariadb-galera-server-5.5.files.in diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in similarity index 100% rename from debian/dist/Ubuntu/mariadb-galera-server-5.5.in rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in From ded756c90dd92ddc656d92ea29fd66a3c7181767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 10 Dec 2013 10:14:43 +0200 Subject: [PATCH 104/294] MDEV-5408: Crash in mariadb-wsrep during plugin load at startup Analysis: If wsrep_provider is not specified ("none") the wsrep is not initialized. Fix: Add additional guard not to call wsrep->post_rollback if wsrep_provider is not specified. --- sql/wsrep_hton.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 203f0888550..d4bb77c9e6f 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -248,11 +248,13 @@ int wsrep_commit(handlerton *hton, THD *thd, bool all) Transaction didn't go through wsrep->pre_commit() so just roll back possible changes to clean state. */ - if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) - { - DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + if (WSREP_PROVIDER_EXISTS) { + if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) + { + DBUG_PRINT("wsrep", ("setting rollback fail")); + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", (long long)thd->real_id, thd->query()); + } } wsrep_cleanup_transaction(thd); } From 170c3c2b213a29b90aa948e1879cae334d48b1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 10 Dec 2013 10:34:41 +0200 Subject: [PATCH 105/294] MDEV-5423: Debian MariaDB-Galera packages do not get built in buildbot [Part 2] Fix: Server name is mariadb-galera-5.5 --- debian/dist/Debian/mariadb-galera-server-5.5.dirs | 2 +- debian/dist/Debian/mariadb-galera-server-5.5.files.in | 6 +++--- debian/dist/Debian/rules | 6 +++--- debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs | 2 +- debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in | 8 ++++---- debian/dist/Ubuntu/rules | 8 ++++---- storage/tokudb/CMakeLists.txt | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.dirs b/debian/dist/Debian/mariadb-galera-server-5.5.dirs index 4f82cf4c4f2..0e3b2ce5af8 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Debian/mariadb-galera-server-5.5.dirs @@ -5,7 +5,7 @@ usr/bin usr/sbin usr/share/man/man8 usr/share/mysql -usr/share/doc/mariadb-server-5.5 +usr/share/doc/mariadb-galera-server-5.5 usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index eb9ba7a9a2c..0ffad95e533 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -37,9 +37,9 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip -usr/share/doc/mariadb-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-server-5.5/INFO_SRC -usr/share/doc/mariadb-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-galera-server-5.5/INFO_SRC +usr/share/doc/mariadb-galera-server-5.5/INFO_BIN usr/share/lintian/overrides/mariadb-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index dcd1b346a82..ac11b76bd24 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -168,7 +168,7 @@ install: build # mariadb-server install -m 0755 $(BUILDDIR)/scripts/mysqld_safe $(TMP)/usr/bin/mysqld_safe - mkdir -p $(TMP)/usr/share/doc/mariadb-server-5.5/examples + mkdir -p $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples # We have a sane my.cnf, cruft not needed (remove my-*.cnf and config-*.cnf) # $(TMP)/usr/share/mysql/*cnf $(TMP)/usr/share/doc/mariadb-server-5.5/examples/ rm -vf $(TMP)/usr/share/mysql/my-*.cnf \ @@ -182,8 +182,8 @@ install: build install -m 0755 debian/additions/debian-start $(TMP)/etc/mysql/ install -m 0755 debian/additions/debian-start.inc.sh $(TMP)/usr/share/mysql/ - install -m 0644 $(builddir)/Docs/INFO_SRC $(TMP)/usr/share/doc/mariadb-server-5.5/INFO_SRC - install -m 0644 $(builddir)/Docs/INFO_BIN $(TMP)/usr/share/doc/mariadb-server-5.5/INFO_BIN + install -m 0644 $(builddir)/Docs/INFO_SRC $(TMP)/usr/share/doc/mariadb-galera-server-5.5/INFO_SRC + install -m 0644 $(builddir)/Docs/INFO_BIN $(TMP)/usr/share/doc/mariadb-galera-server-5.5/INFO_BIN # mariadb-test mv $(TMP)/usr/mysql-test $(TMP)/usr/share/mysql diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs index 4f82cf4c4f2..0e3b2ce5af8 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs @@ -5,7 +5,7 @@ usr/bin usr/sbin usr/share/man/man8 usr/share/mysql -usr/share/doc/mariadb-server-5.5 +usr/share/doc/mariadb-galera-server-5.5 usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in index 4921d3fa267..231c5d4313b 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in @@ -39,10 +39,10 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip -usr/share/doc/mariadb-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-server-5.5/INFO_SRC -usr/share/doc/mariadb-server-5.5/INFO_BIN -usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz +usr/share/doc/mariadb-galera-server-5.5/INFO_SRC +usr/share/doc/mariadb-galera-server-5.5/INFO_BIN +usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 usr/share/man/man1/myisam_ftdump.1 diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index fc1d840d924..387534ba18b 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -168,9 +168,9 @@ install: build # mariadb-server install -m 0755 $(BUILDDIR)/scripts/mysqld_safe $(TMP)/usr/bin/mysqld_safe - mkdir -p $(TMP)/usr/share/doc/mariadb-server-5.5/examples + mkdir -p $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples # We have a sane my.cnf, cruft not needed (remove my-*.cnf and config-*.cnf) - # $(TMP)/usr/share/mysql/*cnf $(TMP)/usr/share/doc/mariadb-server-5.5/examples/ + # $(TMP)/usr/share/mysql/*cnf $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples/ rm -vf $(TMP)/usr/share/mysql/my-*.cnf \ $(TMP)/usr/share/mysql/config-*.cnf \ $(TMP)/usr/share/mysql/mi_test_all* \ @@ -182,8 +182,8 @@ install: build install -m 0755 debian/additions/debian-start $(TMP)/etc/mysql/ install -m 0755 debian/additions/debian-start.inc.sh $(TMP)/usr/share/mysql/ - install -m 0644 $(builddir)/Docs/INFO_SRC $(TMP)/usr/share/doc/mariadb-server-5.5/INFO_SRC - install -m 0644 $(builddir)/Docs/INFO_BIN $(TMP)/usr/share/doc/mariadb-server-5.5/INFO_BIN + install -m 0644 $(builddir)/Docs/INFO_SRC $(TMP)/usr/share/doc/mariadb-galera-server-5.5/INFO_SRC + install -m 0644 $(builddir)/Docs/INFO_BIN $(TMP)/usr/share/doc/mariadb-galera-server-5.5/INFO_BIN # mariadb-test mv $(TMP)/usr/mysql-test $(TMP)/usr/share/mysql diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index c5197dd5dc0..fc65e489dbd 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -16,7 +16,7 @@ ENDIF() ############################################ SET(ENV{TOKUDB_VERSION} "7.0.4") -SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-server-5.5/README-TOKUDB\nusr/share/doc/mariadb-server-5.5/README.md" PARENT_SCOPE) +SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-galera-server-5.5/README-TOKUDB\nusr/share/doc/mariadb-galera-server-5.5/README.md" PARENT_SCOPE) SET(USE_BDB OFF CACHE BOOL "") SET(USE_VALGRIND OFF CACHE BOOL "") SET(BUILD_TESTING OFF CACHE BOOL "") From 3ad45220bc848e6cb5a06cbd71fdfb6970b5f3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 10 Dec 2013 17:45:02 +0200 Subject: [PATCH 106/294] Additional name fixes. --- debian/dist/Debian/mariadb-galera-server-5.5.files | 2 +- debian/dist/Debian/rules | 6 +++--- debian/dist/Ubuntu/mariadb-galera-server-5.5.files | 2 +- debian/dist/Ubuntu/mariadb-server-5.5.py | 2 +- debian/dist/Ubuntu/rules | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files index fcac1651291..fba6d8b2208 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files @@ -46,7 +46,7 @@ usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN usr/share/doc/mariadb-galera-server-5.5/README-wsrep -usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 usr/share/man/man1/myisam_ftdump.1 diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index ac11b76bd24..2d3db49356f 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -166,11 +166,11 @@ install: build install -m 0755 debian/additions/innotop/innotop $(TMP)/usr/bin/ install -m 0644 debian/additions/innotop/innotop.1 $(TMP)/usr/share/man/man1/ - # mariadb-server + # mariadb-galera-server install -m 0755 $(BUILDDIR)/scripts/mysqld_safe $(TMP)/usr/bin/mysqld_safe mkdir -p $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples # We have a sane my.cnf, cruft not needed (remove my-*.cnf and config-*.cnf) - # $(TMP)/usr/share/mysql/*cnf $(TMP)/usr/share/doc/mariadb-server-5.5/examples/ + # $(TMP)/usr/share/mysql/*cnf $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples/ rm -vf $(TMP)/usr/share/mysql/my-*.cnf \ $(TMP)/usr/share/mysql/config-*.cnf \ $(TMP)/usr/share/mysql/mi_test_all* \ @@ -190,7 +190,7 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 + cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files index c1591ab8b02..acf5acb036f 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files @@ -48,7 +48,7 @@ usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN usr/share/doc/mariadb-galera-server-5.5/README-wsrep -usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 usr/share/man/man1/myisam_ftdump.1 diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.py b/debian/dist/Ubuntu/mariadb-server-5.5.py index a1372a3baf5..1a94e1399a2 100644 --- a/debian/dist/Ubuntu/mariadb-server-5.5.py +++ b/debian/dist/Ubuntu/mariadb-server-5.5.py @@ -20,7 +20,7 @@ def _add_my_conf_files(report, filename): continue def add_info(report): - attach_conffiles(report, 'mariadb-server-5.5', conffiles=None) + attach_conffiles(report, 'mariadb-galera-server-5.5', conffiles=None) key = 'Logs' + path_to_key('/var/log/daemon.log') report[key] = "" for line in read_file('/var/log/daemon.log').split('\n'): diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 387534ba18b..5e9609b6c8c 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -166,7 +166,7 @@ install: build install -m 0755 debian/additions/innotop/innotop $(TMP)/usr/bin/ install -m 0644 debian/additions/innotop/innotop.1 $(TMP)/usr/share/man/man1/ - # mariadb-server + # mariadb-galera-server install -m 0755 $(BUILDDIR)/scripts/mysqld_safe $(TMP)/usr/bin/mysqld_safe mkdir -p $(TMP)/usr/share/doc/mariadb-galera-server-5.5/examples # We have a sane my.cnf, cruft not needed (remove my-*.cnf and config-*.cnf) @@ -190,7 +190,7 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-5.5 + cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ @@ -202,7 +202,7 @@ install: build # install AppArmor profile install -D -m 644 debian/apparmor-profile $(TMP)/etc/apparmor.d/usr.sbin.mysqld # install Apport hook - install -D -m 644 debian/mariadb-server-5.5.py $(TMP)/usr/share/apport/package-hooks/source_mariadb-5.5.py + install -D -m 644 debian/mariadb-galera-server-5.5.py $(TMP)/usr/share/apport/package-hooks/source_mariadb-5.5.py autorm=debian/autorm-file; \ rm -f $$autorm; \ From e1ed3dcebf649a540a8a5fd6293ef1494757fb38 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Dec 2013 11:30:23 -0500 Subject: [PATCH 107/294] MDEV#5407, MDEV#5386, MVED#4222 Problem: As, wsrep_provider is dynamic and can accept a valid provider while server is running. Patch for #4222 wrongly skips the initialization of binlog plugin during server start, when wsrep provider is not specified. In wsrep build, if opt_log_bin is not provided, we still init binlog with wsrep_emulate_bin_log ON. Fix: This patch fixes #4222 by adding a check to return from binlog_savepoint_set without proceeding further if wsrep_on is OFF/false. This patch also fixes MDEV#5407 and reverts changes pushed for MDEV#5386 (no longer valid). --- sql/log.cc | 10 +++++++++- sql/sql_base.cc | 6 ------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 850980f04f7..242c45a7ed7 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1708,7 +1708,7 @@ int binlog_init(void *p) { binlog_hton= (handlerton *)p; #ifdef WITH_WSREP - if (WSREP_ON && WSREP_PROVIDER_EXISTS) + if (WSREP_ON) binlog_hton->state= SHOW_OPTION_YES; else { @@ -2217,6 +2217,14 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("binlog_savepoint_set"); +#ifdef WITH_WSREP + /* + If wsrep_emulate_bin_log is true, (i.e opt_bin_log == false), + we should return from here if wsrep_on is off. + */ + if (wsrep_emulate_bin_log && !WSREP(thd)) DBUG_RETURN(0); +#endif /* WITH_WSREP */ + binlog_trans_log_savepos(thd, (my_off_t*) sv); /* Write it to the binary log */ #ifdef WITH_WSREP diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 62fb340cc6e..3acfa63d55e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,7 +62,6 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" -extern handlerton *binlog_hton; #endif // WITH_WSREP bool @@ -1575,11 +1574,6 @@ void close_thread_tables(THD *thd) handled either before writing a query log event (inside binlog_query()) or when preparing a pending event. */ -#ifdef WITH_WSREP - /* In Galera binlog is not enabled by default in case when - wsrep provider is not specified. */ - if ((WSREP_ON && WSREP_PROVIDER_EXISTS) || binlog_hton->state == SHOW_OPTION_YES) -#endif (void)thd->binlog_flush_pending_rows_event(TRUE); mysql_unlock_tables(thd, thd->lock); thd->lock=0; From 48e83ba6f79a042022c1949772e999ddb4fd10c4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Dec 2013 22:11:42 -0500 Subject: [PATCH 108/294] * Updated auto_increment_xxx_func.result to reflect the changes made by https://bugs.launchpad.net/codership-mysql/+bug/587170 * Fix for some compiler errors/warnings. --- .../r/auto_increment_increment_func.result | 24 +++++----- .../r/auto_increment_offset_func.result | 44 +++++++++---------- mysys/my_delete.c | 3 +- sql/mysqld.cc | 2 + sql/sql_parse.cc | 2 +- sql/wsrep_mysqld.h | 2 +- storage/innobase/ut/ut0ut.c | 4 +- storage/xtradb/buf/buf0buf.c | 2 + 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result b/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result index df3ca1ab093..a7ce4e99e20 100644 --- a/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result +++ b/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result @@ -142,8 +142,8 @@ id name 116 Record_10 117 Record_11 119 Record_12 -121 Record_13 -123 Record_14 +120 Record_13 +121 Record_14 ## Changing column's datatype to BigInt and verifying variable's behavior ## ALTER table t1 MODIFY id BIGINT NOT NULL auto_increment; INSERT into t1(name) values('Record_15'); @@ -159,10 +159,10 @@ id name 116 Record_10 117 Record_11 119 Record_12 -121 Record_13 -123 Record_14 -125 Record_15 -127 Record_16 +120 Record_13 +121 Record_14 +122 Record_15 +123 Record_16 '#--------------------FN_DYNVARS_001_07-------------------------#' ## Verifying behavior of variable with negative value ## SET @@auto_increment_increment = -10; @@ -181,12 +181,12 @@ id name 116 Record_10 117 Record_11 119 Record_12 -121 Record_13 -123 Record_14 -125 Record_15 -127 Record_16 -128 Record_17 -129 Record_18 +120 Record_13 +121 Record_14 +122 Record_15 +123 Record_16 +124 Record_17 +125 Record_18 ## Disconnecting test_con2 ## ## Dropping table t1 ## DROP table if exists t1; diff --git a/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result b/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result index d2b5b828c04..58ecf95dae3 100644 --- a/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result +++ b/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result @@ -144,8 +144,8 @@ id name 125 Record_12 134 Record_13 140 Record_14 -150 Record_15 -160 Record_16 +141 Record_15 +142 Record_16 ## Changing datatype of column id with primary key to BigInt ## ALTER table t1 modify id BIGINT NOT NULL auto_increment; INSERT into t1(name) values('Record_17'); @@ -166,10 +166,10 @@ id name 125 Record_12 134 Record_13 140 Record_14 -150 Record_15 -160 Record_16 -170 Record_17 -180 Record_18 +141 Record_15 +142 Record_16 +143 Record_17 +144 Record_18 '#--------------------FN_DYNVARS_002_07-------------------------#' ## Assigning -ve value to variable ## SET @@auto_increment_offset = -10; @@ -196,12 +196,12 @@ id name 125 Record_12 134 Record_13 140 Record_14 -150 Record_15 -160 Record_16 -170 Record_17 -180 Record_18 -181 Record_17 -191 Record_18 +141 Record_15 +142 Record_16 +143 Record_17 +144 Record_18 +145 Record_17 +146 Record_18 ## Assigning value that is out of range of variable ## SET @@auto_increment_offset = 65536; Warnings: @@ -229,16 +229,16 @@ id name 125 Record_12 134 Record_13 140 Record_14 -150 Record_15 -160 Record_16 -170 Record_17 -180 Record_18 -181 Record_17 -191 Record_18 -199 Record_17 -209 Record_18 -219 Record_19 -229 Record_20 +141 Record_15 +142 Record_16 +143 Record_17 +144 Record_18 +145 Record_17 +146 Record_18 +147 Record_17 +148 Record_18 +149 Record_19 +150 Record_20 ## No effect of auto_increment_offset since value of this variable is greater ## ## than auto_increment_increment ## ## Dropping table ## diff --git a/mysys/my_delete.c b/mysys/my_delete.c index f5737ea66e0..881bcad9459 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -150,4 +150,5 @@ error: my_osmaperr(last_error); DBUG_RETURN(-1); } -#endif \ No newline at end of file +#endif + diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 451269fcf56..849ceb1db39 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4464,8 +4464,10 @@ will be ignored as the --log-bin option is not defined."); if (wsrep_before_SE()) { +#ifndef EMBEDDED_LIBRARY set_ports(); // this is also called in network_init() later but we need // to know mysqld_port now - lp:1071882 +#endif /* !EMBEDDED_LIBRARY */ wsrep_init_startup(true); } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 21eb62149ca..e8e5d79b370 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8193,7 +8193,7 @@ void wsrep_write_rbr_buf( FILE *of= fopen(filename, "wb"); if (of) { - fwrite (rbr_buf, buf_len, 1, of); + (void) fwrite (rbr_buf, buf_len, 1, of); fclose(of); } else diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 37e72123c59..619711cc4b0 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -285,7 +285,7 @@ extern wsrep_seqno_t wsrep_locked_seqno; 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 (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ } diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 699af1fcaa1..8b9501ee8bc 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -554,7 +554,7 @@ ut_print_namel( trx ? trx->mysql_thd : NULL, table_id); - fwrite(buf, 1, bufend - buf, f); + (void) fwrite(buf, 1, bufend - buf, f); } /**********************************************************************//** @@ -575,7 +575,7 @@ ut_copy_file( ? (size_t) len : sizeof buf; size_t size = fread(buf, 1, maxs, src); - fwrite(buf, 1, size, dest); + (void) fwrite(buf, 1, size, dest); len -= (long) size; if (size < maxs) { break; diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index f06fd4abfb1..f6d995068c1 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -2537,7 +2537,9 @@ loop: rw_lock_s_unlock(&buf_pool->page_hash_latch); } +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG loop2: +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) { mutex_exit(block_mutex); block = NULL; From 92a15782f9b4f1100cf121294237cf0f643bf734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 11 Dec 2013 09:38:21 +0200 Subject: [PATCH 109/294] MDEV-5428: Debian MariaDB-Galera packages do not get built in buildbot [Part 3] Missed one lintian rule. --- debian/dist/Debian/mariadb-galera-server-5.5.files.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index 0ffad95e533..3586278fdc6 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -40,7 +40,7 @@ usr/bin/resolveip usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN -usr/share/lintian/overrides/mariadb-server-5.5 +usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 usr/share/man/man1/myisam_ftdump.1 From ea6f92662c6ad3db3745aacb80dd162930c88cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 11 Dec 2013 10:45:49 +0200 Subject: [PATCH 110/294] MDEV-5430: Debian MariaDB-Galera packages do not get built in buildbot [Part 4] Missed one file name change. --- .../{mariadb-server-5.5.py => mariadb-galera-server-5.5.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename debian/dist/Ubuntu/{mariadb-server-5.5.py => mariadb-galera-server-5.5.py} (100%) diff --git a/debian/dist/Ubuntu/mariadb-server-5.5.py b/debian/dist/Ubuntu/mariadb-galera-server-5.5.py similarity index 100% rename from debian/dist/Ubuntu/mariadb-server-5.5.py rename to debian/dist/Ubuntu/mariadb-galera-server-5.5.py From 088c069462d4a5cf26e97690e045fc3e737453a3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 11 Dec 2013 21:09:18 +0100 Subject: [PATCH 111/294] fix debian builds --- debian/dist/Debian/control | 22 +--- .../Debian/mariadb-galera-server-5.5.files | 107 ----------------- .../Debian/mariadb-galera-server-5.5.files.in | 33 ++++++ debian/dist/Ubuntu/control | 25 +--- .../Ubuntu/mariadb-galera-server-5.5.files | 109 ------------------ .../Ubuntu/mariadb-galera-server-5.5.files.in | 33 ++++++ 6 files changed, 70 insertions(+), 259 deletions(-) delete mode 100644 debian/dist/Debian/mariadb-galera-server-5.5.files delete mode 100644 debian/dist/Ubuntu/mariadb-galera-server-5.5.files diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index cb1245830c4..cf10e8e2daf 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -42,8 +42,7 @@ Package: mariadb-galera-server Section: database Architecture: all Depends: mariadb-galera-server-5.5 (= ${source:Version}), ${misc:Depends} -Description: MariaDB database server with Galera cluster - (metapackage depending on the latest version) +Description: MariaDB database server with Galera cluster (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of mariadb-galera-server (currently mariadb-galera-server-5.5), as determined by the MariaDB maintainers. Install this package if in doubt about which MariaDB-Galera @@ -54,22 +53,3 @@ Description: MariaDB database server with Galera cluster server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. - -Package: mariadb-client -Section: database -Architecture: all -Depends: mariadb-client-5.5 (= ${source:Version}), ${misc:Depends} -Description: MariaDB database client (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB version - you want, as this is the one we consider to be in the best shape. - -Package: mariadb-test -Section: database -Architecture: all -Depends: mariadb-test-5.5 (= ${source:Version}) -Description: MariaDB database regression test suite (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB - maintainers. diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files b/debian/dist/Debian/mariadb-galera-server-5.5.files deleted file mode 100644 index fba6d8b2208..00000000000 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files +++ /dev/null @@ -1,107 +0,0 @@ -usr/sbin/mysqld -usr/lib/mysql/plugin/ha_innodb.so -usr/lib/mysql/plugin/ha_oqgraph.so -usr/lib/mysql/plugin/sphinx.so -usr/lib/mysql/plugin/auth_socket.so -usr/lib/mysql/plugin/auth_pam.so -usr/lib/mysql/plugin/semisync_master.so -usr/lib/mysql/plugin/semisync_slave.so -usr/lib/mysql/plugin/handlersocket.so -usr/lib/mysql/plugin/sql_errlog.so -usr/lib/libhsclient.so.* -etc/mysql/debian-start -etc/mysql/conf.d/mysqld_safe_syslog.cnf -usr/bin/msql2mysql -usr/bin/my_print_defaults -usr/bin/myisamchk -usr/bin/myisam_ftdump -usr/bin/myisamlog -usr/bin/myisampack -usr/bin/aria_pack -usr/bin/aria_read_log -usr/bin/aria_ftdump -usr/bin/aria_chk -usr/bin/aria_dump_log -usr/bin/mysql_convert_table_format -usr/bin/mysql_install_db -usr/bin/mysql_plugin -usr/bin/mysql_secure_installation -usr/bin/mysql_setpermission -usr/bin/mysql_tzinfo_to_sql -usr/bin/mysql_upgrade -usr/bin/mysql_zap -usr/bin/mysqlbinlog -usr/bin/mysqld_multi -usr/bin/mysqld_safe -usr/bin/mysqlhotcopy -usr/bin/perror -usr/bin/replace -usr/bin/resolve_stack_dump -usr/bin/resolveip -usr/bin/wsrep_sst_common -usr/bin/wsrep_sst_mysqldump -usr/bin/wsrep_sst_rsync -usr/bin/wsrep_sst_xtrabackup -usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-galera-server-5.5/INFO_SRC -usr/share/doc/mariadb-galera-server-5.5/INFO_BIN -usr/share/doc/mariadb-galera-server-5.5/README-wsrep -usr/share/lintian/overrides/mariadb-galera-server-5.5 -usr/share/man/man1/msql2mysql.1 -usr/share/man/man1/myisamchk.1 -usr/share/man/man1/myisam_ftdump.1 -usr/share/man/man1/myisamlog.1 -usr/share/man/man1/myisampack.1 -usr/share/man/man1/my_print_defaults.1 -usr/share/man/man1/mysqlbinlog.1 -usr/share/man/man1/mysql_convert_table_format.1 -usr/share/man/man1/mysqld_multi.1 -usr/share/man/man1/mysqld_safe.1 -usr/share/man/man1/mysqlhotcopy.1 -usr/share/man/man1/mysql_install_db.1 -usr/share/man/man1/mysql_secure_installation.1 -usr/share/man/man1/mysql_setpermission.1 -usr/share/man/man1/mysql_upgrade.1 -usr/share/man/man1/mysql_zap.1 -usr/share/man/man1/perror.1 -usr/share/man/man1/replace.1 -usr/share/man/man1/resolveip.1 -usr/share/man/man1/resolve_stack_dump.1 -usr/share/man/man1/innochecksum.1 -usr/share/man/man1/mysql_tzinfo_to_sql.1 -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian -usr/share/mysql/debian-start.inc.sh -usr/share/mysql/echo_stderr -usr/share/mysql/errmsg-utf8.txt -usr/share/mysql/fill_help_tables.sql -usr/share/mysql/mysql_system_tables_data.sql -usr/share/mysql/mysql_system_tables.sql -usr/share/mysql/mysql_performance_tables.sql -usr/share/mysql/mysql_test_data_timezone.sql -@TOKUDB_DEB_FILES@ -usr/share/mysql/wsrep.cnf -usr/share/mysql/wsrep_notify diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index 3586278fdc6..fba6d8b2208 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -37,9 +38,14 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip +usr/bin/wsrep_sst_common +usr/bin/wsrep_sst_mysqldump +usr/bin/wsrep_sst_rsync +usr/bin/wsrep_sst_xtrabackup usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/README-wsrep usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 @@ -63,6 +69,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt @@ -72,3 +103,5 @@ usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_performance_tables.sql usr/share/mysql/mysql_test_data_timezone.sql @TOKUDB_DEB_FILES@ +usr/share/mysql/wsrep.cnf +usr/share/mysql/wsrep_notify diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 5481fe77c3b..409612dccbb 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -42,10 +42,10 @@ Package: mariadb-galera-server Section: database Architecture: all Depends: mariadb-galera-server-5.5 (= ${source:Version}), ${misc:Depends} -Description: MariaDB database with Galera cluster server (metapackage depending on the latest version) +Description: MariaDB database server with Galera cluster (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-server (currently mariadb-server-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB + mariadb-galera-server (currently mariadb-galera-server-5.5), as determined by the MariaDB + maintainers. Install this package if in doubt about which MariaDB-Galera version you need. That will install the version recommended by the package maintainers. . @@ -53,22 +53,3 @@ Description: MariaDB database with Galera cluster server (metapackage depending server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. - -Package: mariadb-client -Section: database -Architecture: all -Depends: mariadb-client-5.5 (= ${source:Version}), ${misc:Depends} -Description: MariaDB database client (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB - maintainers. Install this package if in doubt about which MariaDB version - you want, as this is the one we consider to be in the best shape. - -Package: mariadb-test -Section: database -Architecture: all -Depends: mariadb-test-5.5 (= ${source:Version}) -Description: MariaDB database regression test suite (metapackage depending on the latest version) - This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB - maintainers. diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files deleted file mode 100644 index acf5acb036f..00000000000 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files +++ /dev/null @@ -1,109 +0,0 @@ -usr/sbin/mysqld -usr/lib/mysql/plugin/ha_innodb.so -usr/lib/mysql/plugin/ha_oqgraph.so -usr/lib/mysql/plugin/sphinx.so -usr/lib/mysql/plugin/auth_socket.so -usr/lib/mysql/plugin/auth_pam.so -usr/lib/mysql/plugin/semisync_master.so -usr/lib/mysql/plugin/semisync_slave.so -usr/lib/mysql/plugin/handlersocket.so -usr/lib/mysql/plugin/sql_errlog.so -usr/lib/libhsclient.so.* -etc/apparmor.d/usr.sbin.mysqld -usr/share/apport/package-hooks/source_mariadb-5.5.py -etc/mysql/debian-start -etc/mysql/conf.d/mysqld_safe_syslog.cnf -usr/bin/msql2mysql -usr/bin/my_print_defaults -usr/bin/myisamchk -usr/bin/myisam_ftdump -usr/bin/myisamlog -usr/bin/myisampack -usr/bin/aria_pack -usr/bin/aria_read_log -usr/bin/aria_ftdump -usr/bin/aria_chk -usr/bin/aria_dump_log -usr/bin/mysql_convert_table_format -usr/bin/mysql_install_db -usr/bin/mysql_plugin -usr/bin/mysql_secure_installation -usr/bin/mysql_setpermission -usr/bin/mysql_tzinfo_to_sql -usr/bin/mysql_upgrade -usr/bin/mysql_zap -usr/bin/mysqlbinlog -usr/bin/mysqld_multi -usr/bin/mysqld_safe -usr/bin/mysqlhotcopy -usr/bin/perror -usr/bin/replace -usr/bin/resolve_stack_dump -usr/bin/resolveip -usr/bin/wsrep_sst_common -usr/bin/wsrep_sst_mysqldump -usr/bin/wsrep_sst_rsync -usr/bin/wsrep_sst_xtrabackup -usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz -usr/share/doc/mariadb-galera-server-5.5/INFO_SRC -usr/share/doc/mariadb-galera-server-5.5/INFO_BIN -usr/share/doc/mariadb-galera-server-5.5/README-wsrep -usr/share/lintian/overrides/mariadb-galera-server-5.5 -usr/share/man/man1/msql2mysql.1 -usr/share/man/man1/myisamchk.1 -usr/share/man/man1/myisam_ftdump.1 -usr/share/man/man1/myisamlog.1 -usr/share/man/man1/myisampack.1 -usr/share/man/man1/my_print_defaults.1 -usr/share/man/man1/mysqlbinlog.1 -usr/share/man/man1/mysql_convert_table_format.1 -usr/share/man/man1/mysqld_multi.1 -usr/share/man/man1/mysqld_safe.1 -usr/share/man/man1/mysqlhotcopy.1 -usr/share/man/man1/mysql_install_db.1 -usr/share/man/man1/mysql_secure_installation.1 -usr/share/man/man1/mysql_setpermission.1 -usr/share/man/man1/mysql_upgrade.1 -usr/share/man/man1/mysql_zap.1 -usr/share/man/man1/perror.1 -usr/share/man/man1/replace.1 -usr/share/man/man1/resolveip.1 -usr/share/man/man1/resolve_stack_dump.1 -usr/share/man/man1/innochecksum.1 -usr/share/man/man1/mysql_tzinfo_to_sql.1 -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian -usr/share/mysql/debian-start.inc.sh -usr/share/mysql/echo_stderr -usr/share/mysql/errmsg-utf8.txt -usr/share/mysql/fill_help_tables.sql -usr/share/mysql/mysql_system_tables_data.sql -usr/share/mysql/mysql_system_tables.sql -usr/share/mysql/mysql_performance_tables.sql -usr/share/mysql/mysql_test_data_timezone.sql -@TOKUDB_DEB_FILES@ -usr/share/mysql/wsrep.cnf -usr/share/mysql/wsrep_notify diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in index 231c5d4313b..acf5acb036f 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -39,9 +40,14 @@ usr/bin/perror usr/bin/replace usr/bin/resolve_stack_dump usr/bin/resolveip +usr/bin/wsrep_sst_common +usr/bin/wsrep_sst_mysqldump +usr/bin/wsrep_sst_rsync +usr/bin/wsrep_sst_xtrabackup usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN +usr/share/doc/mariadb-galera-server-5.5/README-wsrep usr/share/lintian/overrides/mariadb-galera-server-5.5 usr/share/man/man1/msql2mysql.1 usr/share/man/man1/myisamchk.1 @@ -65,6 +71,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt @@ -74,3 +105,5 @@ usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_performance_tables.sql usr/share/mysql/mysql_test_data_timezone.sql @TOKUDB_DEB_FILES@ +usr/share/mysql/wsrep.cnf +usr/share/mysql/wsrep_notify From 31eaa90a6ef767b4f846bfe454892979200003a1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 9 Jan 2014 14:54:57 -0500 Subject: [PATCH 112/294] Merging revision 3839..3932 from codership-mysql/5.5. --- cmake/os/FreeBSD.cmake | 7 - cmake/wsrep.cmake | 2 +- mysys/default.c | 31 - scripts/mysqld_safe.sh | 40 +- scripts/wsrep_sst_xtrabackup.sh | 4 +- sql/CMakeLists.txt | 3 + sql/events.cc | 2 +- sql/handler.cc | 12 +- sql/log.cc | 154 +---- sql/log.h | 15 +- sql/log_event.cc | 57 +- sql/mdl.cc | 5 +- sql/mysqld.cc | 101 ++- sql/mysqld.h | 8 +- sql/sp.cc | 10 +- sql/sql_base.cc | 9 +- sql/sql_class.cc | 47 +- sql/sql_class.h | 15 +- sql/sql_parse.cc | 886 +++---------------------- sql/sql_trigger.cc | 4 +- sql/sys_vars.cc | 14 +- sql/transaction.cc | 3 +- sql/wsrep_applier.cc | 351 ++++++++++ sql/wsrep_applier.h | 38 ++ sql/wsrep_binlog.cc | 321 +++++++++ sql/wsrep_binlog.h | 49 ++ sql/wsrep_hton.cc | 173 +++-- sql/wsrep_mysqld.cc | 368 ++++++---- sql/wsrep_mysqld.h | 195 ++---- sql/wsrep_notify.cc | 3 +- sql/wsrep_priv.h | 210 +----- sql/wsrep_sst.cc | 68 +- sql/wsrep_sst.h | 40 ++ sql/wsrep_thd.cc | 464 +++++++++++++ sql/wsrep_thd.h | 32 + sql/wsrep_utils.cc | 87 ++- sql/wsrep_utils.h | 208 ++++++ sql/wsrep_var.cc | 34 +- sql/wsrep_var.h | 83 +++ storage/innobase/handler/ha_innodb.cc | 99 ++- storage/innobase/handler/ha_innodb.h | 2 +- storage/innobase/lock/lock0lock.c | 32 +- storage/xtradb/handler/ha_innodb.cc | 129 ++-- storage/xtradb/handler/ha_innodb.h | 5 +- storage/xtradb/include/ha_prototypes.h | 2 +- storage/xtradb/lock/lock0lock.c | 90 +-- support-files/mysql.server.sh | 29 +- wsrep/Makefile.am | 7 +- wsrep/wsrep_api.h | 739 ++++++++++++++------- wsrep/wsrep_dummy.c | 125 ++-- wsrep/wsrep_gtid.c | 74 +++ wsrep/wsrep_loader.c | 8 +- wsrep/wsrep_uuid.c | 27 +- 53 files changed, 3238 insertions(+), 2283 deletions(-) create mode 100644 sql/wsrep_applier.cc create mode 100644 sql/wsrep_applier.h create mode 100644 sql/wsrep_binlog.cc create mode 100644 sql/wsrep_binlog.h create mode 100644 sql/wsrep_sst.h create mode 100644 sql/wsrep_thd.cc create mode 100644 sql/wsrep_thd.h create mode 100644 sql/wsrep_utils.h create mode 100644 sql/wsrep_var.h create mode 100644 wsrep/wsrep_gtid.c diff --git a/cmake/os/FreeBSD.cmake b/cmake/os/FreeBSD.cmake index cc7cfa411a3..b1be01ef4d8 100644 --- a/cmake/os/FreeBSD.cmake +++ b/cmake/os/FreeBSD.cmake @@ -33,12 +33,5 @@ IF(EXECINFO) SET(LIBEXECINFO ${EXECINFO}) ENDIF() -# Use atomic builtins -IF(CMAKE_SIZEOF_VOID_P EQUAL 4 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "i386") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") - SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=i686") -ENDIF() - SET(HAVE_SYS_TIMEB_H CACHE INTERNAL "") diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index cae3a7d6ad9..91b3524c199 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -18,7 +18,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7.6") +SET(WSREP_PATCH_VERSION "9") # Obtain patch revision number: # The script tries to probe the bzr revision number using $ENV{WSREP_REV}, and diff --git a/mysys/default.c b/mysys/default.c index 8ed1a454490..ddf4b8afa3f 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -91,34 +91,6 @@ static my_bool defaults_already_read= FALSE; /* The only purpose of this global array is to hold full name of my.cnf * which seems to be otherwise unavailable */ char wsrep_defaults_file[FN_REFLEN + 10]={0,}; -/* Command-line only option to start a new wsrep service instance */ -#define WSREP_NEW_CLUSTER1 "--wsrep-new-cluster" -#define WSREP_NEW_CLUSTER2 "--wsrep_new_cluster" -/* This one is set to true when --wsrep-new-cluster is found in the command - * line arguments */ -my_bool wsrep_new_cluster= FALSE; -/* Finds and removes --wsrep-new-cluster from the arguments list. - * Returns true if found. */ -static my_bool find_wsrep_new_cluster (int* argc, char* argv[]) -{ - my_bool ret= FALSE; - int i; - - for (i= *argc - 1; i > 0; i--) - { - if (!strcmp(argv[i], WSREP_NEW_CLUSTER1) || - !strcmp(argv[i], WSREP_NEW_CLUSTER2)) - { - ret= TRUE; - *argc -= 1; - /* preserve the order of remaining arguments */ - memmove(&argv[i], &argv[i + 1], (*argc - i)*sizeof(argv[i])); - argv[*argc]= NULL; - } - } - - return ret; -} #endif /* WITH_WREP */ /* Which directories are searched for options (and in which order) */ @@ -557,9 +529,6 @@ int my_load_defaults(const char *conf_file, const char **groups, init_alloc_root(&alloc,512,0); if ((dirs= init_default_directories(&alloc)) == NULL) goto err; -#ifdef WITH_WSREP - wsrep_new_cluster= find_wsrep_new_cluster(argc, argv[0]); -#endif /* WITH_WSREP */ /* Check if the user doesn't want any default option processing --no-defaults is always the first option diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 5581a3aceea..09ac77785af 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -224,18 +224,21 @@ wsrep_pick_url() { wsrep_start_position_opt="" wsrep_recover_position() { local mysqld_cmd="$@" - local wr_logfile=$(mktemp) local euid=$(id -u) local ret=0 + local wr_logfile=$(mktemp $DATADIR/wsrep_recovery.XXXXXX) + [ "$euid" = "0" ] && chown $user $wr_logfile chmod 600 $wr_logfile - log_notice "WSREP: Running position recovery with --log_error=$wr_logfile \ - --pid-file="$DATADIR/`@HOSTNAME@`-recover.pid"" + local wr_pidfile="$DATADIR/"`@HOSTNAME@`"-recover.pid" - eval_log_error "$mysqld_cmd --log_error=$wr_logfile --wsrep-recover \ - --pid-file="$DATADIR/`@HOSTNAME@`-recover.pid"" + local wr_options="--log_error='$wr_logfile' --pid-file='$wr_pidfile'" + + log_notice "WSREP: Running position recovery with $wr_options" + + eval_log_error "$mysqld_cmd --wsrep_recover $wr_options" local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" if [ -z "$rp" ]; then @@ -926,31 +929,6 @@ then exit 1 fi -# -# Set mysqld's memory interleave policy. -# - -if @TARGET_LINUX@ && test $numa_interleave -eq 1 -then - # Locate numactl, ensure it exists. - if ! my_which numactl > /dev/null 2>&1 - then - log_error "numactl command not found, required for --numa-interleave" - exit 1 - # Attempt to run a command, ensure it works. - elif ! numactl --interleave=all true - then - log_error "numactl failed, check if numactl is properly installed" - fi - - # Launch mysqld with numactl. - cmd="$cmd numactl --interleave=all" -elif test $numa_interleave -eq 1 -then - log_error "--numa-interleave is not supported on this platform" - exit 1 -fi - for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \ "--datadir=$DATADIR" "--plugin-dir=$plugin_dir" "$USER_OPTION" do @@ -975,7 +953,7 @@ max_wsrep_restarts=0 while true do - rm -f "$pid_file" # Some extra safety + rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety start_time=`date +%M%S` diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 3eb747f50c3..75ffe3eb15f 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -24,7 +24,7 @@ # my_print_defaults to extract values from my.cnf. # # netcat for transfer. # # xbstream/tar for streaming. (and xtrabackup ofc) # -# # +# # # Currently only option in cnf is read specifically for SST # # [sst] # # streamfmt=tar|xbstream # @@ -362,8 +362,6 @@ then if [[ $ecode -ne 0 ]];then wsrep_log_error "Error while getting data from donor node: " \ "exit codes: ${RC[@]}" - wsrep_log_error "Data directory ${DATA} needs to be empty for SST:" \ - "Manual intervention required in that case" exit 32 fi done diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index e59ea142a11..2378ced6504 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -48,6 +48,9 @@ IF(WITH_WSREP) wsrep_sst.cc wsrep_utils.cc wsrep_var.cc + wsrep_binlog.cc + wsrep_applier.cc + wsrep_thd.cc ) SET(WSREP_LIB wsrep) ENDIF() diff --git a/sql/events.cc b/sql/events.cc index 78226bbf7ef..a39f31f416c 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1147,7 +1147,7 @@ end: DBUG_RETURN(ret); } #ifdef WITH_WSREP -int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len) +int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len) { String log_query; diff --git a/sql/handler.cc b/sql/handler.cc index 9cadfb2cf3f..58356116883 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1248,7 +1248,7 @@ int ha_commit_trans(THD *thd, bool all) #ifdef WITH_WSREP if (!WSREP(thd) && - thd->mdl_context.acquire_lock(&mdl_request, + thd->mdl_context.acquire_lock(&mdl_request, #else if (thd->mdl_context.acquire_lock(&mdl_request, #endif /* WITH_WSREP */ @@ -1313,8 +1313,9 @@ int ha_commit_trans(THD *thd, bool all) else { /* not wsrep hton, bail to native mysql behavior */ -#endif +#endif /* WITH_WSREP */ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); + error= 1; #ifdef WITH_WSREP } /* End of else */ #endif @@ -1426,7 +1427,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) #ifdef WSREP_PROC_INFO char info[64]= { 0, }; snprintf (info, sizeof(info) - 1, "ha_commit_one_phase(%lld)", - (long long)thd->wsrep_trx_seqno); + (long long)wsrep_thd_trx_seqno(thd)); #else const char info[]="ha_commit_one_phase()"; #endif /* WSREP_PROC_INFO */ @@ -1462,7 +1463,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) } /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) - thd->transaction.cleanup(); + thd->transaction.cleanup(); #ifdef WITH_WSREP if (WSREP(thd)) thd_proc_info(thd, tmp_info); #endif /* WITH_WSREP */ @@ -1546,8 +1547,7 @@ int ha_rollback_trans(THD *thd, bool all) /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) - thd->transaction.cleanup(); - + thd->transaction.cleanup(); if (all) thd->transaction_rollback_request= FALSE; diff --git a/sql/log.cc b/sql/log.cc index 242c45a7ed7..7f6cff3cc59 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -490,24 +490,10 @@ private: }; handlerton *binlog_hton; -#ifdef WITH_WSREP -extern handlerton *wsrep_hton; -#endif -bool LOGGER::is_log_table_enabled(uint log_table_type) -{ - switch (log_table_type) { - case QUERY_LOG_SLOW: - return (table_log_handler != NULL) && opt_slow_log; - case QUERY_LOG_GENERAL: - return (table_log_handler != NULL) && opt_log ; - default: - DBUG_ASSERT(0); - return FALSE; /* make compiler happy */ - } -} - -#ifdef WITH_WSREP +#if WITH_WSREP +/* the functions below depend on the definition of binlog_cache_manager class, + * so have to stay in this unit. */ IO_CACHE * get_trans_log(THD * thd) { binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*) @@ -515,7 +501,7 @@ IO_CACHE * get_trans_log(THD * thd) if (cache_mngr) { return cache_mngr->get_binlog_cache_log(true); - } + } else { WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id); @@ -523,7 +509,6 @@ IO_CACHE * get_trans_log(THD * thd) } } - bool wsrep_trans_cache_is_empty(THD *thd) { binlog_cache_mngr *const cache_mngr= @@ -535,6 +520,7 @@ void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end) { thd->binlog_flush_pending_rows_event(stmt_end); } + void thd_binlog_trx_reset(THD * thd) { /* @@ -556,74 +542,21 @@ void thd_binlog_rollback_stmt(THD * thd) (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); } -/* - Write the contents of a cache to memory buffer. +#endif /* WITH_WSREP */ - 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(IO_CACHE *cache, uchar **buf, uint *buf_len) +bool LOGGER::is_log_table_enabled(uint log_table_type) { - - if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) - return ER_ERROR_ON_WRITE; - uint length= my_b_bytes_in_cache(cache); - long long total_length = 0; - uchar *buf_ptr = NULL; - - do - { - /* bail out if buffer grows too large - This is a temporary fix to avoid flooding replication - TODO: remove this check for 0.7.4 release - */ - if (total_length > wsrep_max_ws_size) - { - WSREP_WARN("transaction size limit (%lld) exceeded: %lld", - wsrep_max_ws_size, total_length); - if (reinit_io_cache(cache, WRITE_CACHE, 0, 0, 0)) - { - WSREP_WARN("failed to initialize io-cache"); - } - if (buf_ptr) my_free(*buf); - *buf_len = 0; - return ER_ERROR_ON_WRITE; - } - if (total_length > 0) - { - *buf_len += length; - *buf = (uchar *)my_realloc(*buf, total_length+length, MYF(0)); - if (!*buf) - { - WSREP_ERROR("io cache write problem: %d %d", *buf_len, length); - return ER_ERROR_ON_WRITE; - } - buf_ptr = *buf+total_length; - } - else - { - if (buf_ptr != NULL) - { - WSREP_ERROR("io cache alloc error: %d %d", *buf_len, length); - my_free(*buf); - } - if (length > 0) - { - *buf = (uchar *) my_malloc(length, MYF(0)); - buf_ptr = *buf; - *buf_len = length; - } - } - total_length += length; - - memcpy(buf_ptr, cache->read_pos, length); - cache->read_pos=cache->read_end; - } while ((cache->file >= 0) && (length= my_b_fill(cache))); - - return 0; + switch (log_table_type) { + case QUERY_LOG_SLOW: + return (table_log_handler != NULL) && opt_slow_log; + case QUERY_LOG_GENERAL: + return (table_log_handler != NULL) && opt_log ; + default: + DBUG_ASSERT(0); + return FALSE; /* make compiler happy */ + } } -#endif + /* Check if a given table is opened log table */ int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, @@ -1817,13 +1750,6 @@ static inline int binlog_commit_flush_stmt_cache(THD *thd, bool all, binlog_cache_mngr *cache_mngr) { -#ifdef WITH_WSREP - if (thd->wsrep_mysql_replicated > 0) - { - WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated); - return 0; - } -#endif Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"), FALSE, TRUE, TRUE, 0); return (binlog_flush_cache(thd, cache_mngr, &end_evt, all, TRUE, FALSE)); @@ -1841,6 +1767,13 @@ binlog_commit_flush_stmt_cache(THD *thd, bool all, static inline int binlog_commit_flush_trx_cache(THD *thd, bool all, binlog_cache_mngr *cache_mngr) { +#ifdef WITH_WSREP + if (thd->wsrep_mysql_replicated > 0) + { + WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated); + return 0; + } +#endif Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, TRUE, 0); return (binlog_flush_cache(thd, cache_mngr, &end_evt, all, FALSE, TRUE)); @@ -2104,12 +2037,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) if (ending_trans(thd, all) && ((thd->variables.option_bits & OPTION_KEEP_LOG) || (trans_has_updated_non_trans_table(thd) && - WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT) || + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT) || (cache_mngr->trx_cache.changes_to_non_trans_temp_table() && - WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) || + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) || (trans_has_updated_non_trans_table(thd) && ending_single_stmt_trans(thd,all) && - WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED))) + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED))) error= binlog_rollback_flush_trx_cache(thd, all, cache_mngr); /* Truncate the cache if: @@ -2123,9 +2056,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) else if (ending_trans(thd, all) || (!(thd->variables.option_bits & OPTION_KEEP_LOG) && (!stmt_has_updated_non_trans_table(thd) || - WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_STMT) && + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_STMT) && (!cache_mngr->trx_cache.changes_to_non_trans_temp_table() || - WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_MIXED))) + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_MIXED))) error= binlog_truncate_trx_cache(thd, cache_mngr, all); } @@ -5439,35 +5372,6 @@ err: } } -#ifdef WITH_WSREP - if (WSREP(thd) && wsrep_incremental_data_collection && - (wsrep_emulate_bin_log || mysql_bin_log.is_open())) - { - DBUG_ASSERT(thd->wsrep_trx_handle.trx_id != (unsigned long)-1); - if (!error) - { - IO_CACHE* cache= get_trans_log(thd); - uchar* buf= NULL; - uint buf_len= 0; - - if (wsrep_emulate_bin_log) - thd->binlog_flush_pending_rows_event(false); - error= wsrep_write_cache(cache, &buf, &buf_len); - if (!error && buf_len > 0) - { - wsrep_status_t rc= wsrep->append_data(wsrep, - &thd->wsrep_trx_handle, - buf, buf_len); - if (rc != WSREP_OK) - { - sql_print_warning("WSREP: append_data() returned %d", rc); - error= 1; - } - } - if (buf_len) my_free(buf); - } - } -#endif /* WITH_WSREP */ DBUG_RETURN(error); } diff --git a/sql/log.h b/sql/log.h index 0e189a789db..34b9df53c93 100644 --- a/sql/log.h +++ b/sql/log.h @@ -273,12 +273,6 @@ enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; (mmap+fsync is two times faster than write+fsync) */ -#ifdef WITH_WSREP -extern my_bool wsrep_emulate_bin_log; -Log_event* wsrep_read_log_event( - char **arg_buf, size_t *arg_buf_len, - const Format_description_log_event *description_event); -#endif class MYSQL_LOG { public: @@ -870,18 +864,17 @@ enum enum_binlog_format { }; #ifdef WITH_WSREP -IO_CACHE * get_trans_log(THD * thd); +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_trx_reset(THD * thd); void thd_binlog_rollback_stmt(THD * thd); -int wsrep_write_cache(IO_CACHE *cache, uchar **buf, uint *buf_len); -#define WSREP_FORMAT(my_format) \ - ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ +#define WSREP_BINLOG_FORMAT(my_format) \ + ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ wsrep_forced_binlog_format : my_format) #else -#define WSREP_FORMAT(my_format) my_format +#define WSREP_BINLOG_FORMAT(my_format) my_format #endif int query_error_code(THD *thd, bool not_killed); uint purge_log_get_error_code(int res); diff --git a/sql/log_event.cc b/sql/log_event.cc index b4f5f5ad8b2..dac39a63282 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8406,7 +8406,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) thd->is_fatal_error, thd->wsrep_exec_mode, thd->wsrep_conflict_state, - (long long)thd->wsrep_trx_seqno); + (long long)wsrep_thd_trx_seqno(thd)); } #endif if (thd->is_slave_error || thd->is_fatal_error) @@ -10187,7 +10187,7 @@ Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "Write_rows_log_event::write_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; #else const char* tmp = (WSREP(thd)) ? @@ -10864,7 +10864,7 @@ int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "Delete_rows_log_event::find_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; #else const char* tmp = (WSREP(thd)) ? @@ -10880,7 +10880,7 @@ int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) #ifdef WSREP_PROC_INFO snprintf(info, sizeof(info) - 1, "Delete_rows_log_event::ha_delete_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); if (WSREP(thd)) thd_proc_info(thd, info); #else if (WSREP(thd)) thd_proc_info(thd,"Delete_rows_log_event::ha_delete_row()"); @@ -11016,7 +11016,7 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "Update_rows_log_event::find_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; #else const char* tmp = (WSREP(thd)) ? @@ -11053,7 +11053,7 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) #ifdef WSREP_PROC_INFO snprintf(info, sizeof(info) - 1, "Update_rows_log_event::unpack_current_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); if (WSREP(thd)) thd_proc_info(thd, info); #else if (WSREP(thd)) @@ -11082,7 +11082,7 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) #ifdef WSREP_PROC_INFO snprintf(info, sizeof(info) - 1, "Update_rows_log_event::ha_update_row(%lld)", - (long long) thd->wsrep_trx_seqno); + (long long) wsrep_thd_trx_seqno(thd)); if (WSREP(thd)) thd_proc_info(thd, info); #else if (WSREP(thd)) thd_proc_info(thd,"Update_rows_log_event::ha_update_row()"); @@ -11179,48 +11179,6 @@ void Incident_log_event::pack_info(THD *thd, Protocol *protocol) protocol->store(buf, bytes, &my_charset_bin); } #endif -#if WITH_WSREP && !defined(MYSQL_CLIENT) -Format_description_log_event *wsrep_format_desc; // TODO: free them at the end -/* - read the first event from (*buf). The size of the (*buf) is (*buf_len). - 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. -*/ -#define WSREP_MAX_ALLOWED_PACKET 1024*1024*1024 // current protocol max - -Log_event* wsrep_read_log_event( - char **arg_buf, size_t *arg_buf_len, - const Format_description_log_event *description_event) -{ - DBUG_ENTER("wsrep_read_log_event"); - char *head= (*arg_buf); - - uint data_len = uint4korr(head + EVENT_LEN_OFFSET); - char *buf= (*arg_buf); - const char *error= 0; - Log_event *res= 0; - - if (data_len > WSREP_MAX_ALLOWED_PACKET) - { - error = "Event too big"; - goto err; - } - - res= Log_event::read_log_event(buf, data_len, &error, description_event, FALSE); - -err: - if (!res) - { - DBUG_ASSERT(error != 0); - sql_print_error("Error in Log_event::read_log_event(): " - "'%s', data_len: %d, event_type: %d", - error,data_len,head[EVENT_TYPE_OFFSET]); - } - (*arg_buf)+= data_len; - (*arg_buf_len)-= data_len; - DBUG_RETURN(res); -} -#endif #ifdef MYSQL_CLIENT @@ -11310,6 +11268,7 @@ st_print_event_info::st_print_event_info() } #endif + #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) diff --git a/sql/mdl.cc b/sql/mdl.cc index fe8efd3e6cd..268a6621f65 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -22,6 +22,7 @@ #include #ifdef WITH_WSREP #include "wsrep_mysqld.h" +#include "wsrep_thd.h" extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); extern "C" char *wsrep_thd_query(THD *thd); void sql_print_information(const char *format, ...) @@ -3029,7 +3030,7 @@ void MDL_ticket::wsrep_report(bool debug) { if (debug) { - WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)", + WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s", (get_type() == MDL_INTENTION_EXCLUSIVE) ? "intention exclusive" : ((get_type() == MDL_SHARED) ? "shared" : ((get_type() == MDL_SHARED_HIGH_PRIO ? "shared high prio" : @@ -3049,7 +3050,7 @@ void MDL_ticket::wsrep_report(bool debug) ((m_lock->key.mdl_namespace() == MDL_key::COMMIT) ? "COMMIT" : (char *)"UNKNOWN"))))))), m_lock->key.db_name(), - m_lock->key.name(), + m_lock->key.name(), m_lock->key.get_wait_state_name()); } } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 849ceb1db39..953b59031d8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -74,6 +74,9 @@ #include "debug_sync.h" #ifdef WITH_WSREP #include "wsrep_mysqld.h" +#include "wsrep_var.h" +#include "wsrep_thd.h" +#include "wsrep_sst.h" ulong wsrep_running_threads = 0; // # of currently running wsrep threads #endif #include "sql_callback.h" @@ -354,7 +357,11 @@ static char *default_character_set_name; static char *character_set_filesystem_name; static char *lc_messages; static char *lc_time_names_name; +#ifndef WITH_WSREP static char *my_bind_addr_str; +#else +char *my_bind_addr_str; +#endif /* WITH_WSREP */ static char *default_collation_name; char *default_storage_engine; static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; @@ -716,7 +723,7 @@ mysql_mutex_t LOCK_wsrep_slave_threads; mysql_mutex_t LOCK_wsrep_desync; int wsrep_replaying= 0; static void wsrep_close_threads(THD* thd); -#endif +#endif /* WITH_WSREP */ int mysqld_server_started= 0; File_parser_dummy_hook file_parser_dummy_hook; @@ -1863,6 +1870,7 @@ extern "C" void unireg_abort(int exit_code) WSREP_INFO("Some threads may fail to exit."); } #endif // WITH_WSREP + clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); mysqld_exit(exit_code); @@ -2389,7 +2397,7 @@ static my_socket activate_tcp_port(uint port) socket_errno); unireg_abort(1); } -#if defined(WITH_WSREP) && defined(HAVE_FCNTL) +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) (void) fcntl(ip_sock, F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ DBUG_RETURN(ip_sock); @@ -2513,7 +2521,7 @@ static void network_init(void) if (listen(unix_sock,(int) back_log) < 0) sql_print_warning("listen() on Unix socket failed with error %d", socket_errno); -#if defined(WITH_WSREP) && defined(HAVE_FCNTL) +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) (void) fcntl(unix_sock, F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ } @@ -4141,25 +4149,25 @@ static int init_thread_environment() return 1; } #ifdef WITH_WSREP - mysql_mutex_init(key_LOCK_wsrep_ready, - &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_ready, + &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_ready, &COND_wsrep_ready, NULL); - mysql_mutex_init(key_LOCK_wsrep_sst, - &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_sst, + &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST); 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_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_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_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_slave_threads, + &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_desync, + &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST); #endif return 0; } @@ -4789,7 +4797,7 @@ pthread_handler_t start_wsrep_THD(void *arg) THD *thd; wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; - if (my_thread_init()) + if (my_thread_init()) { WSREP_ERROR("Could not initialize thread"); return(NULL); @@ -4852,7 +4860,7 @@ pthread_handler_t start_wsrep_THD(void *arg) statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); delete thd; - + return(NULL); } @@ -4910,42 +4918,6 @@ pthread_handler_t start_wsrep_THD(void *arg) return(NULL); } -void wsrep_create_rollbacker() -{ - if (WSREP_PROVIDER_EXISTS) - { - pthread_t hThread; - /* create rollbacker */ - if (pthread_create( &hThread, &connection_attrib, - start_wsrep_THD, (void*)wsrep_rollback_process)) - WSREP_WARN("Can't create thread to manage wsrep rollback"); - } -} - -void wsrep_create_appliers(long threads) -{ - if (!wsrep_connected) - { - /* see wsrep_replication_start() for the logic */ - if (wsrep_cluster_address && strlen(wsrep_cluster_address) && - WSREP_PROVIDER_EXISTS) - { - WSREP_ERROR("Trying to launch slave threads before creating " - "connection at '%s'", wsrep_cluster_address); - assert(0); - } - return; - } - - long wsrep_threads=0; - pthread_t hThread; - while (wsrep_threads++ < threads) { - if (pthread_create( - &hThread, &connection_attrib, - start_wsrep_THD, (void*)wsrep_replication_process)) - WSREP_WARN("Can't create thread to manage wsrep replication"); - } -} /**/ static bool abort_replicated(THD *thd) { @@ -4970,7 +4942,7 @@ WSREP_WARN("applier has wsrep_exec_mode = %d", thd->wsrep_exec_mode); if ( thd->slave_thread || /* declared as mysql slave */ thd->system_thread || /* declared as system thread */ - !thd->vio_ok() || /* server internal thread */ + !thd->vio_ok() || /* server internal thread */ thd->wsrep_exec_mode==REPL_RECV || /* applier or replaying thread */ thd->wsrep_applier || /* wsrep slave applier */ !thd->variables.wsrep_on) /* client, but fenced outside wsrep */ @@ -5452,6 +5424,9 @@ int mysqld_main(int argc, char **argv) return 1; } #endif +#ifdef WITH_WSREP + wsrep_filter_new_cluster (&argc, argv); +#endif /* WITH_WSREP */ orig_argc= argc; orig_argv= argv; @@ -5755,6 +5730,13 @@ int mysqld_main(int argc, char **argv) unireg_abort(1); #ifdef WITH_WSREP /* WSREP AFTER SE */ + if (wsrep_recovery) + { + select_thread_in_use= 0; + wsrep_recover(); + unireg_abort(0); + } + if (opt_bootstrap) { /*! bootstrap wsrep init was taken care of above */ @@ -6484,7 +6466,7 @@ void handle_connections_sockets() sleep(1); // Give other threads some time continue; } -#if defined(WITH_WSREP) && defined(HAVE_FCNTL) +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) (void) fcntl(new_sock, F_SETFD, FD_CLOEXEC); #endif /* WITH_WSREP */ @@ -7984,6 +7966,7 @@ SHOW_VAR status_vars[]= { {"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}, @@ -9220,6 +9203,9 @@ void refresh_status(THD *thd) /* Reset some global variables */ reset_status_vars(); +#ifdef WITH_WSREP + wsrep->stats_reset(wsrep); +#endif /* WITH_WSREP */ /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters, 0); @@ -9256,3 +9242,4 @@ template class I_List; template class I_List; template class I_List_iterator; #endif + diff --git a/sql/mysqld.h b/sql/mysqld.h index 0075c81726c..f392452f56e 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -227,7 +227,7 @@ extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, #ifdef WITH_WSREP extern PSI_mutex_key key_LOCK_wsrep_thd; extern PSI_cond_key key_COND_wsrep_thd; -#endif /* HAVE_MMAP */ +#endif /* HAVE_WSREP */ #ifdef HAVE_OPENSSL extern PSI_mutex_key key_LOCK_des_key_file; @@ -423,7 +423,7 @@ enum options_mysqld OPT_WSREP_START_POSITION, OPT_WSREP_SST_AUTH, OPT_WSREP_RECOVER, -#endif +#endif /* WITH_WSREP */ OPT_which_is_always_the_last }; #endif @@ -572,5 +572,9 @@ extern uint internal_tmp_table_max_key_segments; extern uint volatile global_disable_checkpoint; extern my_bool opt_help; +#ifdef WITH_WSREP +#include "my_pthread.h" +pthread_handler_t start_wsrep_THD(void*); +#endif /* WITH_WSREP */ #endif /* MYSQLD_INCLUDED */ diff --git a/sql/sp.cc b/sql/sp.cc index 269917d6863..c379dbd7fbf 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2289,7 +2289,7 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, return sp; } #ifdef WITH_WSREP -int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len) +int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) { String log_query; sp_head *sp = thd->lex->sphead; @@ -2315,10 +2315,10 @@ int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len) sp->m_chistics, &(thd->lex->definer->user), &(thd->lex->definer->host), saved_mode)) - { - WSREP_WARN("SP create string failed: %s", thd->query()); - return 1; - } + { + WSREP_WARN("SP create string failed: %s", thd->query()); + return 1; + } return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); } #endif /* WITH_WSREP */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3acfa63d55e..5eb6607fb4d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -59,9 +59,9 @@ #ifdef __WIN__ #include #endif - #ifdef WITH_WSREP #include "wsrep_mysqld.h" +#include "wsrep_thd.h" #endif // WITH_WSREP bool @@ -4227,7 +4227,7 @@ thr_lock_type read_lock_type_for_table(THD *thd, */ bool log_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; ulong binlog_format= thd->variables.binlog_format; - if ((log_on == FALSE) || (WSREP_FORMAT(binlog_format) == BINLOG_FORMAT_ROW) || + if ((log_on == FALSE) || (WSREP_BINLOG_FORMAT(binlog_format) == BINLOG_FORMAT_ROW) || (table_list->table->s->table_category == TABLE_CATEGORY_LOG) || (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || !(is_update_query(prelocking_ctx->sql_command) || @@ -5894,7 +5894,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, We can solve these problems in mixed mode by switching to binlogging if at least one updated table is used by sub-statement */ - if (WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables && + if (WSREP_BINLOG_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); } @@ -9431,6 +9431,7 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, { mysql_mutex_assert_owner(&LOCK_open); } + #ifdef WITH_WSREP /* if thd was BF aborted, exclusive locks were canceled */ #else @@ -9438,6 +9439,7 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, MDL_EXCLUSIVE)); #endif /* WITH_WSREP */ + key_length= create_table_def_key(key, db, table_name); if ((share= (TABLE_SHARE*) my_hash_search(&table_def_cache,(uchar*) key, @@ -9461,7 +9463,6 @@ void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, thus others can use table */ if (table->in_use != thd && - table->in_use->wsrep_bf_thd != thd && table->in_use->wsrep_conflict_state != MUST_ABORT) { #endif diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2b9595a5080..334d6c5a619 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -848,9 +848,9 @@ extern "C" const char *wsrep_thd_conflict_state_str(THD *thd) (thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void"; } -extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd) +extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd) { - return &thd->wsrep_trx_handle; + return &thd->wsrep_ws_handle; } extern "C"void wsrep_thd_LOCK(THD *thd) @@ -875,7 +875,7 @@ extern "C" my_thread_id wsrep_thd_thread_id(THD *thd) } extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd) { - return (thd) ? thd->wsrep_trx_seqno : WSREP_SEQNO_UNDEFINED; + return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED; } extern "C" query_id_t wsrep_thd_query_id(THD *thd) { @@ -913,16 +913,16 @@ extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal) extern "C" int wsrep_trx_order_before(void *thd1, void *thd2) { - if (((THD*)thd1)->wsrep_trx_seqno < ((THD*)thd2)->wsrep_trx_seqno) { - WSREP_DEBUG("BF conflict, order: %lld %lld\n", - (long long)((THD*)thd1)->wsrep_trx_seqno, - (long long)((THD*)thd2)->wsrep_trx_seqno); - return 1; - } - WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", - (long long)((THD*)thd1)->wsrep_trx_seqno, - (long long)((THD*)thd2)->wsrep_trx_seqno); - return 0; + if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) { + WSREP_DEBUG("BF conflict, order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno((THD*)thd1), + (long long)wsrep_thd_trx_seqno((THD*)thd2)); + return 1; + } + WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno((THD*)thd1), + (long long)wsrep_thd_trx_seqno((THD*)thd2)); + return 0; } extern "C" int wsrep_trx_is_aborting(void *thd_ptr) @@ -1000,7 +1000,7 @@ THD::THD() wsrep_applier(is_applier), wsrep_applier_closing(FALSE), wsrep_client_thread(0), - wsrep_trx_seqno(WSREP_SEQNO_UNDEFINED), + wsrep_apply_toi(false), #endif m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) @@ -1104,9 +1104,8 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); - wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; - wsrep_trx_handle.opaque = NULL; - //wsrep_retry_autocommit= ::wsrep_retry_autocommit; + 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; @@ -1471,7 +1470,10 @@ void THD::init(void) 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_converted_lock_session= false; + //wsrep_retry_autocommit= ::wsrep_retry_autocommit; wsrep_retry_counter= 0; wsrep_rli= NULL; wsrep_PA_safe= true; @@ -2116,6 +2118,7 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= FALSE; + /* reset replication info structure */ #ifndef EMBEDDED_LIBRARY if (rli_slave) @@ -4279,7 +4282,7 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd) #else if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) #endif - return (int) WSREP_FORMAT(thd->variables.binlog_format); + return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format); else return BINLOG_FORMAT_UNSPEC; } @@ -4839,7 +4842,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && - !(WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT && + !(WSREP_BINLOG_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db))) { /* @@ -5003,7 +5006,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) */ my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0)); } - else if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW && + else if (WSREP_BINLOG_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW && sqlcom_can_generate_row_events(this)) { /* @@ -5032,7 +5035,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) else { /* binlog_format = STATEMENT */ - if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT) + if (WSREP_BINLOG_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT) { if (lex->is_stmt_row_injection()) { @@ -5144,7 +5147,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) "and binlog_filter->db_ok(db) = %d", mysql_bin_log.is_open(), (variables.option_bits & OPTION_BIN_LOG), - WSREP_FORMAT(variables.binlog_format), + WSREP_BINLOG_FORMAT(variables.binlog_format), binlog_filter->db_ok(db))); #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index f35e8914c42..d10769d10a8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -49,6 +49,7 @@ #include "wsrep_mysqld.h" struct wsrep_thd_shadow { ulonglong options; + uint server_status; enum wsrep_exec_mode wsrep_exec_mode; Vio *vio; ulong tx_isolation; @@ -1807,7 +1808,8 @@ public: int is_current_stmt_binlog_format_row() const { DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || current_stmt_binlog_format == BINLOG_FORMAT_ROW); - return (WSREP_FORMAT((ulong)current_stmt_binlog_format) == BINLOG_FORMAT_ROW); + return (WSREP_BINLOG_FORMAT((ulong)current_stmt_binlog_format) == + BINLOG_FORMAT_ROW); } private: @@ -2353,11 +2355,13 @@ public: enum wsrep_conflict_state wsrep_conflict_state; mysql_mutex_t LOCK_wsrep_thd; mysql_cond_t COND_wsrep_thd; - wsrep_seqno_t wsrep_trx_seqno; + // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 + // wsrep_seqno_t wsrep_trx_seqno; + wsrep_trx_meta_t wsrep_trx_meta; uint32 wsrep_rand; Relay_log_info* wsrep_rli; bool wsrep_converted_lock_session; - wsrep_trx_handle_t wsrep_trx_handle; + wsrep_ws_handle_t wsrep_ws_handle; #ifdef WSREP_PROC_INFO char wsrep_info[128]; /* string for dynamic proc info */ #endif /* WSREP_PROC_INFO */ @@ -2374,6 +2378,7 @@ public: const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; + bool wsrep_apply_toi; /* applier processing in TOI */ #endif /* WITH_WSREP */ /** Internal parser state. @@ -2819,7 +2824,7 @@ public: tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ - if ((WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_MIXED) && + if ((WSREP_BINLOG_FORMAT(variables.binlog_format) == BINLOG_FORMAT_MIXED)&& (in_sub_stmt == 0)) set_current_stmt_binlog_format_row(); @@ -2861,7 +2866,7 @@ public: show_system_thread(system_thread))); if (in_sub_stmt == 0) { - if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW) + if (WSREP_BINLOG_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW) set_current_stmt_binlog_format_row(); else if (temporary_tables == NULL) clear_current_stmt_binlog_format_row(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e8e5d79b370..d497b6d1263 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -104,13 +104,9 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" -#include "rpl_rli.h" -static void wsrep_client_rollback(THD *thd); - -extern Format_description_log_event *wsrep_format_desc; - +#include "wsrep_thd.h" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state); + Parser_state *parser_state); #endif /* WITH_WSREP */ /** @defgroup Runtime_Environment Runtime Environment @@ -445,13 +441,6 @@ bool is_log_table_write_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0; } -#ifdef WITH_WSREP -bool is_show_query(enum enum_sql_command command) -{ - DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); - return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0; -} -#endif void execute_init_command(THD *thd, LEX_STRING *init_command, mysql_rwlock_t *var_lock) { @@ -637,7 +626,7 @@ void do_handle_bootstrap(THD *thd) close_connection(thd, ER_OUT_OF_RESOURCES, 1); #else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif +#endif /* WITH_WSREP */ #endif thd->fatal_error(); goto end; @@ -717,13 +706,13 @@ bool do_command(THD *thd) { mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_query_state= QUERY_IDLE; - if (thd->wsrep_conflict_state==MUST_ABORT) + if (thd->wsrep_conflict_state==MUST_ABORT) { wsrep_client_rollback(thd); } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } -#endif +#endif /* WITH_WSREP */ /* indicator of uninitialized lex => normal flow of errors handling (see my_message_sql) @@ -776,12 +765,12 @@ bool do_command(THD *thd) if (thd->wsrep_conflict_state == ABORTING) { while (thd->wsrep_conflict_state == ABORTING) { - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - my_sleep(1000); - mysql_mutex_lock(&thd->LOCK_wsrep_thd); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + my_sleep(1000); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); } thd->store_globals(); - } + } else if (thd->wsrep_conflict_state == ABORTED) { thd->store_globals(); @@ -795,7 +784,7 @@ bool do_command(THD *thd) (!WSREP(thd) && (packet_length= my_net_read(net)) == packet_error)) #else if ((packet_length= my_net_read(net)) == packet_error) -#endif +#endif /* WITH_WSREP */ { DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, @@ -805,12 +794,12 @@ bool do_command(THD *thd) mysql_mutex_lock(&thd->LOCK_wsrep_thd); if (thd->wsrep_conflict_state == MUST_ABORT) { - DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id)); - wsrep_client_rollback(thd); + DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id)); + wsrep_client_rollback(thd); } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } -#endif +#endif /* WITH_WSREP */ /* Check if we can continue without closing the connection */ @@ -858,11 +847,11 @@ bool do_command(THD *thd) #ifdef WITH_WSREP if (WSREP(thd)) { - /* + /* * 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->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && + if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && command != COM_QUERY && command != COM_PING && command != COM_QUIT && @@ -875,14 +864,14 @@ bool do_command(THD *thd) command != COM_TIME && command != COM_END ) { - my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), "WSREP has not yet prepared node for application use"); thd->protocol->end_statement(); return_value= FALSE; goto out; } } -#endif +#endif /* WITH_WSREP */ /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); @@ -892,17 +881,17 @@ bool do_command(THD *thd) if (WSREP(thd)) { while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) { - 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); - } - return_value= dispatch_command(command, thd, thd->wsrep_retry_query, - thd->wsrep_retry_query_len); - thd->variables.character_set_client = current_charset; + 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); + } + return_value= dispatch_command(command, thd, thd->wsrep_retry_query, + thd->wsrep_retry_query_len); + thd->variables.character_set_client = current_charset; } } if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING) @@ -912,7 +901,7 @@ bool do_command(THD *thd) thd->wsrep_retry_query_len = 0; thd->wsrep_retry_command = COM_CONNECT; } -#endif +#endif /* WITH_WSREP */ out: DBUG_RETURN(return_value); } @@ -1059,7 +1048,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { wsrep_client_rollback(thd); } - if (thd->wsrep_conflict_state== ABORTED) + if (thd->wsrep_conflict_state== ABORTED) { my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); WSREP_DEBUG("Deadlock error for: %s", thd->query()); @@ -1264,7 +1253,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); #else mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); -#endif +#endif /* WITH_WSREP */ while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) @@ -1325,14 +1314,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->set_time(); /* Reset the query start time. */ #else thd->set_time(); /* Reset the query start time. */ -#endif +#endif /* WITH_WSREP */ parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ #ifdef WITH_WSREP wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); #else mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); -#endif +#endif /* WITH_WSREP */ } DBUG_PRINT("info",("query ready")); @@ -1666,14 +1655,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_wsrep_thd); if ((thd->wsrep_conflict_state != REPLAYING) && - (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) - { + (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + thd->update_server_status(); thd->protocol->end_statement(); query_cache_end_of_result(thd); + } + else + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - } else { /* if (WSREP(thd))... */ #endif /* WITH_WSREP */ DBUG_ASSERT(thd->derived_tables == NULL && @@ -2146,6 +2138,13 @@ err: return TRUE; } +#ifdef WITH_WSREP +static 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; +} +#endif /* WITH_WSREP */ /** Execute command saved in thd and lex->sql_command. @@ -2381,7 +2380,7 @@ mysql_execute_command(THD *thd) } } } - if (lex->sql_command== SQLCOM_UNLOCK_TABLES && + if (lex->sql_command== SQLCOM_UNLOCK_TABLES && thd->wsrep_converted_lock_session) { thd->wsrep_converted_lock_session= false; @@ -2389,13 +2388,13 @@ mysql_execute_command(THD *thd) lex->tx_release= TVL_NO; } - /* + /* * bail out if DB snapshot has not been installed. We however, * allow SET and SHOW queries */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && - !is_show_query(lex->sql_command)) + !wsrep_is_show_query(lex->sql_command)) { #if DIRTY_HACK /* Dirty hack for lp:1002714 - trying to recognize mysqldump connection @@ -2410,7 +2409,7 @@ mysql_execute_command(THD *thd) strncmp(thd->query(), mysqldump_magic_str, mysqldump_magic_str_len)) { #endif /* DIRTY_HACK */ - my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), "WSREP has not yet prepared node for application use"); goto error; #if DIRTY_HACK @@ -2449,7 +2448,9 @@ mysql_execute_command(THD *thd) if (trans_commit_implicit(thd)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } /* Release metadata locks acquired in this transaction. */ @@ -2480,7 +2481,13 @@ mysql_execute_command(THD *thd) break; case SQLCOM_SHOW_STATUS: { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ execute_show_status(thd, all_tables); +#ifdef WITH_WSREP + if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); +#endif /* WITH_WSREP */ break; } case SQLCOM_SHOW_DATABASES: @@ -2511,7 +2518,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_PROFILE: #endif /* WITH_WSREP */ - { + { thd->status_var.last_query_cost= 0.0; /* @@ -2821,7 +2828,7 @@ case SQLCOM_PREPARE: */ if (thd->query_name_consts && mysql_bin_log.is_open() && - WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT && + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT && !mysql_bin_log.is_query_in_union(thd, thd->query_id)) { List_iterator_fast it(select_lex->item_list); @@ -3503,7 +3510,7 @@ end_with_restore_list: #ifdef WITH_WSREP for (TABLE_LIST *table= all_tables; table; table= table->next_global) { - if (!lex->drop_temporary && + if (!lex->drop_temporary && (!thd->is_current_stmt_binlog_format_row() || !find_temporary_table(thd, table))) { @@ -4169,7 +4176,7 @@ end_with_restore_list: lex->insert_list, lex->ha_rkey_mode, select_lex->where, unit->select_limit_cnt, unit->offset_limit_cnt); #ifdef WITH_WSREP - if (WSREP(thd)) thd_proc_info(thd, tmp_info); + if (WSREP(thd)) thd_proc_info(thd, tmp_info); } #endif /* WITH_WSREP */ break; @@ -4178,7 +4185,9 @@ end_with_restore_list: if (trans_begin(thd, lex->start_transaction_opt)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } my_ok(thd); @@ -4196,7 +4205,9 @@ end_with_restore_list: if (trans_commit(thd)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } thd->mdl_context.release_transactional_locks(); @@ -4217,7 +4228,20 @@ end_with_restore_list: thd->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 */ break; } case SQLCOM_ROLLBACK: @@ -4233,7 +4257,9 @@ end_with_restore_list: if (trans_rollback(thd)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } thd->mdl_context.release_transactional_locks(); @@ -4251,20 +4277,18 @@ end_with_restore_list: /* Disconnect the current client connection. */ if (tx_release) thd->killed= KILL_CONNECTION; - #ifdef WITH_WSREP +#ifdef WITH_WSREP if (WSREP(thd)) { - if (thd->wsrep_conflict_state == NO_CONFLICT || - thd->wsrep_conflict_state == REPLAYING) - { - my_ok(thd); + if (thd->wsrep_conflict_state == NO_CONFLICT) { + my_ok(thd); } } else { #endif /* WITH_WSREP */ - my_ok(thd); - #ifdef WITH_WSREP + my_ok(thd); +#ifdef WITH_WSREP } #endif /* WITH_WSREP */ - break; + break; } case SQLCOM_RELEASE_SAVEPOINT: if (trans_release_savepoint(thd, lex->ident)) @@ -4781,7 +4805,9 @@ create_sp_error: if (trans_xa_commit(thd)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } thd->mdl_context.release_transactional_locks(); @@ -4796,7 +4822,9 @@ create_sp_error: if (trans_xa_rollback(thd)) { thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ goto error; } thd->mdl_context.release_transactional_locks(); @@ -5931,7 +5959,12 @@ void THD::reset_for_next_command() thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; #ifdef WITH_WSREP - if (WSREP(thd)) { + /* + Autoinc variables should be adjusted only for locally executed + transactions. Appliers and replayers are either processing ROW + events or get autoinc variable values from Query_log_event. + */ + if (WSREP(thd) && thd->wsrep_exec_mode == LOCAL_STATE) { if (wsrep_auto_increment_control) { if (thd->variables.auto_increment_offset != @@ -6147,96 +6180,10 @@ void mysql_init_multi_delete(LEX *lex) } #ifdef WITH_WSREP -void wsrep_replay_transaction(THD *thd) -{ - /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) - { - if (thd->wsrep_exec_mode!= REPL_RECV) - { - if (thd->stmt_da->is_sent) - { - WSREP_ERROR("replay issue, thd has reported status already"); - } - thd->stmt_da->reset_diagnostics_area(); - - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - mysql_reset_thd_for_next_command(thd); - thd->killed= NOT_KILLED; - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%ld)", - thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); - - thd_proc_info(thd, "wsrep replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)thd->wsrep_trx_seqno); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_trx_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_wsrep_thd); - - switch (rcode) - { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); - WSREP_DEBUG("trx_replay successful for: %ld %llu", - thd->thread_id, (long long)thd->real_id); - break; - case WSREP_TRX_FAIL: - if (thd->stmt_da->is_sent) - { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - } - thd->wsrep_conflict_state= ABORTED; - thd->wsrep_bf_thd = NULL; - wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, query: %s", - rcode, thd->query() ? thd->query() : "void"); - /* we're now in inconsistent state, must abort */ - unireg_abort(1); - break; - } - - wsrep_cleanup_transaction(thd); - - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - } -} - static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state) + Parser_state *parser_state) { - bool is_autocommit= + bool is_autocommit= !thd->in_multi_stmt_transaction_mode() && thd->wsrep_conflict_state == NO_CONFLICT && !thd->wsrep_applier && @@ -6259,9 +6206,10 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, WSREP_DEBUG("abort in exec query state, avoiding autocommit"); } - if (thd->wsrep_conflict_state== MUST_REPLAY) + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) { - wsrep_replay_transaction(thd); + wsrep_replay_transaction(thd); } /* setting error code for BF aborted trxs */ @@ -6274,7 +6222,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->lex->sql_command != SQLCOM_SELECT && (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) { - WSREP_DEBUG("wsrep retrying AC query: %s", + WSREP_DEBUG("wsrep retrying AC query: %s", (thd->query()) ? thd->query() : "void"); close_thread_tables(thd); @@ -6287,10 +6235,10 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, } else { - WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", - (thd->wsrep_conflict_state == ABORTED) ? + WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + (thd->wsrep_conflict_state == ABORTED) ? "BF Aborted" : "cert failure", - thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + thd->thread_id, is_autocommit, thd->wsrep_retry_counter, thd->variables.wsrep_retry_autocommit, thd->query()); my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); thd->killed= NOT_KILLED; @@ -6309,7 +6257,8 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, if (thd->wsrep_retry_query) { - WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s", + WSREP_DEBUG("releasing retry_query: " + "conf %d sent %d kill %d errno %d SQL %s", thd->wsrep_conflict_state, thd->stmt_da->is_sent, thd->killed, @@ -7304,7 +7253,7 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal) #ifdef WITH_WSREP if (((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) && - !wsrep_thd_is_brute_force((void *)tmp)) + !wsrep_thd_is_brute_force((void *)tmp)) #else if ((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) @@ -8083,621 +8032,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } -#ifdef WITH_WSREP -/* must have (&thd->LOCK_wsrep_thd) */ -static void wsrep_client_rollback(THD *thd) -{ - WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", - thd->thread_id, thd->query()); - - thd->wsrep_conflict_state= ABORTING; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - trans_rollback(thd); - - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("unlocking tables for BF abort (%ld)", 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 (%ld)", 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 (%ld)", thd->thread_id); - thd->clear_binlog_table_maps(); - } - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_conflict_state= ABORTED; - thd->wsrep_bf_thd = NULL; -} - -static enum wsrep_status wsrep_apply_sql( - THD *thd, const char *sql, size_t sql_len, time_t timeval, uint32 randseed) -{ - int error; - enum wsrep_status ret_code= WSREP_OK; - CHARSET_INFO *current_charset = thd->variables.character_set_client; - - DBUG_ENTER("wsrep_bf_execute_cb"); - thd->wsrep_exec_mode= REPL_RECV; - thd->net.vio= 0; - thd->start_time= timeval; - thd->wsrep_rand= randseed; - - thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; - - DBUG_PRINT("wsrep", ("SQL: %s", sql)); - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_query_state= QUERY_EXEC; - /* preserve replaying mode */ - if (thd->wsrep_conflict_state!= REPLAYING) - thd->wsrep_conflict_state= NO_CONFLICT; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - 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 BF SQL apply temporally setting character set to : %s", - my_charset_latin1.csname); - } - - if ((error= dispatch_command(COM_QUERY, thd, (char*)sql, sql_len))) { - WSREP_WARN("BF SQL apply failed: %d, %lld", - thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); - thd->variables.character_set_client = current_charset; - DBUG_RETURN(WSREP_FATAL); - } - thd->variables.character_set_client = current_charset; - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state!= NO_CONFLICT && - thd->wsrep_conflict_state!= REPLAYING) { - ret_code= WSREP_FATAL; - WSREP_DEBUG("BF thd ending, with: %d, %lld", - thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); - } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - assert(thd->wsrep_exec_mode== REPL_RECV); - DBUG_RETURN(ret_code); -} - -void wsrep_write_rbr_buf( - THD *thd, const void* rbr_buf, size_t buf_len) -{ - char filename[PATH_MAX]= {0}; - int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", - wsrep_data_home_dir, thd->thread_id, - (long long)thd->wsrep_trx_seqno); - if (len >= PATH_MAX) - { - WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); - return; - } - - FILE *of= fopen(filename, "wb"); - if (of) - { - (void) fwrite (rbr_buf, buf_len, 1, of); - fclose(of); - } - else - { - WSREP_ERROR("Failed to open file '%s': %d (%s)", - filename, errno, strerror(errno)); - } -} - -static inline wsrep_status_t wsrep_apply_rbr( - THD *thd, const uchar *rbr_buf, size_t buf_len) -{ - char *buf= (char *)rbr_buf; - int rcode= 0; - int event= 1; - Format_description_log_event *description_event = wsrep_format_desc; - DBUG_ENTER("wsrep_apply_rbr"); - - if (thd->killed == KILL_CONNECTION) - { - WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", - (long long) thd->wsrep_trx_seqno); - DBUG_RETURN(WSREP_FATAL); - } - - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_query_state= QUERY_EXEC; - if (thd->wsrep_conflict_state!= REPLAYING) - thd->wsrep_conflict_state= NO_CONFLICT; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", - (long long) thd->wsrep_trx_seqno); - - if ((rcode= trans_begin(thd))) - WSREP_WARN("begin for rbr apply failed: %lld, code: %d", - (long long) thd->wsrep_trx_seqno, rcode); - - while(buf_len) - { - int exec_res; - int error = 0; - Log_event* ev= wsrep_read_log_event(&buf, &buf_len, description_event); - - if (!ev) - { - WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", - (long long)thd->wsrep_trx_seqno, (long int) buf_len); - rcode= 1; - goto error; - } - switch (ev->get_type_code()) { - case WRITE_ROWS_EVENT: - case UPDATE_ROWS_EVENT: - case DELETE_ROWS_EVENT: - DBUG_ASSERT(buf_len != 0 || - ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)); - break; - case FORMAT_DESCRIPTION_EVENT: - description_event = (Format_description_log_event *)ev; - break; - default: - break; - } - - thd->server_id = ev->server_id; // use the original server id for logging - thd->set_time(); // time the query - wsrep_xid_init(&thd->transaction.xid_state.xid, - wsrep_cluster_uuid(), - thd->wsrep_trx_seqno); - thd->lex->current_select= 0; - if (!ev->when) - ev->when = time(NULL); - ev->thd = thd; - exec_res = ev->apply_event(thd->wsrep_rli); - DBUG_PRINT("info", ("exec_event result: %d", exec_res)); - - if (exec_res) - { - WSREP_WARN("RBR event %d %s apply warning: %d, %lld", - event, ev->get_type_str(), exec_res, (long long) thd->wsrep_trx_seqno); - rcode= exec_res; - /* stop processing for the first error */ - delete ev; - goto error; - } - 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)thd->wsrep_trx_seqno); - - if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_WARN("RBR event apply failed, rolling back: %lld", - (long long) thd->wsrep_trx_seqno); - 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_FATAL); - } - - if ((ev->get_type_code() == WRITE_ROWS_EVENT || - ev->get_type_code() == UPDATE_ROWS_EVENT || - ev->get_type_code() == DELETE_ROWS_EVENT) && - ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)) - { - thd->wsrep_rli->cleanup_context(thd, 0); - - if (error == 0) - { - thd->clear_error(); - } - else - WSREP_ERROR("Error in %s event: commit of row events failed: %lld", - ev->get_type_str(), (long long)thd->wsrep_trx_seqno); - } - - if (description_event != ev) - delete ev; - } - - error: - mysql_mutex_lock(&thd->LOCK_wsrep_thd); - thd->wsrep_query_state= QUERY_IDLE; - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - - assert(thd->wsrep_exec_mode== REPL_RECV); - - if (thd->killed == KILL_CONNECTION) - WSREP_INFO("applier aborted: %lld", (long long)thd->wsrep_trx_seqno); - - if (rcode) DBUG_RETURN(WSREP_FATAL); - DBUG_RETURN(WSREP_OK); -} - -wsrep_status_t wsrep_apply_cb(void* const ctx, - const void* const buf, size_t const buf_len, - wsrep_seqno_t const global_seqno) -{ - THD* const thd((THD*)ctx); - - thd->wsrep_trx_seqno= global_seqno; - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "applying write set %lld: %p, %zu", - (long long)thd->wsrep_trx_seqno, buf, buf_len); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "applying write set"); -#endif /* WSREP_PROC_INFO */ - - wsrep_status_t const rcode(wsrep_apply_rbr(thd, (const uchar*)buf, buf_len)); - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "applied write set %lld", (long long)thd->wsrep_trx_seqno); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "applied write set"); -#endif /* WSREP_PROC_INFO */ - - if (WSREP_OK != rcode) wsrep_write_rbr_buf(thd, buf, buf_len); - TABLE *tmp; - while ((tmp = thd->temporary_tables)) - { - WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", - thd->thread_id, - (tmp->s) ? tmp->s->db.str : "void", - (tmp->s) ? tmp->s->table_name.str : "void"); - close_temporary_table(thd, tmp, 1, 1); - } - - return rcode; -} - -#if DELETE // this does not work in 5.5 -/* a common wrapper for end_trans() function - to put all necessary stuff */ -static inline wsrep_status_t -wsrep_end_trans (THD* const thd, enum enum_mysql_completiontype const end) -{ - if (0 == end_trans(thd, end)) - { - return WSREP_OK; - } - else - { - return WSREP_FATAL; - } -} -#endif - -wsrep_status_t wsrep_commit(THD* const thd, wsrep_seqno_t const global_seqno) -{ -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "committing %lld", (long long)thd->wsrep_trx_seqno); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "committing"); -#endif /* WSREP_PROC_INFO */ - - wsrep_status_t const rcode(wsrep_apply_sql(thd, "COMMIT", 6, 0, 0)); -// wsrep_status_t const rcode(wsrep_end_trans (thd, COMMIT)); - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "committed %lld", (long long)thd->wsrep_trx_seqno); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "committed"); -#endif /* WSREP_PROC_INFO */ - - if (WSREP_OK == rcode) - { - // TODO: mark snapshot with global_seqno. - } - - return rcode; -} - -wsrep_status_t wsrep_rollback(THD* const thd, wsrep_seqno_t const global_seqno) -{ -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "rolling back %lld", (long long)thd->wsrep_trx_seqno); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "rolling back"); -#endif /* WSREP_PROC_INFO */ - - wsrep_status_t const rcode(wsrep_apply_sql(thd, "ROLLBACK", 8, 0, 0)); -// wsrep_status_t const rcode(wsrep_end_trans (thd, ROLLBACK)); - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "rolled back %lld", (long long)thd->wsrep_trx_seqno); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "rolled back"); -#endif /* WSREP_PROC_INFO */ - - return rcode; -} - -wsrep_status_t wsrep_commit_cb(void* const ctx, - wsrep_seqno_t const global_seqno, - bool const commit) -{ - THD* const thd((THD*)ctx); - - assert(global_seqno == thd->wsrep_trx_seqno); - - if (commit) - return wsrep_commit(thd, global_seqno); - else - return wsrep_rollback(thd, global_seqno); -} - -Relay_log_info* wsrep_relay_log_init(const char* log_fname) -{ - Relay_log_info* rli= new Relay_log_info(false); - - rli->no_storage= true; - if (!rli->relay_log.description_event_for_exec) - { - rli->relay_log.description_event_for_exec= - new Format_description_log_event(4); - } - - rli->sql_thd= current_thd; - return rli; -} - -void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) -{ - shadow->options = thd->variables.option_bits; - shadow->wsrep_exec_mode = thd->wsrep_exec_mode; - shadow->vio = thd->net.vio; - - if (opt_log_slave_updates) - thd->variables.option_bits|= OPTION_BIN_LOG; - else - thd->variables.option_bits&= ~(OPTION_BIN_LOG); - - if (!thd->wsrep_rli) thd->wsrep_rli= wsrep_relay_log_init("wsrep_relay"); - - thd->wsrep_exec_mode= REPL_RECV; - thd->net.vio= 0; - thd->clear_error(); - - thd->variables.option_bits|= OPTION_NOT_AUTOCOMMIT; - - shadow->tx_isolation = thd->variables.tx_isolation; - thd->variables.tx_isolation = ISO_READ_COMMITTED; - thd->tx_isolation = ISO_READ_COMMITTED; - - shadow->db = thd->db; - shadow->db_length = thd->db_length; - thd->reset_db(NULL, 0); -} - -void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) -{ - thd->variables.option_bits = shadow->options; - thd->wsrep_exec_mode = shadow->wsrep_exec_mode; - thd->net.vio = shadow->vio; - thd->variables.tx_isolation = shadow->tx_isolation; - - thd->reset_db(shadow->db, shadow->db_length); -} - -void wsrep_replication_process(THD *thd) -{ - int rcode; - DBUG_ENTER("wsrep_replication_process"); - - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - - 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); - /* fall through to node shutdown */ - 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->temporary_tables) - { - WSREP_DEBUG("Applier %lu, has temporary tables at exit", thd->thread_id); - } - wsrep_return_from_bf_mode(thd, &shadow); - DBUG_VOID_RETURN; -} - -void wsrep_rollback_process(THD *thd) -{ - 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; - - mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); - - WSREP_DEBUG("WSREP rollback thread wakes for signal"); - - 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); - - /* check for false alarms */ - if (!wsrep_aborting_thd) - { - 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_wsrep_thd); - if (aborting->wsrep_conflict_state== ABORTED) - { - WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", - (long long)aborting->real_id, - aborting->wsrep_conflict_state); - - mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); - mysql_mutex_lock(&LOCK_wsrep_rollback); - continue; - } - aborting->wsrep_conflict_state= ABORTING; - - mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); - - aborting->store_globals(); - - mysql_mutex_lock(&aborting->LOCK_wsrep_thd); - wsrep_client_rollback(aborting); - WSREP_DEBUG("WSREP rollbacker aborted thd: (%lu %llu)", - aborting->thread_id, (long long)aborting->real_id); - mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); - - mysql_mutex_lock(&LOCK_wsrep_rollback); - } - } - - mysql_mutex_unlock(&LOCK_wsrep_rollback); - sql_print_information("WSREP: rollbacker thread exiting"); - - DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); - DBUG_VOID_RETURN; -} -extern "C" -int wsrep_thd_is_brute_force(void *thd_ptr) -{ - /* - Brute force: - Appliers and replaying are running in REPL_RECV mode. TOI statements - in TOTAL_ORDER mode. Locally committing transaction that has got - past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode. - - Everything else is running in LOCAL_STATE and should not be considered - brute force. - */ - if (thd_ptr) { - switch (((THD *)thd_ptr)->wsrep_exec_mode) { - case LOCAL_STATE: return 0; - case REPL_RECV: return 1; - case TOTAL_ORDER: return 2; - case LOCAL_COMMIT: return 3; - } - } - DBUG_ASSERT(0); - return 0; -} -extern "C" -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"); - - if ( (WSREP(bf_thd) || - ( (WSREP_ON || wsrep_OSU_method_options == WSREP_OSU_RSU) && - bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && - victim_thd) - { - WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? - (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); - ha_wsrep_abort_transaction(bf_thd, victim_thd, signal); - } - else - { - WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); - } - - DBUG_RETURN(1); -} -extern "C" -int wsrep_thd_in_locking_session(void *thd_ptr) -{ - if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { - return 1; - } - return 0; -} -#endif /** Retuns information about user or current user. diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 46f8100d9d1..da03e5f7a03 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2453,7 +2453,7 @@ bool load_table_name_for_trigger(THD *thd, DBUG_RETURN(FALSE); } #ifdef WITH_WSREP -int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len) +int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) { LEX *lex= thd->lex; String stmt_query; @@ -2501,6 +2501,6 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len) stmt_query.append(stmt_definition.str, stmt_definition.length); return wsrep_to_buf_helper(thd, stmt_query.c_ptr(), stmt_query.length(), - buf, buf_len); + buf, buf_len); } #endif /* WITH_WSREP */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index ef70b1e77d0..6c3dd171706 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2571,7 +2571,9 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) { thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; thd->mdl_context.release_transactional_locks(); +#ifdef WITH_WSREP WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id); +#endif /* WITH_WSREP */ return true; } /* @@ -3654,7 +3656,9 @@ static Sys_var_tz Sys_time_zone( SESSION_VAR(time_zone), NO_CMD_LINE, DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG); #ifdef WITH_WSREP -#include "wsrep_mysqld.h" +#include "wsrep_var.h" +#include "wsrep_sst.h" +#include "wsrep_binlog.h" static Sys_var_charptr Sys_wsrep_provider( "wsrep_provider", "Path to replication provider library", @@ -3812,10 +3816,11 @@ static Sys_var_charptr Sys_wsrep_start_position ( ON_CHECK(wsrep_start_position_check), ON_UPDATE(wsrep_start_position_update)); -static Sys_var_ulonglong Sys_wsrep_max_ws_size ( +static Sys_var_ulong Sys_wsrep_max_ws_size ( "wsrep_max_ws_size", "Max write set size (bytes)", GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1024, 4294967296ULL), DEFAULT(1073741824ULL), BLOCK_SIZE(1)); + /* Upper limit is 65K short of 4G to avoid overlows on 32-bit systems */ + VALID_RANGE(1024, WSREP_MAX_WS_SIZE), DEFAULT(1073741824UL), BLOCK_SIZE(1)); static Sys_var_ulong Sys_wsrep_max_ws_rows ( "wsrep_max_ws_rows", "Max number of rows in write set", @@ -3835,8 +3840,7 @@ static Sys_var_mybool Sys_wsrep_certify_nonPK( static Sys_var_mybool Sys_wsrep_causal_reads( "wsrep_causal_reads", "Enable \"strictly synchronous\" semantics for read operations", SESSION_VAR(wsrep_causal_reads), - CMD_LINE(OPT_ARG), DEFAULT(FALSE)); - // ON_UPDATE(wsrep_causal_reads_update)); + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; static Sys_var_enum Sys_wsrep_OSU_method( diff --git a/sql/transaction.cc b/sql/transaction.cc index c66b86ff87f..36ed15bfe9c 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -298,6 +298,7 @@ bool trans_rollback(THD *thd) DBUG_RETURN(test(res)); } + /** Implicitly rollback the current transaction, typically after deadlock was discovered. @@ -329,7 +330,6 @@ bool trans_rollback_implicit(THD *thd) #ifdef WITH_WSREP wsrep_register_hton(thd, true); #endif /* WITH_WSREP */ - thd->server_status&= ~SERVER_STATUS_IN_TRANS; DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); res= ha_rollback_trans(thd, true); @@ -433,7 +433,6 @@ bool trans_rollback_stmt(THD *thd) wsrep_register_hton(thd, FALSE); #endif /* WITH_WSREP */ ha_rollback_trans(thd, FALSE); - if (! thd->in_active_multi_stmt_transaction()) thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; } diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc new file mode 100644 index 00000000000..f1016dff902 --- /dev/null +++ b/sql/wsrep_applier.cc @@ -0,0 +1,351 @@ +/* Copyright (C) 2013 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "wsrep_priv.h" +#include "wsrep_binlog.h" // wsrep_dump_rbr_buf() + +#include "log_event.h" // EVENT_LEN_OFFSET, etc. + +#include "wsrep_applier.h" + +/* + read the first event from (*buf). The size of the (*buf) is (*buf_len). + 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) +{ + DBUG_ENTER("wsrep_read_log_event"); + char *head= (*arg_buf); + + uint data_len = uint4korr(head + EVENT_LEN_OFFSET); + char *buf= (*arg_buf); + const char *error= 0; + Log_event *res= 0; + + if (data_len > wsrep_max_ws_size) + { + error = "Event too big"; + goto err; + } + + res= Log_event::read_log_event(buf, data_len, &error, description_event, + FALSE); + +err: + if (!res) + { + DBUG_ASSERT(error != 0); + sql_print_error("Error in Log_event::read_log_event(): " + "'%s', data_len: %d, event_type: %d", + error,data_len,head[EVENT_TYPE_OFFSET]); + } + (*arg_buf)+= data_len; + (*arg_buf_len)-= data_len; + DBUG_RETURN(res); +} + +#include "transaction.h" // trans_commit(), trans_rollback() +#include "rpl_rli.h" // class Relay_log_info; +#include "sql_base.h" // close_temporary_table() + +extern const Format_description_log_event *wsrep_format_desc; + +static wsrep_cb_status_t wsrep_apply_events(THD* thd, + const void* events_buf, + size_t buf_len) +{ + char *buf= (char *)events_buf; + int rcode= 0; + int event= 1; + + DBUG_ENTER("wsrep_apply_rbr"); + + if (thd->killed == KILL_CONNECTION) + { + WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", + (long long) wsrep_thd_trx_seqno(thd)); + DBUG_RETURN(WSREP_CB_FAILURE); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + if (thd->wsrep_conflict_state!= REPLAYING) + thd->wsrep_conflict_state= NO_CONFLICT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", + (long long) wsrep_thd_trx_seqno(thd)); + + while(buf_len) + { + int exec_res; + int error = 0; + Log_event* ev= wsrep_read_log_event(&buf, &buf_len, wsrep_format_desc); + + if (!ev) + { + WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", + (long long)wsrep_thd_trx_seqno(thd), buf_len); + rcode= 1; + goto error; + } + switch (ev->get_type_code()) { + case WRITE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case DELETE_ROWS_EVENT: + DBUG_ASSERT(buf_len != 0 || + ((Rows_log_event*)ev)->get_flags(Rows_log_event::STMT_END_F)); + break; + default: + break; + } + + thd->server_id = ev->server_id; // use the original server id for logging + thd->set_time(); // time the query + wsrep_xid_init(&thd->transaction.xid_state.xid, + &thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + thd->lex->current_select= 0; + if (!ev->when) + ev->when = time(NULL); + ev->thd = thd; + exec_res = ev->apply_event(thd->wsrep_rli); + DBUG_PRINT("info", ("exec_event result: %d", exec_res)); + + if (exec_res) + { + WSREP_WARN("RBR event %d %s apply warning: %d, %lld", + event, ev->get_type_str(), exec_res, + (long long) wsrep_thd_trx_seqno(thd)); + rcode= exec_res; + /* stop processing for the first error */ + delete ev; + goto error; + } + 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); + } + + if ((ev->get_type_code() == WRITE_ROWS_EVENT || + ev->get_type_code() == UPDATE_ROWS_EVENT || + ev->get_type_code() == DELETE_ROWS_EVENT) && + ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)) + { + thd->wsrep_rli->cleanup_context(thd, 0); + + if (error == 0) + { + thd->clear_error(); + } + else + WSREP_ERROR("Error in %s event: commit of row events failed: %lld", + ev->get_type_str(), (long long)wsrep_thd_trx_seqno(thd)); + } + delete ev; + } + + error: + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_IDLE; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + assert(thd->wsrep_exec_mode== REPL_RECV); + + 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); + + 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 */ + + 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(thd, buf, buf_len); + } + + TABLE *tmp; + while ((tmp = thd->temporary_tables)) + { + WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", + thd->thread_id, + (tmp->s) ? tmp->s->db.str : "void", + (tmp->s) ? tmp->s->table_name.str : "void"); + close_temporary_table(thd, tmp, 1, 1); + } + + return rcode; +} + +static wsrep_cb_status_t wsrep_commit(THD* const thd, + wsrep_seqno_t const global_seqno) +{ +#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); + +#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 */ + + if (WSREP_CB_SUCCESS == rcode) + { + // TODO: mark snapshot with global_seqno. + } + + return rcode; +} + +static wsrep_cb_status_t wsrep_rollback(THD* const thd, + wsrep_seqno_t const global_seqno) +{ +#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, meta->gtid.seqno); + else + rcode = wsrep_rollback(thd, meta->gtid.seqno); + + thd->mdl_context.release_transactional_locks(); + 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 (*exit == false && 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; +} diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h new file mode 100644 index 00000000000..816970db67c --- /dev/null +++ b/sql/wsrep_applier.h @@ -0,0 +1,38 @@ +/* Copyright 2013 Codership Oy + + 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_APPLIER_H +#define WSREP_APPLIER_H + +#include + +/* wsrep callback prototypes */ + +wsrep_cb_status_t wsrep_apply_cb(void *ctx, + const void* buf, size_t buf_len, + uint32_t flags, + const wsrep_trx_meta_t* meta); + +wsrep_cb_status_t wsrep_commit_cb(void *ctx, + uint32_t flags, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit, + bool commit); + +wsrep_cb_status_t wsrep_unordered_cb(void* ctx, + const void* data, + size_t size); + +#endif /* WSREP_APPLIER_H */ diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc new file mode 100644 index 00000000000..a0c56ce9299 --- /dev/null +++ b/sql/wsrep_binlog.cc @@ -0,0 +1,321 @@ +/* Copyright (C) 2013 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "wsrep_binlog.h" +#include "wsrep_priv.h" + +/* + Write the contents of a cache to a memory buffer. + + 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_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len) +{ + *buf= NULL; + *buf_len= 0; + + 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 ER_ERROR_ON_WRITE; + } + + uint length = my_b_bytes_in_cache(cache); + if (unlikely(0 == length)) length = my_b_fill(cache); + + size_t total_length = 0; + + 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 (total_length > wsrep_max_ws_size) + { + WSREP_WARN("transaction size limit (%lu) exceeded: %zu", + wsrep_max_ws_size, total_length); + goto error; + } + + uchar* tmp = (uchar *)my_realloc(*buf, total_length, MYF(0)); + if (!tmp) + { + WSREP_ERROR("could not (re)allocate buffer: %zu + %u", + *buf_len, length); + goto error; + } + *buf = tmp; + + memcpy(*buf + *buf_len, cache->read_pos, length); + *buf_len = total_length; + cache->read_pos = cache->read_end; + } while ((cache->file >= 0) && (length = my_b_fill(cache))); + + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_WARN("failed to initialize io-cache"); + goto cleanup; + } + + return 0; + +error: + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_ERROR("failed to initialize io-cache"); + } +cleanup: + my_free(*buf); + *buf= NULL; + *buf_len= 0; + return ER_ERROR_ON_WRITE; +} + +#define STACK_SIZE 4096 /* 4K - for buffer preallocated on the stack: + * many transactions would fit in there + * so there is no need to reach for the heap */ + +/* Returns minimum multiple of HEAP_PAGE_SIZE that is >= length */ +static inline size_t +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)); + 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)); + + if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) + { + WSREP_ERROR("failed to initialize io-cache"); + 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); + 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(0)); + if (!tmp) + { + WSREP_ERROR("could not (re)allocate buffer: %zu + %u", + allocated, length); + err = WSREP_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; + cache->read_pos = cache->read_end; + } while ((cache->file >= 0) && (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(thd, buf, used); + + my_free(heap_buf); + return err; +} + +/* + 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 uses incremental data appending as it reads it from cache. + */ +static int wsrep_write_cache_inc(wsrep_t* const wsrep, + THD* const thd, + IO_CACHE* const cache, + size_t* const len) +{ + 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 WSREP_TRX_ROLLBACK; + } + + int err(WSREP_OK); + + size_t total_length(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 + 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_SIZE_EXCEEDED; + goto cleanup; + } + + if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle, + cache->read_pos, length))) + goto cleanup; + + cache->read_pos = cache->read_end; + } while ((cache->file >= 0) && (length = my_b_fill(cache))); + + 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"); + } + + return err; +} + +/* + 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. + */ +int wsrep_write_cache(wsrep_t* const wsrep, + 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); + } +} + +void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) +{ + char filename[PATH_MAX]= {0}; + int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", + wsrep_data_home_dir, thd->thread_id, + (long long)wsrep_thd_trx_seqno(thd)); + if (len >= PATH_MAX) + { + WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); + return; + } + + FILE *of= fopen(filename, "wb"); + if (of) + { + fwrite (rbr_buf, buf_len, 1, of); + fclose(of); + } + else + { + WSREP_ERROR("Failed to open file '%s': %d (%s)", + filename, errno, strerror(errno)); + } +} + diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h new file mode 100644 index 00000000000..6de73b2f5ee --- /dev/null +++ b/sql/wsrep_binlog.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2013 Codership Oy + + 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_BINLOG_H +#define WSREP_BINLOG_H + +#include "sql_class.h" // THD, IO_CACHE + +#define HEAP_PAGE_SIZE 65536 /* 64K */ +#define WSREP_MAX_WS_SIZE (0xFFFFFFFFUL - HEAP_PAGE_SIZE) + +/* + Write the contents of a cache to a memory buffer. + + 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_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len); + +/* + 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. + + @param len total amount of data written + @return wsrep error status + */ +int wsrep_write_cache (wsrep_t* wsrep, + THD* thd, + IO_CACHE* cache, + size_t* len); + +/* Dump replication buffer to disk */ +void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); + +#endif /* WSREP_BINLOG_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index d4bb77c9e6f..8eb5340dd58 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -18,7 +18,7 @@ #include "rpl_filter.h" #include #include "wsrep_mysqld.h" -#include "wsrep_priv.h" +#include "wsrep_binlog.h" #include #include @@ -26,10 +26,11 @@ 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 +extern "C" int thd_binlog_format(const MYSQL_THD thd); +// todo: share interface with ha_innodb.c -enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); +enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, + bool all); /* Cleanup after local transaction commit/rollback, replay or TOI. @@ -37,8 +38,9 @@ enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool al void wsrep_cleanup_transaction(THD *thd) { if (wsrep_emulate_bin_log) thd_binlog_trx_reset(thd); - thd->wsrep_trx_handle.trx_id= WSREP_UNDEFINED_TRX_ID; - thd->wsrep_trx_seqno= WSREP_SEQNO_UNDEFINED; + 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; return; } @@ -66,7 +68,7 @@ handlerton *wsrep_hton; */ void wsrep_register_hton(THD* thd, bool all) { - if (thd->wsrep_exec_mode != TOTAL_ORDER) + if (thd->wsrep_exec_mode != TOTAL_ORDER && !thd->wsrep_apply_toi) { THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) @@ -94,8 +96,8 @@ void wsrep_post_commit(THD* thd, bool all) { if (thd->wsrep_exec_mode == LOCAL_COMMIT) { - DBUG_ASSERT(thd->wsrep_trx_seqno != WSREP_SEQNO_UNDEFINED); - if (wsrep->post_commit(wsrep, &thd->wsrep_trx_handle)) + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); + if (wsrep->post_commit(wsrep, &thd->wsrep_ws_handle)) { DBUG_PRINT("wsrep", ("set committed fail")); WSREP_WARN("set committed fail: %llu %d", @@ -106,7 +108,7 @@ void wsrep_post_commit(THD* thd, bool all) } /* - wsrep exploits binlog's caches even if binlogging itself is not + 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 @@ -125,7 +127,7 @@ wsrep_close_connection(handlerton* hton, THD* thd) 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 @@ -147,18 +149,15 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all) 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_seqno == WSREP_SEQNO_UNDEFINED); + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); - if ((all || + if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) { switch (wsrep_run_wsrep_commit(thd, hton, all)) { case WSREP_TRX_OK: - // DBUG_ASSERT(thd->wsrep_trx_seqno > old || - // thd->wsrep_exec_mode == REPL_RECV || - // thd->wsrep_exec_mode == TOTAL_ORDER); break; case WSREP_TRX_ROLLBACK: case WSREP_TRX_ERROR: @@ -208,10 +207,10 @@ static int wsrep_rollback(handlerton *hton, THD *thd, bool all) if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) { - if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) + if (wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) { DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", (long long)thd->real_id, thd->query()); } wsrep_cleanup_transaction(thd); @@ -249,12 +248,12 @@ int wsrep_commit(handlerton *hton, THD *thd, bool all) possible changes to clean state. */ if (WSREP_PROVIDER_EXISTS) { - if (wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle)) - { - DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", - (long long)thd->real_id, thd->query()); - } + if (wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) + { + DBUG_PRINT("wsrep", ("setting rollback fail")); + WSREP_ERROR("settting rollback fail: thd: %llu SQL: %s", + (long long)thd->real_id, thd->query()); + } } wsrep_cleanup_transaction(thd); } @@ -266,26 +265,24 @@ int wsrep_commit(handlerton *hton, THD *thd, bool all) extern Rpl_filter* binlog_filter; extern my_bool opt_log_slave_updates; -extern void wsrep_write_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); + enum wsrep_trx_status -wsrep_run_wsrep_commit( - THD *thd, handlerton *hton, bool all) +wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) { - int rcode = -1; - uint data_len = 0; - uchar *rbr_data = NULL; + int rcode= -1; + size_t data_len= 0; IO_CACHE *cache; int replay_round= 0; if (thd->stmt_da->is_error()) { - WSREP_ERROR("commit issue, error: %d %s", + WSREP_ERROR("commit issue, error: %d %s", thd->stmt_da->sql_errno(), thd->stmt_da->message()); } DBUG_ENTER("wsrep_run_wsrep_commit"); - if (thd->slave_thread && !opt_log_slave_updates) { - DBUG_RETURN(WSREP_TRX_OK); - } + + 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_wsrep_thd); @@ -303,9 +300,9 @@ wsrep_run_wsrep_commit( } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } - if (thd->wsrep_exec_mode != LOCAL_STATE) { - DBUG_RETURN(WSREP_TRX_OK); - } + + 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); @@ -327,10 +324,10 @@ wsrep_run_wsrep_commit( mysql_mutex_lock(&LOCK_wsrep_replaying); - while (wsrep_replaying > 0 && + while (wsrep_replaying > 0 && thd->wsrep_conflict_state == NO_CONFLICT && thd->killed == NOT_KILLED && - !shutdown_in_progress) + !shutdown_in_progress) { mysql_mutex_unlock(&LOCK_wsrep_replaying); @@ -348,9 +345,12 @@ wsrep_run_wsrep_commit( 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: (%lu) conflict: %d (round: %d)", - wsrep_replaying, thd->thread_id, thd->wsrep_conflict_state, replay_round); + WSREP_DEBUG("commit waiting for replaying: replayers %d, thd: (%lu) " + "conflict: %d (round: %d)", + wsrep_replaying, thd->thread_id, + thd->wsrep_conflict_state, replay_round); mysql_mutex_unlock(&LOCK_wsrep_replaying); @@ -371,7 +371,8 @@ wsrep_run_wsrep_commit( WSREP_DEBUG("innobase_commit abort after replaying wait %s", (thd->query()) ? thd->query() : "void"); DBUG_RETURN(WSREP_TRX_ROLLBACK); - } + } + thd->wsrep_query_state = QUERY_COMMITTING; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -379,28 +380,28 @@ wsrep_run_wsrep_commit( rcode = 0; if (cache) { thd->binlog_flush_pending_rows_event(true); - rcode = wsrep_write_cache(cache, &rbr_data, &data_len); - if (rcode) { - WSREP_ERROR("rbr write fail, data_len: %d, %d", data_len, rcode); - if (data_len) my_free(rbr_data); + 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_ROLLBACK); } } - if (data_len == 0) + + if (data_len == 0) { - if (thd->stmt_da->is_ok() && + if (thd->stmt_da->is_ok() && thd->stmt_da->affected_rows() > 0 && !binlog_filter->is_on()) { WSREP_DEBUG("empty rbr buffer, query: %s, " - "affected rows: %llu, " - "changed tables: %d, " + "affected rows: %llu, " + "changed tables: %d, " "sql_log_bin: %d, " - "wsrep status (%d %d %d)", + "wsrep status (%d %d %d)", thd->query(), thd->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); + thd->wsrep_exec_mode, thd->wsrep_query_state, + thd->wsrep_conflict_state); } else { @@ -409,38 +410,33 @@ wsrep_run_wsrep_commit( thd->wsrep_query_state= QUERY_EXEC; DBUG_RETURN(WSREP_TRX_OK); } - if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_handle.trx_id) + + if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id) { - WSREP_WARN("SQL statement was ineffective, THD: %lu, buf: %d\n" - "QUERY: %s\n" - " => Skipping replication", - thd->thread_id, data_len, thd->query()); - if (wsrep_debug) - { - wsrep_write_rbr_buf(thd, rbr_data, data_len); - } + WSREP_WARN("SQL statement was ineffective, THD: %lu, buf: %zu\n" + "QUERY: %s\n" + " => Skipping replication", + thd->thread_id, data_len, thd->query()); rcode = WSREP_TRX_FAIL; } else if (!rcode) { - rcode = wsrep->pre_commit( - wsrep, - (wsrep_conn_id_t)thd->thread_id, - &thd->wsrep_trx_handle, - rbr_data, - data_len, - (thd->wsrep_PA_safe) ? WSREP_FLAG_PA_SAFE : 0ULL, - &thd->wsrep_trx_seqno); - switch (rcode) { - case WSREP_TRX_MISSING: + if (WSREP_OK == rcode) + 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); + + if (rcode == WSREP_TRX_MISSING) { WSREP_WARN("Transaction missing in provider, thd: %ld, SQL: %s", thd->thread_id, thd->query()); - wsrep_write_rbr_buf(thd, rbr_data, data_len); rcode = WSREP_TRX_FAIL; - break; - case WSREP_BF_ABORT: + } else if (rcode == WSREP_BF_ABORT) { WSREP_DEBUG("thd %lu seqno %lld BF aborted by provider, will replay", - thd->thread_id, (long long)thd->wsrep_trx_seqno); + thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno); mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_conflict_state = MUST_REPLAY; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -449,22 +445,14 @@ wsrep_run_wsrep_commit( WSREP_DEBUG("replaying increased: %d, thd: %lu", wsrep_replaying, thd->thread_id); mysql_mutex_unlock(&LOCK_wsrep_replaying); - break; - default: - break; } } else { WSREP_ERROR("I/O error reading from thd's binlog iocache: " "errno=%d, io cache code=%d", my_errno, cache->error); - if (data_len) my_free(rbr_data); DBUG_ASSERT(0); // failure like this can not normally happen DBUG_RETURN(WSREP_TRX_ERROR); } - if (data_len) { - my_free(rbr_data); - } - mysql_mutex_lock(&thd->LOCK_wsrep_thd); switch(rcode) { case 0: @@ -481,22 +469,22 @@ wsrep_run_wsrep_commit( { WSREP_WARN("thd %lu seqno %lld: conflict state %d after post commit", thd->thread_id, - (long long)thd->wsrep_trx_seqno, + (long long)thd->wsrep_trx_meta.gtid.seqno, thd->wsrep_conflict_state); } thd->wsrep_exec_mode= LOCAL_COMMIT; - DBUG_ASSERT(thd->wsrep_trx_seqno != WSREP_SEQNO_UNDEFINED); + 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, - wsrep_cluster_uuid(), - thd->wsrep_trx_seqno); + &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_seqno != WSREP_SEQNO_UNDEFINED); + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); case WSREP_TRX_FAIL: WSREP_DEBUG("commit failed for reason: %d", rcode); DBUG_PRINT("wsrep", ("replicating commit fail")); @@ -505,7 +493,7 @@ wsrep_run_wsrep_commit( if (thd->wsrep_conflict_state == MUST_ABORT) { thd->wsrep_conflict_state= ABORTED; - } + } else { WSREP_DEBUG("conflict state: %d", thd->wsrep_conflict_state); @@ -563,14 +551,15 @@ mysql_declare_plugin(wsrep) &wsrep_storage_engine, "wsrep", "Codership Oy", - "A pseudo storage engine to represent transactions in multi-master synchornous replication", + "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 */ - NULL, /* config options */ + NULL, /* config options */ 0, /* flags */ } mysql_declare_plugin_end; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 2181054a34c..666952e6f52 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright 2008 Codership Oy +/* Copyright 2008-2013 Codership Oy 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,11 +17,17 @@ #include #include #include "wsrep_priv.h" +#include "wsrep_thd.h" +#include "wsrep_sst.h" +#include "wsrep_utils.h" +#include "wsrep_var.h" +#include "wsrep_binlog.h" +#include "wsrep_applier.h" #include #include #include "log_event.h" -extern Format_description_log_event *wsrep_format_desc; +Format_description_log_event *wsrep_format_desc = NULL; wsrep_t *wsrep = NULL; my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface @@ -33,24 +39,26 @@ const char* wsrep_data_home_dir = NULL; const char* wsrep_dbug_option = ""; long wsrep_slave_threads = 1; // # of slave action appliers wanted +int wsrep_slave_count_change = 0; // # of appliers to stop or start my_bool wsrep_debug = 0; // enable debug level logging my_bool wsrep_convert_LOCK_to_trx = 1; // convert locking sessions to trx ulong wsrep_retry_autocommit = 5; // retry aborted autocommit trx my_bool wsrep_auto_increment_control = 1; // control auto increment variables my_bool wsrep_drupal_282555_workaround = 1; // retry autoinc insert after dupkey my_bool wsrep_incremental_data_collection = 0; // incremental data collection -long long wsrep_max_ws_size = 1073741824LL; //max ws (RBR buffer) size -long wsrep_max_ws_rows = 65536; // max number of rows in ws +ulong wsrep_max_ws_size = 1073741824UL;//max ws (RBR buffer) size +ulong wsrep_max_ws_rows = 65536; // max number of rows in ws int wsrep_to_isolation = 0; // # of active TO isolation threads my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key long wsrep_max_protocol_version = 2; // maximum protocol version to use ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery my_bool wsrep_replicate_myisam = 0; // enable myisam replication -my_bool wsrep_log_conflicts = 0; // +my_bool wsrep_log_conflicts = 0; ulong wsrep_mysql_replication_bundle = 0; +my_bool wsrep_desync = 0; // desynchronize the node from the + // cluster my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals -my_bool wsrep_desync = 0; // desynchronize the node from the cluster /* * End configuration options @@ -88,12 +96,12 @@ 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; /* End wsrep status variables */ - wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; @@ -104,14 +112,6 @@ long wsrep_protocol_version = 2; // if there was no state gap on receiving first view event. static my_bool wsrep_startup = TRUE; -// action execute callback -extern wsrep_status_t wsrep_apply_cb(void *ctx, - const void* buf, size_t buf_len, - wsrep_seqno_t global_seqno); - -extern wsrep_status_t wsrep_commit_cb (void *ctx, - wsrep_seqno_t global_seqno, - bool commit); static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { switch (level) { @@ -195,19 +195,25 @@ void wsrep_get_SE_checkpoint(XID* xid) plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); } -static void 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, - ssize_t* sst_req_len) +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) { + *sst_req = NULL; + *sst_req_len = 0; + wsrep_member_status_t new_status= local_status.get(); - if (memcmp(&cluster_uuid, &view->uuid, sizeof(wsrep_uuid_t))) + if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) { - memcpy((wsrep_uuid_t*)&cluster_uuid, &view->uuid, sizeof(cluster_uuid)); + memcpy((wsrep_uuid_t*)&cluster_uuid, &view->state_id.uuid, + sizeof(cluster_uuid)); + wsrep_uuid_print (&cluster_uuid, cluster_uuid_str, sizeof(cluster_uuid_str)); } @@ -219,7 +225,7 @@ static void wsrep_view_handler_cb (void* app_ctx, 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->seqno, + 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); @@ -274,16 +280,18 @@ static void wsrep_view_handler_cb (void* app_ctx, WSREP_DEBUG("[debug]: closing client connections for PRIM"); wsrep_close_client_connections(TRUE); - *sst_req_len= wsrep_sst_prepare (sst_req); + ssize_t const req_len= wsrep_sst_prepare (sst_req); - if (*sst_req_len < 0) + if (req_len < 0) { - int err = *sst_req_len; - WSREP_ERROR("SST preparation failed: %d (%s)", -err, strerror(-err)); + WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len, + strerror(-req_len)); new_status= WSREP_MEMBER_UNDEFINED; } else { + assert(sst_req != NULL); + *sst_req_len= req_len; new_status= WSREP_MEMBER_JOINER; } } @@ -299,14 +307,14 @@ static void wsrep_view_handler_cb (void* app_ctx, { wsrep_SE_init_grab(); // Signal mysqld init thread to continue - wsrep_sst_complete (&cluster_uuid, view->seqno, false); + wsrep_sst_complete (&cluster_uuid, view->state_id.seqno, false); // and wait for SE initialization wsrep_SE_init_wait(); } else { local_uuid= cluster_uuid; - local_seqno= view->seqno; + local_seqno= view->state_id.seqno; } /* Init storage engine XIDs from first view */ XID xid; @@ -319,7 +327,7 @@ static void wsrep_view_handler_cb (void* app_ctx, 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->seqno, + wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno, &local_uuid, -1); unireg_abort(1); } @@ -331,9 +339,23 @@ static void wsrep_view_handler_cb (void* app_ctx, global_system_variables.auto_increment_increment= view->memb_num; } + { /* 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; + } + out: wsrep_startup= FALSE; local_status.set(new_status, view); + + return WSREP_CB_SUCCESS; } void wsrep_ready_set (my_bool x) @@ -364,14 +386,26 @@ void wsrep_ready_wait () static void wsrep_synced_cb(void* app_ctx) { WSREP_INFO("Synchronized with group, ready for connections"); + bool signal_main= false; if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); if (!wsrep_ready) { wsrep_ready= TRUE; mysql_cond_signal (&COND_wsrep_ready); + signal_main= true; + } local_status.set(WSREP_MEMBER_SYNCED); mysql_mutex_unlock (&LOCK_wsrep_ready); + + 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(); + } } static void wsrep_init_position() @@ -416,6 +450,8 @@ static void wsrep_init_position() } } +extern const char* my_bind_addr_str; + int wsrep_init() { int rcode= -1; @@ -470,7 +506,7 @@ int wsrep_init() size_t const node_addr_max= sizeof(node_addr) - 1; if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) { - size_t const ret= guess_ip(node_addr, node_addr_max); + size_t const ret= wsrep_guess_ip(node_addr, node_addr_max); if (!(ret > 0 && ret < node_addr_max)) { WSREP_WARN("Failed to guess base node address. Set it explicitly via " @@ -488,37 +524,56 @@ int wsrep_init() if ((!wsrep_node_incoming_address || !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { - size_t const node_addr_len= strlen(node_addr); - if (node_addr_len > 0) + unsigned int my_bind_ip= INADDR_ANY; // default if not set + if (my_bind_addr_str && strlen(my_bind_addr_str)) { - const char* const colon= strrchr(node_addr, ':'); - if (strchr(node_addr, ':') == colon) // 1 or 0 ':' + my_bind_ip= wsrep_check_ip(my_bind_addr_str); + } + + if (INADDR_ANY != my_bind_ip) + { + if (INADDR_NONE != my_bind_ip && INADDR_LOOPBACK != my_bind_ip) { - size_t const ip_len= colon ? colon - node_addr : node_addr_len; - if (ip_len + 7 /* :55555\0 */ < inc_addr_max) + snprintf(inc_addr, inc_addr_max, "%s:%u", + my_bind_addr_str, (int)mysqld_port); + } // else leave inc_addr an empty string - mysqld is not listening for + // client connections on network interfaces. + } + else // mysqld binds to 0.0.0.0, take IP from wsrep_node_address if possible + { + size_t const node_addr_len= strlen(node_addr); + if (node_addr_len > 0) + { + const char* const colon= strrchr(node_addr, ':'); + if (strchr(node_addr, ':') == colon) // 1 or 0 ':' { - memcpy (inc_addr, node_addr, ip_len); - snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",mysqld_port); + size_t const ip_len= colon ? colon - node_addr : node_addr_len; + if (ip_len + 7 /* :55555\0 */ < inc_addr_max) + { + memcpy (inc_addr, node_addr, 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'; + } } else { WSREP_WARN("Guessing address for incoming client connections: " - "address too long."); + "too many colons :) ."); inc_addr[0]= '\0'; } } - else - { - WSREP_WARN("Guessing address for incoming client connections: " - "too many colons :) ."); - inc_addr[0]= '\0'; - } - } - if (!strlen(inc_addr)) - { - WSREP_WARN("Guessing address for incoming client connections failed. " - "Try setting wsrep_node_incoming_address explicitly."); + if (!strlen(inc_addr)) + { + WSREP_WARN("Guessing address for incoming client connections failed. " + "Try setting wsrep_node_incoming_address explicitly."); + } } } else if (!strchr(wsrep_node_incoming_address, ':')) // no port included @@ -546,6 +601,8 @@ int wsrep_init() struct wsrep_init_args wsrep_args; + struct wsrep_gtid const state_id = { local_uuid, local_seqno }; + wsrep_args.data_dir = wsrep_data_home_dir; wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; wsrep_args.node_address = node_addr; @@ -554,13 +611,13 @@ int wsrep_init() wsrep_provider_options : ""; wsrep_args.proto_ver = wsrep_max_protocol_version; - wsrep_args.state_uuid = &local_uuid; - wsrep_args.state_seqno = local_seqno; + wsrep_args.state_id = &state_id; 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; @@ -661,8 +718,36 @@ void wsrep_stop_replication(THD *thd) return; } +/* This one is set to true when --wsrep-new-cluster is found in the command + * line arguments */ +static my_bool wsrep_new_cluster= FALSE; +#define WSREP_NEW_CLUSTER "--wsrep-new-cluster" +/* Finds and hides --wsrep-new-cluster from the arguments list + * by moving it to the end of the list and decrementing argument count */ +void wsrep_filter_new_cluster (int* argc, char* argv[]) +{ + int i; + for (i= *argc - 1; i > 0; i--) + { + /* make a copy of the argument to convert possible underscores to hyphens. + * the copy need not to be longer than WSREP_NEW_CLUSTER option */ + char arg[sizeof(WSREP_NEW_CLUSTER) + 2]= { 0, }; + strncpy(arg, argv[i], sizeof(arg) - 1); + char* underscore; + while (NULL != (underscore= strchr(arg, '_'))) *underscore= '-'; -extern my_bool wsrep_new_cluster; + if (!strcmp(arg, WSREP_NEW_CLUSTER)) + { + wsrep_new_cluster= TRUE; + *argc -= 1; + /* preserve the order of remaining arguments AND + * preserve the original argument pointers - just in case */ + char* wnc= argv[i]; + memmove(&argv[i], &argv[i + 1], (*argc - i)*sizeof(argv[i])); + argv[*argc]= wnc; /* this will be invisible to the rest of the program */ + } + } +} bool wsrep_start_replication() { @@ -686,20 +771,16 @@ bool wsrep_start_replication() return true; } - /* Note 'bootstrap' address is not officially supported in wsrep API #23 - but it can be back ported from #24 provider to get sneak preview of - bootstrap command - */ - const char* cluster_address = - wsrep_new_cluster ? "bootstrap" : wsrep_cluster_address; + bool const bootstrap(TRUE == wsrep_new_cluster); wsrep_new_cluster= FALSE; WSREP_INFO("Start replication"); if ((rcode = wsrep->connect(wsrep, wsrep_cluster_name, - cluster_address, - wsrep_sst_donor))) + wsrep_cluster_address, + wsrep_sst_donor, + bootstrap))) { if (-ESOCKTNOSUPPORT == rcode) { @@ -720,11 +801,6 @@ bool wsrep_start_replication() { wsrep_connected= TRUE; - uint64_t caps = wsrep->capabilities (wsrep); - - wsrep_incremental_data_collection = - !!(caps & WSREP_CAP_WRITE_SET_INCREMENTS); - char* opts= wsrep->options_get(wsrep); if (opts) { @@ -749,8 +825,8 @@ wsrep_causal_wait (THD* thd) { // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // TODO: modify to check if thd has locked any rows. - wsrep_seqno_t seqno; - wsrep_status_t ret= wsrep->causal_read (wsrep, &seqno); + wsrep_gtid_t gtid; + wsrep_status_t ret= wsrep->causal_read (wsrep, >id); if (unlikely(WSREP_OK != ret)) { @@ -798,7 +874,7 @@ static void wsrep_keys_free(wsrep_key_arr_t* key_arr) { for (size_t i= 0; i < key_arr->keys_len; ++i) { - my_free((wsrep_key_part_t*)key_arr->keys[i].key_parts); + my_free((void*)key_arr->keys[i].key_parts); } my_free(key_arr->keys); key_arr->keys= 0; @@ -818,7 +894,7 @@ static void wsrep_keys_free(wsrep_key_arr_t* key_arr) static bool wsrep_prepare_key_for_isolation(const char* db, const char* table, - wsrep_key_part_t* key, + wsrep_buf_t* key, size_t* key_len) { if (*key_len < 2) return false; @@ -837,13 +913,13 @@ static bool wsrep_prepare_key_for_isolation(const char* db, // sql_print_information("%s.%s", db, table); if (db) { - key[*key_len].buf= db; - key[*key_len].buf_len= strlen(db); + key[*key_len].ptr= db; + key[*key_len].len= strlen(db); ++(*key_len); if (table) { - key[*key_len].buf= table; - key[*key_len].buf_len= strlen(table); + key[*key_len].ptr= table; + key[*key_len].len= strlen(table); ++(*key_len); } } @@ -879,23 +955,23 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd, { if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0)))) { - sql_print_error("Can't allocate memory for key_array"); + WSREP_ERROR("Can't allocate memory for key_array"); goto err; } ka->keys_len= 1; - if (!(ka->keys[0].key_parts= (wsrep_key_part_t*) - my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + if (!(ka->keys[0].key_parts= (wsrep_buf_t*) + my_malloc(sizeof(wsrep_buf_t)*2, MYF(0)))) { - sql_print_error("Can't allocate memory for key_parts"); + WSREP_ERROR("Can't allocate memory for key_parts"); goto err; } - ka->keys[0].key_parts_len= 2; + ka->keys[0].key_parts_num= 2; if (!wsrep_prepare_key_for_isolation( db, table, - (wsrep_key_part_t*)ka->keys[0].key_parts, - &ka->keys[0].key_parts_len)) + (wsrep_buf_t*)ka->keys[0].key_parts, + &ka->keys[0].key_parts_num)) { - sql_print_error("Preparing keys for isolation failed"); + WSREP_ERROR("Preparing keys for isolation failed"); goto err; } } @@ -910,24 +986,24 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd, ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); if (!tmp) { - sql_print_error("Can't allocate memory for key_array"); + WSREP_ERROR("Can't allocate memory for key_array"); goto err; } ka->keys= tmp; - if (!(ka->keys[ka->keys_len].key_parts= (wsrep_key_part_t*) - my_malloc(sizeof(wsrep_key_part_t)*2, MYF(0)))) + if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*) + my_malloc(sizeof(wsrep_buf_t)*2, MYF(0)))) { - sql_print_error("Can't allocate memory for key_parts"); + WSREP_ERROR("Can't allocate memory for key_parts"); goto err; } - ka->keys[ka->keys_len].key_parts_len= 2; + ka->keys[ka->keys_len].key_parts_num= 2; ++ka->keys_len; if (!wsrep_prepare_key_for_isolation( table->db, table->table_name, - (wsrep_key_part_t*)ka->keys[ka->keys_len - 1].key_parts, - &ka->keys[ka->keys_len - 1].key_parts_len)) + (wsrep_buf_t*)ka->keys[ka->keys_len - 1].key_parts, + &ka->keys[ka->keys_len - 1].key_parts_num)) { - sql_print_error("Preparing keys for isolation failed"); + WSREP_ERROR("Preparing keys for isolation failed"); goto err; } } @@ -939,12 +1015,11 @@ err: } - bool wsrep_prepare_key_for_innodb(const uchar* cache_key, - size_t cache_key_len, + size_t cache_key_len, const uchar* row_id, size_t row_id_len, - wsrep_key_part_t* key, + wsrep_buf_t* key, size_t* key_len) { if (*key_len < 3) return false; @@ -954,33 +1029,36 @@ bool wsrep_prepare_key_for_innodb(const uchar* cache_key, { case 0: { - key[*key_len].buf = cache_key; - key[*key_len].buf_len = cache_key_len; - ++(*key_len); + key[0].ptr = cache_key; + key[0].len = cache_key_len; + + *key_len = 1; break; } case 1: case 2: { - key[*key_len].buf = cache_key; - key[*key_len].buf_len = strlen( (char*)cache_key ); - ++(*key_len); - key[*key_len].buf = cache_key + strlen( (char*)cache_key ) + 1; - key[*key_len].buf_len = strlen( (char*)(key[*key_len].buf) ); - ++(*key_len); + key[0].ptr = cache_key; + key[0].len = strlen( (char*)cache_key ); + + key[1].ptr = cache_key + strlen( (char*)cache_key ) + 1; + key[1].len = strlen( (char*)(key[1].ptr) ); + + *key_len = 2; break; } default: return false; } - key[*key_len].buf = row_id; - key[*key_len].buf_len = row_id_len; + key[*key_len].ptr = row_id; + key[*key_len].len = row_id_len; ++(*key_len); return true; } + /* * Construct Query_log_Event from thd query and serialize it * into buffer. @@ -988,7 +1066,7 @@ bool wsrep_prepare_key_for_innodb(const uchar* cache_key, * Return 0 in case of success, 1 in case of error. */ int wsrep_to_buf_helper( - THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len) + THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len) { IO_CACHE tmp_io_cache; if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, @@ -999,9 +1077,9 @@ int wsrep_to_buf_helper( /* if there is prepare query, add event for it */ if (thd->wsrep_TOI_pre_query) { - Query_log_event ev(thd, thd->wsrep_TOI_pre_query, - thd->wsrep_TOI_pre_query_len, - FALSE, FALSE, FALSE, 0); + Query_log_event ev(thd, thd->wsrep_TOI_pre_query, + thd->wsrep_TOI_pre_query_len, + FALSE, FALSE, FALSE, 0); if (ev.write(&tmp_io_cache)) ret= 1; } @@ -1009,7 +1087,7 @@ int wsrep_to_buf_helper( Query_log_event ev(thd, query, query_len, FALSE, FALSE, FALSE, 0); if (ev.write(&tmp_io_cache)) ret= 1; - if (!ret && wsrep_write_cache(&tmp_io_cache, buf, buf_len)) ret= 1; + if (!ret && wsrep_write_cache_buf(&tmp_io_cache, buf, buf_len)) ret= 1; close_cached_file(&tmp_io_cache); return ret; @@ -1017,7 +1095,7 @@ int wsrep_to_buf_helper( #include "sql_show.h" static int -create_view_query(THD *thd, uchar** buf, uint* buf_len) +create_view_query(THD *thd, uchar** buf, size_t* buf_len) { LEX *lex= thd->lex; SELECT_LEX *select_lex= &lex->select_lex; @@ -1036,15 +1114,15 @@ create_view_query(THD *thd, uchar** buf, uint* buf_len) if (!lex->definer) { /* - DEFINER-clause is missing; we have to create default definer in - persistent arena to be PS/SP friendly. - If this is an ALTER VIEW then the current user should be set as - the definer. + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. */ if (!(lex->definer= create_default_definer(thd))) { - WSREP_WARN("view default definer issue"); + WSREP_WARN("view default definer issue"); } } @@ -1071,7 +1149,7 @@ create_view_query(THD *thd, uchar** buf, uint* buf_len) List_iterator_fast names(lex->view_list); LEX_STRING *name; int i; - + for (i= 0; (name= names++); i++) { buff.append(i ? ", " : "("); @@ -1082,7 +1160,7 @@ create_view_query(THD *thd, uchar** buf, uint* buf_len) 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); + 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 @@ -1094,11 +1172,11 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, { wsrep_status_t ret(WSREP_WARNING); uchar* buf(0); - uint buf_len(0); + size_t buf_len(0); int buf_err; - WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode, thd->query() ); + WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_exec_mode, thd->query() ); switch (thd->lex->sql_command) { case SQLCOM_CREATE_VIEW: @@ -1121,19 +1199,20 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, } wsrep_key_arr_t key_arr= {0, 0}; + struct wsrep_buf buff = { buf, buf_len }; if (!buf_err && wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&& WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, key_arr.keys, key_arr.keys_len, - buf, buf_len, - &thd->wsrep_trx_seqno))) + &buff, 1, + &thd->wsrep_trx_meta))) { thd->wsrep_exec_mode= TOTAL_ORDER; wsrep_to_isolation++; if (buf) my_free(buf); wsrep_keys_free(&key_arr); - WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)thd->wsrep_trx_seqno, - thd->wsrep_exec_mode); + WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_exec_mode); } else { /* jump to error handler in mysql_execute_command() */ @@ -1152,10 +1231,11 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, static void wsrep_TOI_end(THD *thd) { wsrep_status_t ret; wsrep_to_isolation--; - WSREP_DEBUG("TO END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + + WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { - WSREP_DEBUG("TO END: %lld", (long long)thd->wsrep_trx_seqno); + WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd)); } else { WSREP_WARN("TO isolation end failed for: %d, sql: %s", @@ -1166,7 +1246,7 @@ static void wsrep_TOI_end(THD *thd) { static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) { wsrep_status_t ret(WSREP_WARNING); - WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, thd->query() ); ret = wsrep->desync(wsrep); @@ -1211,7 +1291,7 @@ static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) static void wsrep_RSU_end(THD *thd) { wsrep_status_t ret(WSREP_WARNING); - WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)thd->wsrep_trx_seqno, + WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, thd->query() ); @@ -1255,13 +1335,27 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, mysql_mutex_unlock(&thd->LOCK_wsrep_thd); DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); - DBUG_ASSERT(thd->wsrep_trx_seqno == WSREP_SEQNO_UNDEFINED); + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); if (wsrep_debug && thd->mdl_context.has_locks()) { WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", thd->query(), thd->thread_id); } + + /* + It makes sense to set auto_increment_* to defaults in TOI operations. + Must be done before wsrep_TOI_begin() since Query_log_event encapsulating + TOI statement and auto inc variables for wsrep replication is constructed + there. Variables are reset back in THD::reset_for_next_command() before + processing of next command. + */ + if (wsrep_auto_increment_control) + { + thd->variables.auto_increment_offset = 1; + thd->variables.auto_increment_increment = 1; + } + if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { @@ -1272,12 +1366,6 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (!ret) { thd->wsrep_exec_mode= TOTAL_ORDER; - /* It makes sense to set auto_increment_* to defaults in TOI operations */ - if (wsrep_auto_increment_control) - { - thd->variables.auto_increment_offset = 1; - thd->variables.auto_increment_increment = 1; - } } } return ret; @@ -1302,10 +1390,10 @@ void wsrep_to_isolation_end(THD *thd) "request: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ "granted: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ msg, \ - req->thread_id, (long long)req->wsrep_trx_seqno, \ + req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \ req->command, req->lex->sql_command, req->query(), \ - gra->thread_id, (long long)gra->wsrep_trx_seqno, \ + gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ gra->command, gra->lex->sql_command, gra->query()); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 619711cc4b0..815990ba9d4 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -1,4 +1,4 @@ -/* Copyright 2008-2012 Codership Oy +/* Copyright 2008-2013 Codership Oy 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 @@ -26,23 +26,22 @@ typedef struct st_mysql_show_var SHOW_VAR; class set_var; class THD; -#ifdef WITH_WSREP -#include "../wsrep/wsrep_api.h" -//#include "wsrep_mysqld.h" - enum wsrep_exec_mode { +enum wsrep_exec_mode { LOCAL_STATE, REPL_RECV, TOTAL_ORDER, LOCAL_COMMIT - }; - enum wsrep_query_state { +}; + +enum wsrep_query_state { QUERY_IDLE, QUERY_EXEC, QUERY_COMMITTING, QUERY_EXITING, QUERY_ROLLINGBACK, - }; - enum wsrep_conflict_state { +}; + +enum wsrep_conflict_state { NO_CONFLICT, MUST_ABORT, ABORTING, @@ -51,13 +50,14 @@ class THD; REPLAYING, RETRY_AUTOCOMMIT, CERT_FAILURE, - }; - enum wsrep_consistency_check_mode { +}; + +enum wsrep_consistency_check_mode { NO_CONSISTENCY_CHECK, CONSISTENCY_CHECK_DECLARED, CONSISTENCY_CHECK_RUNNING, - }; -#endif +}; + // Global wsrep parameters extern wsrep_t* wsrep; @@ -73,20 +73,16 @@ extern const char* wsrep_node_incoming_address; extern const char* wsrep_data_home_dir; extern const char* wsrep_dbug_option; extern long wsrep_slave_threads; -extern my_bool wsrep_debug; +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_sst_method; -extern const char* wsrep_sst_receive_address; -extern char* wsrep_sst_auth; -extern const char* wsrep_sst_donor; -extern my_bool wsrep_sst_donor_rejects_queries; extern const char* wsrep_start_position; -extern long long wsrep_max_ws_size; -extern long wsrep_max_ws_rows; +extern ulong wsrep_max_ws_size; +extern ulong wsrep_max_ws_rows; extern const char* wsrep_notify_cmd; extern my_bool wsrep_certify_nonPK; extern long wsrep_max_protocol_version; @@ -98,7 +94,6 @@ extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; -extern ulong wsrep_mysql_replication_bundle; extern my_bool wsrep_load_data_splitting; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; @@ -111,81 +106,29 @@ extern long long wsrep_cluster_conf_id; extern const char* wsrep_cluster_status; extern long wsrep_cluster_size; extern long wsrep_local_index; +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 int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); -extern void wsrep_free_status(THD *thd); // Other wsrep global variables extern my_bool wsrep_inited; // whether wsrep is initialized ? -#define WSREP_SST_ADDRESS_AUTO "AUTO" -#define WSREP_NODE_INCOMING_AUTO "AUTO" +int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); +void wsrep_free_status(THD *thd); -// MySQL variables funcs - -#define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) -#define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) -#define DEFAULT_ARGS (THD* thd, enum_var_type var_type) -#define INIT_ARGS (const char* opt) - -extern int wsrep_init_vars(); - -extern bool wsrep_on_update UPDATE_ARGS; -extern void wsrep_causal_reads_update UPDATE_ARGS; -extern bool wsrep_start_position_check CHECK_ARGS; -extern bool wsrep_start_position_update UPDATE_ARGS; -extern void wsrep_start_position_init INIT_ARGS; - -extern bool wsrep_provider_check CHECK_ARGS; -extern bool wsrep_provider_update UPDATE_ARGS; -extern void wsrep_provider_init INIT_ARGS; - -extern bool wsrep_provider_options_check CHECK_ARGS; -extern bool wsrep_provider_options_update UPDATE_ARGS; -extern void wsrep_provider_options_init INIT_ARGS; - -extern bool wsrep_cluster_address_check CHECK_ARGS; -extern bool wsrep_cluster_address_update UPDATE_ARGS; -extern void wsrep_cluster_address_init INIT_ARGS; - -extern bool wsrep_cluster_name_check CHECK_ARGS; -extern bool wsrep_cluster_name_update UPDATE_ARGS; - -extern bool wsrep_node_name_check CHECK_ARGS; -extern bool wsrep_node_name_update UPDATE_ARGS; - -extern bool wsrep_node_address_check CHECK_ARGS; -extern bool wsrep_node_address_update UPDATE_ARGS; -extern void wsrep_node_address_init INIT_ARGS; - -extern bool wsrep_sst_method_check CHECK_ARGS; -extern bool wsrep_sst_method_update UPDATE_ARGS; -extern void wsrep_sst_method_init INIT_ARGS; - -extern bool wsrep_sst_receive_address_check CHECK_ARGS; -extern bool wsrep_sst_receive_address_update UPDATE_ARGS; - -extern bool wsrep_sst_auth_check CHECK_ARGS; -extern bool wsrep_sst_auth_update UPDATE_ARGS; -extern void wsrep_sst_auth_init INIT_ARGS; - -extern bool wsrep_sst_donor_check CHECK_ARGS; -extern bool wsrep_sst_donor_update UPDATE_ARGS; - -extern bool wsrep_slave_threads_check CHECK_ARGS; -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_before_SE(); // initialize wsrep before storage - // engines (true) or after (false) -extern int wsrep_init(); -extern void wsrep_deinit(); -extern void wsrep_recover(); +/* 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_init(); +void wsrep_deinit(); +void wsrep_recover(); +bool wsrep_before_SE(); // initialize wsrep before storage + // engines (true) or after (false) +/* wsrep initialization sequence at startup + * @param before wsrep_before_SE() value */ +void wsrep_init_startup(bool before); extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); @@ -194,18 +137,18 @@ extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); extern "C" const char * wsrep_thd_query_state_str(THD *thd); -extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); +extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(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); + THD *thd, enum wsrep_query_state state); extern "C" void wsrep_thd_set_conflict_state( - THD *thd, enum wsrep_conflict_state state); + THD *thd, enum wsrep_conflict_state state); extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); -extern "C"void wsrep_thd_LOCK(THD *thd); -extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" void wsrep_thd_LOCK(THD *thd); +extern "C" void wsrep_thd_UNLOCK(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); extern "C" time_t wsrep_thd_query_start(THD *thd); extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); @@ -217,18 +160,11 @@ extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); - -/* wsrep initialization sequence at startup - * @param first wsrep_before_SE() value */ -extern void wsrep_init_startup(bool before); - extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); extern void wsrep_close_applier(THD *thd); extern void wsrep_wait_appliers_close(THD *thd); extern void wsrep_close_applier_threads(int count); -extern void wsrep_create_appliers(long threads = wsrep_slave_threads); -extern void wsrep_create_rollbacker(); extern void wsrep_kill_mysql(THD *thd); /* new defines */ @@ -285,32 +221,20 @@ extern wsrep_seqno_t wsrep_locked_seqno; 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 (bf_thd) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ } #define WSREP_PROVIDER_EXISTS \ (wsrep_provider && strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN)) -/*! Synchronizes applier thread start with init thread */ -extern void wsrep_sst_grab(); -/*! Init thread waits for SST completion */ -extern bool wsrep_sst_wait(); -/*! Signals wsrep that initialization is complete, writesets can be applied */ -extern void wsrep_sst_continue(); - -extern void wsrep_SE_init_grab(); /*! grab init critical section */ -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 */ - extern void wsrep_ready_wait(); enum wsrep_trx_status { WSREP_TRX_OK, WSREP_TRX_ROLLBACK, WSREP_TRX_ERROR, - }; +}; extern enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all); @@ -318,17 +242,10 @@ class Ha_trx_info; struct THD_TRANS; void wsrep_register_hton(THD* thd, bool all); void wsrep_post_commit(THD* thd, bool all); -void wsrep_replication_process(THD *thd); -void wsrep_rollback_process(THD *thd); void wsrep_brute_force_killer(THD *thd); int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id); + extern "C" bool wsrep_consistency_check(void *thd_ptr); -extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); -extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, - my_bool signal); -extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); -void *wsrep_prepare_bf_thd(THD *thd); -void wsrep_return_from_bf_mode(void *shadow, THD *thd); /* this is visible for client build so that innodb plugin gets this */ typedef struct wsrep_aborting_thd { @@ -337,29 +254,21 @@ typedef struct wsrep_aborting_thd { } *wsrep_aborting_thd_t; extern mysql_mutex_t LOCK_wsrep_ready; -extern mysql_cond_t COND_wsrep_ready; +extern mysql_cond_t COND_wsrep_ready; extern mysql_mutex_t LOCK_wsrep_sst; -extern mysql_cond_t COND_wsrep_sst; +extern mysql_cond_t COND_wsrep_sst; extern mysql_mutex_t LOCK_wsrep_sst_init; -extern mysql_cond_t COND_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 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 wsrep_aborting_thd_t wsrep_aborting_thd; -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_emulate_bin_log; -extern my_bool wsrep_auto_increment_control; -extern my_bool wsrep_drupal_282555_workaround; -extern long long wsrep_max_ws_size; -extern long wsrep_max_ws_rows; -extern int wsrep_to_isolation; -extern my_bool wsrep_certify_nonPK; +extern mysql_cond_t COND_wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_slave_threads; extern mysql_mutex_t LOCK_wsrep_desync; +extern wsrep_aborting_thd_t wsrep_aborting_thd; +extern my_bool wsrep_emulate_bin_log; +extern int wsrep_to_isolation; extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready; @@ -381,13 +290,11 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list); void wsrep_to_isolation_end(THD *thd); void wsrep_cleanup_transaction(THD *thd); -void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow*); -void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow*); int wsrep_to_buf_helper( - THD* thd, const char *query, uint query_len, uchar** buf, uint* buf_len); -int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len); -int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len); -int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len); + THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len); +int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len); const wsrep_uuid_t* wsrep_cluster_uuid(); struct xid_t; diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index ff997d01183..291cdbb7c75 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -15,6 +15,7 @@ #include #include "wsrep_priv.h" +#include "wsrep_utils.h" const char* wsrep_notify_cmd=""; @@ -64,7 +65,7 @@ void wsrep_notify_status (wsrep_member_status_t status, { char uuid_str[40]; - wsrep_uuid_print (&view->uuid, uuid_str, sizeof(uuid_str)); + wsrep_uuid_print (&view->state_id.uuid, uuid_str, sizeof(uuid_str)); cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --uuid %s", uuid_str); diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h index 700639ebcb1..93640fbcc03 100644 --- a/sql/wsrep_priv.h +++ b/sql/wsrep_priv.h @@ -26,208 +26,26 @@ #include #include -extern void wsrep_ready_set (my_bool x); +void wsrep_ready_set (my_bool x); -extern ssize_t wsrep_sst_prepare (void** msg); -extern int wsrep_sst_donate_cb (void* app_ctx, - void* recv_ctx, - const void* msg, size_t msg_len, - const wsrep_uuid_t* current_uuid, - wsrep_seqno_t current_seqno, - const char* state, size_t state_len, - bool bypass); - -extern size_t guess_ip (char* buf, size_t buf_len); -extern size_t guess_address(char* buf, size_t buf_len); +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_gtid_t* state_id, + const char* state, size_t state_len, + bool bypass); extern wsrep_uuid_t local_uuid; extern wsrep_seqno_t local_seqno; +// a helper function +void wsrep_sst_received(wsrep_t*, const wsrep_uuid_t*, wsrep_seqno_t, + const void*, size_t); /*! SST thread signals init thread about sst completion */ -extern void wsrep_sst_complete(const wsrep_uuid_t* uuid, wsrep_seqno_t, bool); +void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool); -extern void wsrep_notify_status (wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0); +void wsrep_notify_status (wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0); -namespace wsp { -class node_status -{ -public: - node_status() : status(WSREP_MEMBER_UNDEFINED) {} - void set(wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0) - { - if (status != new_status || 0 != view) - { - wsrep_notify_status(new_status, view); - status = new_status; - } - } - wsrep_member_status_t get() const { return status; } -private: - wsrep_member_status_t status; -}; -} /* namespace wsp */ - -extern wsp::node_status local_status; - -namespace wsp { -/* A small class to run external programs. */ -class process -{ -private: - const char* const str_; - FILE* io_; - int err_; - pid_t pid_; - -public: -/*! @arg type is a pointer to a null-terminated string which must contain - either the letter 'r' for reading or the letter 'w' for writing. - */ - process (const char* cmd, const char* type); - ~process (); - - FILE* pipe () { return io_; } - int error() { return err_; } - int wait (); - const char* cmd() { return str_; } -}; -#ifdef REMOVED -class lock -{ - pthread_mutex_t* const mtx_; - -public: - - lock (pthread_mutex_t* mtx) : mtx_(mtx) - { - int err = pthread_mutex_lock (mtx_); - - if (err) - { - WSREP_ERROR("Mutex lock failed: %s", strerror(err)); - abort(); - } - } - - virtual ~lock () - { - int err = pthread_mutex_unlock (mtx_); - - if (err) - { - WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); - abort(); - } - } - - inline void wait (pthread_cond_t* cond) - { - pthread_cond_wait (cond, mtx_); - } - -private: - - lock (const lock&); - lock& operator=(const lock&); - -}; - -class monitor -{ - int mutable refcnt; - pthread_mutex_t mutable mtx; - pthread_cond_t mutable cond; - -public: - - monitor() : refcnt(0) - { - pthread_mutex_init (&mtx, NULL); - pthread_cond_init (&cond, NULL); - } - - ~monitor() - { - pthread_mutex_destroy (&mtx); - pthread_cond_destroy (&cond); - } - - void enter() const - { - lock l(&mtx); - - while (refcnt) - { - l.wait(&cond); - } - refcnt++; - } - - void leave() const - { - lock l(&mtx); - - refcnt--; - if (refcnt == 0) - { - pthread_cond_signal (&cond); - } - } - -private: - - monitor (const monitor&); - monitor& operator= (const monitor&); -}; - -class critical -{ - const monitor& mon; - -public: - - critical(const monitor& m) : mon(m) { mon.enter(); } - - ~critical() { mon.leave(); } - -private: - - critical (const critical&); - critical& operator= (const critical&); -}; -#endif - -class thd -{ - class thd_init - { - public: - thd_init() { my_thread_init(); } - ~thd_init() { my_thread_end(); } - } - init; - - thd (const thd&); - thd& operator= (const thd&); - -public: - - thd(my_bool wsrep_on); - ~thd(); - THD* const ptr; -}; - -class string -{ -public: - string() : string_(0) {} - void set(char* str) { if (string_) free (string_); string_ = str; } - ~string() { set (0); } -private: - char* string_; -}; - -} // namespace wsrep #endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 7afdb4909e4..ec636a8b1ec 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -13,6 +13,8 @@ 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_sst.h" + #include #include #include @@ -23,6 +25,7 @@ #include #include #include "wsrep_priv.h" +#include "wsrep_utils.h" #include #include @@ -61,7 +64,6 @@ const char* wsrep_sst_donor = ""; // container for real auth string 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) @@ -214,8 +216,8 @@ bool wsrep_sst_wait () // Signal end of SST void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, - wsrep_seqno_t sst_seqno, - bool needed) + wsrep_seqno_t sst_seqno, + bool needed) { if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); if (!sst_complete) @@ -228,18 +230,37 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, } else { - WSREP_WARN("Nobody is waiting for SST."); + /* 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); } +void wsrep_sst_received (wsrep_t* const wsrep, + const wsrep_uuid_t* const uuid, + wsrep_seqno_t const seqno, + const void* const state, + size_t const state_len) +{ + int const rcode(seqno < 0 ? seqno : 0); + wsrep_gtid_t const state_id = { + *uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno) + }; + wsrep->sst_received(wsrep, &state_id, state, state_len, rcode); +} + // Let applier threads to continue void wsrep_sst_continue () { if (sst_needed) { WSREP_INFO("Signalling provider to continue."); - wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + wsrep_sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); } } @@ -519,7 +540,7 @@ ssize_t wsrep_sst_prepare (void** msg) } else { - ssize_t ret= guess_ip (ip_buf, ip_max); + ssize_t ret= wsrep_guess_ip (ip_buf, ip_max); if (ret && ret < ip_max) { @@ -707,7 +728,9 @@ static int sst_donate_mysqldump (const char* addr, ret= sst_run_shell (cmd_str, 3); } - wsrep->sst_sent (wsrep, uuid, ret ? ret : seqno); + wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)}; + + wsrep->sst_sent (wsrep, &state_id, ret); return ret; } @@ -927,7 +950,10 @@ wait_signal: } // signal to donor that SST is over - wsrep->sst_sent (wsrep, &ret_uuid, err ? -err : ret_seqno); + struct wsrep_gtid const state_id = { + ret_uuid, err ? WSREP_SEQNO_UNDEFINED : ret_seqno + }; + wsrep->sst_sent (wsrep, &state_id, -err); proc.wait(); return NULL; @@ -981,12 +1007,11 @@ static int sst_donate_other (const char* method, return arg.err; } -int wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, - const void* msg, size_t msg_len, - const wsrep_uuid_t* current_uuid, - wsrep_seqno_t current_seqno, - const char* state, size_t state_len, - bool bypass) +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) { /* This will be reset when sync callback is called. * Should we set wsrep_ready to FALSE here too? */ @@ -998,20 +1023,20 @@ int wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, const char* data = method + method_len + 1; char uuid_str[37]; - wsrep_uuid_print (current_uuid, uuid_str, sizeof(uuid_str)); + wsrep_uuid_print (¤t_gtid->uuid, uuid_str, sizeof(uuid_str)); int ret; if (!strcmp (WSREP_SST_MYSQLDUMP, method)) { - ret = sst_donate_mysqldump (data, current_uuid, uuid_str, current_seqno, - bypass); + ret = sst_donate_mysqldump(data, ¤t_gtid->uuid, uuid_str, + current_gtid->seqno, bypass); } else { - ret = sst_donate_other (method, data, uuid_str, current_seqno, bypass); + ret = sst_donate_other(method, data, uuid_str, current_gtid->seqno,bypass); } - return (ret > 0 ? 0 : ret); + return (ret > 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE); } void wsrep_SE_init_grab() @@ -1021,7 +1046,10 @@ void wsrep_SE_init_grab() void wsrep_SE_init_wait() { - mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); + while (SE_initialized == false) + { + mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init); + } mysql_mutex_unlock (&LOCK_wsrep_sst_init); } diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h new file mode 100644 index 00000000000..b7f0e26f226 --- /dev/null +++ b/sql/wsrep_sst.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2013 Codership Oy + + 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_SST_H +#define WSREP_SST_H + +#include // my_bool + +/* system variables */ +extern const char* wsrep_sst_method; +extern const char* wsrep_sst_receive_address; +extern const char* wsrep_sst_donor; +extern char* wsrep_sst_auth; +extern my_bool wsrep_sst_donor_rejects_queries; + +/*! Synchronizes applier thread start with init thread */ +extern void wsrep_sst_grab(); +/*! Init thread waits for SST completion */ +extern bool wsrep_sst_wait(); +/*! Signals wsrep that initialization is complete, writesets can be applied */ +extern void wsrep_sst_continue(); + +extern void wsrep_SE_init_grab(); /*! grab init critical section */ +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 */ + +#endif /* WSREP_SST_H */ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc new file mode 100644 index 00000000000..d9c30e501e6 --- /dev/null +++ b/sql/wsrep_thd.cc @@ -0,0 +1,464 @@ +/* Copyright (C) 2013 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "wsrep_thd.h" + +#include "transaction.h" +#include "rpl_rli.h" +#include "log_event.h" +#include "sql_parse.h" +#include "slave.h" // opt_log_slave_updates +#include "sql_base.h" // close_thread_tables() +#include "mysqld.h" // start_wsrep_THD(); + +static long long wsrep_bf_aborts_counter = 0; + +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff) +{ + wsrep_local_bf_aborts = my_atomic_load64(&wsrep_bf_aborts_counter); + var->type = SHOW_LONGLONG; + var->value = (char*)&wsrep_local_bf_aborts; + return 0; +} + +/* must have (&thd->LOCK_wsrep_thd) */ +void wsrep_client_rollback(THD *thd) +{ + WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", + thd->thread_id, thd->query()); + + my_atomic_add64(&wsrep_bf_aborts_counter, 1); + + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("unlocking tables for BF abort (%ld)", 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 (%ld)", 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 (%ld)", thd->thread_id); + thd->clear_binlog_table_maps(); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; +} + +static Relay_log_info* wsrep_relay_log_init(const char* log_fname) +{ + Relay_log_info* rli= new Relay_log_info(false); + + rli->no_storage= true; + if (!rli->relay_log.description_event_for_exec) + { + rli->relay_log.description_event_for_exec= + new Format_description_log_event(4); + } + + rli->sql_thd= current_thd; + return rli; +} + +static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) +{ + 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; + + if (opt_log_slave_updates) + thd->variables.option_bits|= OPTION_BIN_LOG; + else + thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + if (!thd->wsrep_rli) thd->wsrep_rli= wsrep_relay_log_init("wsrep_relay"); + + 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; + shadow->db_length = thd->db_length; + thd->reset_db(NULL, 0); +} + +static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) +{ + 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->reset_db(shadow->db, shadow->db_length); +} + +void wsrep_replay_transaction(THD *thd) +{ + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) { + if (thd->wsrep_exec_mode!= REPL_RECV) { + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); + + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_reset_thd_for_next_command(thd); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); + + 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_wsrep_thd); + + 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: %ld %llu", + thd->thread_id, (long long)thd->real_id); + if (thd->stmt_da->is_sent) + { + WSREP_WARN("replay ok, thd has reported status"); + } + else if (thd->stmt_da->is_set()) + { + if (thd->stmt_da->status() != Diagnostics_area::DA_OK) + { + WSREP_WARN("replay ok, thd has error status %d", + thd->stmt_da->status()); + } + } + else + { + my_ok(thd); + } + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + + wsrep_cleanup_transaction(thd); + + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + } +} + +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); + /* fall through to node shutdown */ + 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->temporary_tables) + { + WSREP_DEBUG("Applier %lu, has temporary tables at exit", thd->thread_id); + } + wsrep_return_from_bf_mode(thd, &shadow); + DBUG_VOID_RETURN; +} + +void wsrep_create_appliers(long threads) +{ + if (!wsrep_connected) + { + /* 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; + pthread_t hThread; + while (wsrep_threads++ < threads) { + if (pthread_create( + &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_replication_process)) + WSREP_WARN("Can't create thread to manage wsrep replication"); + } +} + +static void wsrep_rollback_process(THD *thd) +{ + 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; + + mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); + + WSREP_DEBUG("WSREP rollback thread wakes for signal"); + + 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); + + /* check for false alarms */ + if (!wsrep_aborting_thd) + { + 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_wsrep_thd); + if (aborting->wsrep_conflict_state== ABORTED) + { + WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", + (long long)aborting->real_id, + aborting->wsrep_conflict_state); + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_rollback); + continue; + } + aborting->wsrep_conflict_state= ABORTING; + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + + aborting->store_globals(); + + mysql_mutex_lock(&aborting->LOCK_wsrep_thd); + wsrep_client_rollback(aborting); + WSREP_DEBUG("WSREP rollbacker aborted thd: (%lu %llu)", + aborting->thread_id, (long long)aborting->real_id); + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + } + } + + mysql_mutex_unlock(&LOCK_wsrep_rollback); + sql_print_information("WSREP: rollbacker thread exiting"); + + DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); + DBUG_VOID_RETURN; +} + +void wsrep_create_rollbacker() +{ + if (wsrep_provider && strcasecmp(wsrep_provider, "none")) + { + pthread_t hThread; + /* create rollbacker */ + if (pthread_create( &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_rollback_process)) + WSREP_WARN("Can't create thread to manage wsrep rollback"); + } +} + +extern "C" +int wsrep_thd_is_brute_force(void *thd_ptr) +{ + /* + Brute force: + Appliers and replaying are running in REPL_RECV mode. TOI statements + in TOTAL_ORDER mode. Locally committing transaction that has got + past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode. + + Everything else is running in LOCAL_STATE and should not be considered + brute force. + */ + if (thd_ptr) { + switch (((THD *)thd_ptr)->wsrep_exec_mode) { + case LOCAL_STATE: return 0; + case REPL_RECV: return 1; + case TOTAL_ORDER: return 2; + case LOCAL_COMMIT: return 3; + } + } + DBUG_ASSERT(0); + return 0; +} + +extern "C" +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"); + + if ( (WSREP(bf_thd) || + ( (WSREP_ON || wsrep_OSU_method_options == WSREP_OSU_RSU) && + bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && + victim_thd) + { + WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? + (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); + ha_wsrep_abort_transaction(bf_thd, victim_thd, signal); + } + else + { + WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); + } + + DBUG_RETURN(1); +} + +extern "C" +int wsrep_thd_in_locking_session(void *thd_ptr) +{ + if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { + return 1; + } + return 0; +} + diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h new file mode 100644 index 00000000000..bded13b5684 --- /dev/null +++ b/sql/wsrep_thd.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2013 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#ifndef WSREP_THD_H +#define WSREP_THD_H + +#include "sql_class.h" + +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff); +void wsrep_client_rollback(THD *thd); +void wsrep_replay_transaction(THD *thd); +void wsrep_create_appliers(long threads); +void wsrep_create_rollbacker(); + +extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); +extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, + my_bool signal); +extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); + +#endif /* WSREP_THD_H */ diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 53d0f7c449e..90af2fb8156 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -14,20 +14,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -//! @file declares symbols private to wsrep integration layer +//! @file some utility functions and classes not directly related to replication #ifndef _GNU_SOURCE #define _GNU_SOURCE // POSIX_SPAWN_USEVFORK flag #endif +#include "wsrep_utils.h" +#include "wsrep_mysqld.h" + +#include + #include // posix_spawn() #include // pipe() #include // errno #include // strerror() #include // waitpid() - -#include -#include "wsrep_priv.h" +#include +#include +#include // getaddrinfo() extern char** environ; // environment variables @@ -313,23 +318,69 @@ thd::~thd () } // namespace wsp -extern ulong my_bind_addr; -extern uint mysqld_port; +/* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */ +unsigned int wsrep_check_ip (const char* const addr) +{ + unsigned int ret = INADDR_NONE; + struct addrinfo *res, hints; -size_t guess_ip (char* buf, size_t buf_len) + memset (&hints, 0, sizeof(hints)); + hints.ai_flags= AI_PASSIVE/*|AI_ADDRCONFIG*/; + hints.ai_socktype= SOCK_STREAM; + hints.ai_family= AF_UNSPEC; + + int gai_ret = getaddrinfo(addr, NULL, &hints, &res); + if (0 == gai_ret) + { + if (AF_INET == res->ai_family) /* IPv4 */ + { + struct sockaddr_in* a= (struct sockaddr_in*)res->ai_addr; + ret= htonl(a->sin_addr.s_addr); + } + else /* IPv6 */ + { + struct sockaddr_in6* a= (struct sockaddr_in6*)res->ai_addr; + if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr)) + ret= INADDR_ANY; + else if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr)) + ret= INADDR_LOOPBACK; + else + ret= 0xdeadbeef; + } + freeaddrinfo (res); + } + else { + WSREP_ERROR ("getaddrinfo() failed on '%s': %d (%s)", + addr, gai_ret, gai_strerror(gai_ret)); + } + + // uint8_t* b= (uint8_t*)&ret; + // fprintf (stderr, "########## wsrep_check_ip returning: %hhu.%hhu.%hhu.%hhu\n", + // b[0], b[1], b[2], b[3]); + + return ret; +} + +extern const char* my_bind_addr_str; +extern uint mysqld_port; + +size_t wsrep_guess_ip (char* buf, size_t buf_len) { size_t ip_len = 0; - if (htonl(INADDR_NONE) == my_bind_addr) { - WSREP_ERROR("Networking not configured, cannot receive state transfer."); - return 0; - } + if (my_bind_addr_str && strlen(my_bind_addr_str)) + { + unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str); - if (htonl(INADDR_ANY) != my_bind_addr) { - uint8_t* b = (uint8_t*)&my_bind_addr; - ip_len = snprintf (buf, buf_len, - "%hhu.%hhu.%hhu.%hhu", b[0],b[1],b[2],b[3]); - return ip_len; + if (INADDR_NONE == ip_type) { + WSREP_ERROR("Networking not configured, cannot receive state transfer."); + return 0; + } + + if (INADDR_ANY != ip_type) {; + strncpy (buf, my_bind_addr_str, buf_len); + return strlen(buf); + } } // mysqld binds to all interfaces - try IP from wsrep_node_address @@ -400,9 +451,9 @@ size_t guess_ip (char* buf, size_t buf_len) return ip_len; } -size_t guess_address(char* buf, size_t buf_len) +size_t wsrep_guess_address(char* buf, size_t buf_len) { - size_t addr_len = guess_ip (buf, buf_len); + size_t addr_len = wsrep_guess_ip (buf, buf_len); if (addr_len && addr_len < buf_len) { addr_len += snprintf (buf + addr_len, buf_len - addr_len, diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h new file mode 100644 index 00000000000..337678238f8 --- /dev/null +++ b/sql/wsrep_utils.h @@ -0,0 +1,208 @@ +/* Copyright (C) 2013 Codership Oy + + 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_UTILS_H +#define WSREP_UTILS_H + +#include "wsrep_priv.h" + +unsigned int wsrep_check_ip (const char* addr); +size_t wsrep_guess_ip (char* buf, size_t buf_len); +size_t wsrep_guess_address(char* buf, size_t buf_len); + +namespace wsp { +class node_status +{ +public: + node_status() : status(WSREP_MEMBER_UNDEFINED) {} + void set(wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0) + { + if (status != new_status || 0 != view) + { + wsrep_notify_status(new_status, view); + status = new_status; + } + } + wsrep_member_status_t get() const { return status; } +private: + wsrep_member_status_t status; +}; +} /* namespace wsp */ + +extern wsp::node_status local_status; + +namespace wsp { +/* A small class to run external programs. */ +class process +{ +private: + const char* const str_; + FILE* io_; + int err_; + pid_t pid_; + +public: +/*! @arg type is a pointer to a null-terminated string which must contain + either the letter 'r' for reading or the letter 'w' for writing. + */ + process (const char* cmd, const char* type); + ~process (); + + FILE* pipe () { return io_; } + int error() { return err_; } + int wait (); + const char* cmd() { return str_; } +}; + +class thd +{ + class thd_init + { + public: + thd_init() { my_thread_init(); } + ~thd_init() { my_thread_end(); } + } + init; + + thd (const thd&); + thd& operator= (const thd&); + +public: + + thd(my_bool wsrep_on); + ~thd(); + THD* const ptr; +}; + +class string +{ +public: + string() : string_(0) {} + void set(char* str) { if (string_) free (string_); string_ = str; } + ~string() { set (0); } +private: + char* string_; +}; + +#ifdef REMOVED +class lock +{ + pthread_mutex_t* const mtx_; + +public: + + lock (pthread_mutex_t* mtx) : mtx_(mtx) + { + int err = pthread_mutex_lock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex lock failed: %s", strerror(err)); + abort(); + } + } + + virtual ~lock () + { + int err = pthread_mutex_unlock (mtx_); + + if (err) + { + WSREP_ERROR("Mutex unlock failed: %s", strerror(err)); + abort(); + } + } + + inline void wait (pthread_cond_t* cond) + { + pthread_cond_wait (cond, mtx_); + } + +private: + + lock (const lock&); + lock& operator=(const lock&); + +}; + +class monitor +{ + int mutable refcnt; + pthread_mutex_t mutable mtx; + pthread_cond_t mutable cond; + +public: + + monitor() : refcnt(0) + { + pthread_mutex_init (&mtx, NULL); + pthread_cond_init (&cond, NULL); + } + + ~monitor() + { + pthread_mutex_destroy (&mtx); + pthread_cond_destroy (&cond); + } + + void enter() const + { + lock l(&mtx); + + while (refcnt) + { + l.wait(&cond); + } + refcnt++; + } + + void leave() const + { + lock l(&mtx); + + refcnt--; + if (refcnt == 0) + { + pthread_cond_signal (&cond); + } + } + +private: + + monitor (const monitor&); + monitor& operator= (const monitor&); +}; + +class critical +{ + const monitor& mon; + +public: + + critical(const monitor& m) : mon(m) { mon.enter(); } + + ~critical() { mon.leave(); } + +private: + + critical (const critical&); + critical& operator= (const critical&); +}; +#endif + +} // namespace wsrep + +#endif /* WSREP_UTILS_H */ diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 5dc9a475e0d..81d436f6116 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -13,12 +13,15 @@ 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_var.h" + #include #include #include #include #include #include "wsrep_priv.h" +#include "wsrep_thd.h" #include #include #include @@ -34,8 +37,7 @@ const char* wsrep_node_name = 0; const char* wsrep_node_address = 0; const char* wsrep_node_incoming_address = 0; const char* wsrep_start_position = 0; -ulong wsrep_OSU_method_options; -static int wsrep_thread_change = 0; +ulong wsrep_OSU_method_options; int wsrep_init_vars() { @@ -58,15 +60,6 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type) // FIXME: this variable probably should be changed only per session thd->variables.wsrep_on = global_system_variables.wsrep_on; } - else { - } - -#ifdef REMOVED - if (thd->variables.wsrep_on) - thd->variables.option_bits |= (OPTION_BIN_LOG); - else - thd->variables.option_bits &= ~(OPTION_BIN_LOG); -#endif return false; } @@ -75,8 +68,6 @@ void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) if (var_type == OPT_GLOBAL) { thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; } - else { - } } static int wsrep_start_position_verify (const char* start_str) @@ -146,7 +137,7 @@ bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) wsrep_set_local_position (wsrep_start_position); if (wsrep) { - wsrep->sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + wsrep_sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); } return 0; @@ -157,7 +148,7 @@ void wsrep_start_position_init (const char* val) if (NULL == val || wsrep_start_position_verify (val)) { WSREP_ERROR("Bad initial value for wsrep_start_position: %s", - (val ? val : "")); + (val ? val : "")); return; } @@ -173,7 +164,7 @@ static bool refresh_provider_options() { if (wsrep_provider_options) my_free((void *)wsrep_provider_options); wsrep_provider_options = (char*)my_memdup(opts, strlen(opts) + 1, - MYF(MY_WME)); + MYF(MY_WME)); } else { @@ -453,7 +444,7 @@ void wsrep_node_address_init (const char* value) bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) { mysql_mutex_lock(&LOCK_wsrep_slave_threads); - wsrep_thread_change = var->value->val_int() - wsrep_slave_threads; + wsrep_slave_count_change = var->value->val_int() - wsrep_slave_threads; mysql_mutex_unlock(&LOCK_wsrep_slave_threads); return 0; @@ -461,13 +452,10 @@ bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) { - if (wsrep_thread_change > 0) + if (wsrep_slave_count_change > 0) { - wsrep_create_appliers(wsrep_thread_change); - } - else if (wsrep_thread_change < 0) - { - wsrep_close_applier_threads(-wsrep_thread_change); + wsrep_create_appliers(wsrep_slave_count_change); + wsrep_slave_count_change = 0; } return false; } diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h new file mode 100644 index 00000000000..b69f670a14b --- /dev/null +++ b/sql/wsrep_var.h @@ -0,0 +1,83 @@ +/* Copyright (C) 2013 Codership Oy + + 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_VAR_H +#define WSREP_VAR_H + +#define WSREP_NODE_INCOMING_AUTO "AUTO" + +// MySQL variables funcs + +#include "sql_priv.h" +class sys_var; +class set_var; +class THD; + +int wsrep_init_vars(); + +#define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) +#define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) +#define DEFAULT_ARGS (THD* thd, enum_var_type var_type) +#define INIT_ARGS (const char* opt) + +extern bool wsrep_on_update UPDATE_ARGS; +extern void wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_start_position_check CHECK_ARGS; +extern bool wsrep_start_position_update UPDATE_ARGS; +extern void wsrep_start_position_init INIT_ARGS; + +extern bool wsrep_provider_check CHECK_ARGS; +extern bool wsrep_provider_update UPDATE_ARGS; +extern void wsrep_provider_init INIT_ARGS; + +extern bool wsrep_provider_options_check CHECK_ARGS; +extern bool wsrep_provider_options_update UPDATE_ARGS; +extern void wsrep_provider_options_init INIT_ARGS; + +extern bool wsrep_cluster_address_check CHECK_ARGS; +extern bool wsrep_cluster_address_update UPDATE_ARGS; +extern void wsrep_cluster_address_init INIT_ARGS; + +extern bool wsrep_cluster_name_check CHECK_ARGS; +extern bool wsrep_cluster_name_update UPDATE_ARGS; + +extern bool wsrep_node_name_check CHECK_ARGS; +extern bool wsrep_node_name_update UPDATE_ARGS; + +extern bool wsrep_node_address_check CHECK_ARGS; +extern bool wsrep_node_address_update UPDATE_ARGS; +extern void wsrep_node_address_init INIT_ARGS; + +extern bool wsrep_sst_method_check CHECK_ARGS; +extern bool wsrep_sst_method_update UPDATE_ARGS; +extern void wsrep_sst_method_init INIT_ARGS; + +extern bool wsrep_sst_receive_address_check CHECK_ARGS; +extern bool wsrep_sst_receive_address_update UPDATE_ARGS; + +extern bool wsrep_sst_auth_check CHECK_ARGS; +extern bool wsrep_sst_auth_update UPDATE_ARGS; +extern void wsrep_sst_auth_init INIT_ARGS; + +extern bool wsrep_sst_donor_check CHECK_ARGS; +extern bool wsrep_sst_donor_update UPDATE_ARGS; + +extern bool wsrep_slave_threads_check CHECK_ARGS; +extern bool wsrep_slave_threads_update UPDATE_ARGS; + +extern bool wsrep_desync_check CHECK_ARGS; +extern bool wsrep_desync_update UPDATE_ARGS; + +#endif /* WSREP_VAR_H */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7cc21ce5a8e..83f559e5161 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -120,9 +120,9 @@ extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; -static inline wsrep_trx_handle_t* -wsrep_trx_handle(THD* thd, const trx_t* trx) { - return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), +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); } @@ -130,7 +130,7 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, size_t cache_key_len, const uchar* row_id, size_t row_id_len, - wsrep_key_part_t* key, + wsrep_buf_t* key, size_t* key_len); extern handlerton * wsrep_hton; @@ -7182,6 +7182,7 @@ wsrep_append_foreign_key( ulint rcode = DB_SUCCESS; char cache_key[513] = {'\0'}; int cache_key_len; + bool const copy = true; if (!wsrep_on(trx->mysql_thd) || wsrep_thd_exec_mode(thd) != LOCAL_STATE) @@ -7308,30 +7309,31 @@ wsrep_append_foreign_key( foreign->foreign_table->name); } - wsrep_key_part_t wkey_part[3]; + wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; if (!wsrep_prepare_key_for_innodb( (const uchar*)cache_key, cache_key_len + 1, (const uchar*)key, len+1, wkey_part, - &wkey.key_parts_len)) { - WSREP_WARN("key prepare failed for cascaded FK: %s", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void"); + &wkey.key_parts_num)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); return DB_ERROR; } rcode = (int)wsrep->append_key( wsrep, - wsrep_trx_handle(thd, trx), + wsrep_ws_handle(thd, trx), &wkey, - 1, - shared); + 1, + shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, + copy); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); - WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void", rcode); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); return DB_ERROR; } @@ -7352,6 +7354,7 @@ wsrep_append_key( ) { DBUG_ENTER("wsrep_append_key"); + bool const copy = true; #ifdef WSREP_DEBUG_PRINT fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", (shared) ? "Shared" : "Exclusive", @@ -7362,52 +7365,37 @@ wsrep_append_key( } fprintf(stderr, "\n"); #endif - wsrep_key_part_t wkey_part[3]; + wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; if (!wsrep_prepare_key_for_innodb( (const uchar*)table_share->table_cache_key.str, table_share->table_cache_key.length, (const uchar*)key, key_len, wkey_part, - &wkey.key_parts_len)) { - WSREP_WARN("key prepare failed for: %s", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void"); + &wkey.key_parts_num)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } int rcode = (int)wsrep->append_key( wsrep, - wsrep_trx_handle(thd, trx), + wsrep_ws_handle(thd, trx), &wkey, 1, - shared); + shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, + copy); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); - WSREP_WARN("Appending row key failed: %s, %d", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void", rcode); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); DBUG_RETURN(rcode); } DBUG_RETURN(0); } -ibool -wsrep_is_cascding_foreign_key_parent( - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index /*!< in: InnoDB index */ -) { - // return referenced_by_foreign_key(); - dict_foreign_t* fk = dict_table_get_referenced_constraint(table, index); - if (fk && - (fk->type & DICT_FOREIGN_ON_UPDATE_CASCADE || - fk->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) - ) { - return TRUE; - } - return FALSE; -} - int ha_innobase::wsrep_append_keys( /*==================*/ @@ -7455,19 +7443,30 @@ ha_innobase::wsrep_append_keys( ut_a(table->s->keys <= 256); uint i; for (i=0; is->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; + 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; keyval0[0] = (char)i; keyval1[0] = (char)i; + if (!tab) { + WSREP_WARN("MySQL-InnoDB key mismatch %s %s", + table->s->table_name.str, + key_info->name); + } if (key_info->flags & HA_NOSAME || - referenced_by_foreign_key()) { + ((tab && + dict_table_get_referenced_constraint(tab, idx)) || + (!tab && referenced_by_foreign_key()))) { + if (key_info->flags & HA_NOSAME || shared) key_appended = true; @@ -12822,7 +12821,7 @@ wsrep_fake_trx_id( trx_id_t trx_id = trx_sys_get_new_trx_id(); mutex_exit(&kernel_mutex); - (void *)wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), trx_id); + (void *)wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id); } #endif /* WITH_WSREP */ diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index bb12eed8c9f..c00fef579b0 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -308,7 +308,7 @@ extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); extern "C" const char * wsrep_thd_query_state_str(THD *thd); -extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); +extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(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( diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 6e762f65679..c500bf44ffa 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1742,7 +1742,7 @@ lock_t* lock_rec_create( /*============*/ #ifdef WITH_WSREP - lock_t* c_lock, /* conflicting lock */ + lock_t* c_lock, /* conflicting lock */ #endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and @@ -1810,7 +1810,7 @@ lock_rec_create( #ifdef WITH_WSREP if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock_t *hash = c_lock->hash; + lock_t *hash = c_lock->hash; lock_t *prev = NULL; while (hash && @@ -1829,7 +1829,7 @@ lock_rec_create( * delayed conflict resolution '...kill_one_trx' was not called, * if victim was waiting for some other lock */ - if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->was_chosen_as_deadlock_victim = TRUE; if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { @@ -1851,8 +1851,8 @@ lock_rec_create( } if (wsrep_debug) fprintf( - stderr, - "WSREP: c_lock canceled %llu\n", + stderr, + "WSREP: c_lock canceled %llu\n", (ulonglong) c_lock->trx->id); /* have to bail out here to avoid lock_set_lock... */ @@ -1865,7 +1865,7 @@ lock_rec_create( #else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); -#endif +#endif /* WITH_WSREP */ if (lock_is_wait_not_by_other(type_mode)) { lock_set_lock_and_trx_wait(lock, trx); @@ -1886,7 +1886,7 @@ enum db_err lock_rec_enqueue_waiting( /*=====================*/ #ifdef WITH_WSREP - lock_t* c_lock, /* conflicting lock */ + lock_t* c_lock, /* conflicting lock */ #endif ulint type_mode,/*!< in: lock mode this transaction is requesting: @@ -2231,7 +2231,7 @@ lock_rec_lock_slow( { trx_t* trx; #ifdef WITH_WSREP - lock_t *c_lock= 0; + lock_t* c_lock = NULL; #endif lock_t* lock; @@ -2281,10 +2281,10 @@ lock_rec_lock_slow( #ifdef WITH_WSREP } else if ((c_lock = lock_rec_other_has_conflicting( - mode, block, heap_no, trx))) { + mode, block, heap_no, trx))) { #else } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { -#endif +#endif /* WITH_WSREP */ /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong @@ -2293,12 +2293,15 @@ lock_rec_lock_slow( ut_ad(lock == NULL); enqueue_waiting: #ifdef WITH_WSREP - return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no, + /* c_lock is NULL here if jump to enqueue_waiting happened + but it's ok because lock is not NULL in that case and c_lock + is not used. */ + return(lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, lock, index, thr)); #else return(lock_rec_enqueue_waiting(mode, block, heap_no, lock, index, thr)); -#endif +#endif /* WITH_WSREP */ } else if (!impl) { /* Set the requested lock on the record */ @@ -3961,7 +3964,8 @@ lock_table_create( if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { if (wsrep_debug) { - fprintf(stderr, "WSREP: table c_lock in wait: %llu new loc: %llu\n", + fprintf(stderr, + "WSREP: table c_lock in wait: %llu new loc: %llu\n", (ulonglong) c_lock->trx->id, lock->trx->id); } @@ -5603,7 +5607,7 @@ lock_rec_insert_check_and_lock( | LOCK_INSERT_INTENTION, block, next_rec_heap_no, NULL, index, thr); -#endif +#endif /* WITH_WSREP */ } else { err = DB_SUCCESS; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 9a40b9eef84..9737843a00b 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -137,9 +137,9 @@ extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; -static inline wsrep_trx_handle_t* -wsrep_trx_handle(THD* thd, const trx_t* trx) { - return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), +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); } @@ -147,7 +147,7 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, size_t cache_key_len, const uchar* row_id, size_t row_id_len, - wsrep_key_part_t* key, + wsrep_buf_t* key, size_t* key_len); extern handlerton * wsrep_hton; @@ -1187,6 +1187,8 @@ innobase_release_temporary_latches( 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 @@ -2729,6 +2731,7 @@ innobase_init( innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; + innobase_hton->wsrep_fake_trx_id=wsrep_fake_trx_id; #endif /* WITH_WSREP */ innobase_hton->kill_query = innobase_kill_query; @@ -8222,6 +8225,7 @@ wsrep_append_foreign_key( ulint rcode = DB_SUCCESS; char cache_key[513] = {'\0'}; int cache_key_len; + bool const copy = true; if (!wsrep_on(trx->mysql_thd) || wsrep_thd_exec_mode(thd) != LOCAL_STATE) @@ -8348,30 +8352,31 @@ wsrep_append_foreign_key( foreign->foreign_table->name); } - wsrep_key_part_t wkey_part[3]; + wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; if (!wsrep_prepare_key_for_innodb( (const uchar*)cache_key, cache_key_len + 1, (const uchar*)key, len+1, wkey_part, - &wkey.key_parts_len)) { - WSREP_WARN("key prepare failed for cascaded FK: %s", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void"); + &wkey.key_parts_num)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); return DB_ERROR; } rcode = (int)wsrep->append_key( wsrep, - wsrep_trx_handle(thd, trx), + wsrep_ws_handle(thd, trx), &wkey, - 1, - shared); + 1, + shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, + copy); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); - WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void", rcode); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); return DB_ERROR; } @@ -8392,6 +8397,7 @@ wsrep_append_key( ) { DBUG_ENTER("wsrep_append_key"); + bool const copy = true; #ifdef WSREP_DEBUG_PRINT fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", (shared) ? "Shared" : "Exclusive", @@ -8402,52 +8408,37 @@ wsrep_append_key( } fprintf(stderr, "\n"); #endif - wsrep_key_part_t wkey_part[3]; + wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; if (!wsrep_prepare_key_for_innodb( (const uchar*)table_share->table_cache_key.str, table_share->table_cache_key.length, (const uchar*)key, key_len, wkey_part, - &wkey.key_parts_len)) { - WSREP_WARN("key prepare failed for: %s", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void"); + &wkey.key_parts_num)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } int rcode = (int)wsrep->append_key( wsrep, - wsrep_trx_handle(thd, trx), + wsrep_ws_handle(thd, trx), &wkey, 1, - shared); + shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, + copy); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); - WSREP_WARN("Appending row key failed: %s, %d", - (wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void", rcode); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); DBUG_RETURN(rcode); } DBUG_RETURN(0); } -ibool -wsrep_is_cascding_foreign_key_parent( - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index /*!< in: InnoDB index */ -) { - // return referenced_by_foreign_key(); - dict_foreign_t* fk = dict_table_get_referenced_constraint(table, index); - if (fk && - (fk->type & DICT_FOREIGN_ON_UPDATE_CASCADE || - fk->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) - ) { - return TRUE; - } - return FALSE; -} - int ha_innobase::wsrep_append_keys( /*==================*/ @@ -8495,19 +8486,30 @@ ha_innobase::wsrep_append_keys( ut_a(table->s->keys <= 256); uint i; for (i=0; is->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; + 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; keyval0[0] = (char)i; keyval1[0] = (char)i; + if (!tab) { + WSREP_WARN("MySQL-InnoDB key mismatch %s %s", + table->s->table_name.str, + key_info->name); + } if (key_info->flags & HA_NOSAME || - referenced_by_foreign_key()) { + ((tab && + dict_table_get_referenced_constraint(tab, idx)) || + (!tab && referenced_by_foreign_key()))) { + if (key_info->flags & HA_NOSAME || shared) key_appended = true; @@ -13877,25 +13879,35 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) This function is used to kill one transaction in BF. */ int wsrep_innobase_kill_one_trx( + void *bf_thd_ptr, /*!< in: BF thd */ trx_t *bf_trx, /*!< in: BF trx */ trx_t *victim_trx, /*!< in: victim trx */ ibool signal, /*!< in: signal to be used */ ibool have_kernel_mutex) /*!mysql_thd; - THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; if (have_kernel_mutex) { ut_ad(mutex_own(&kernel_mutex)); } + if (!bf_thd) bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + if (!thd) { DBUG_PRINT("wsrep", ("no thd for conflicting lock")); WSREP_WARN("no THD for trx: %llu", victim_trx->id); DBUG_RETURN(1); } + if (!bf_thd) { + DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); + WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0); + DBUG_RETURN(1); + } + + WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", signal, (long long)bf_seqno, @@ -14098,8 +14110,8 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { - int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, - signal, FALSE); + int rcode = wsrep_innobase_kill_one_trx( + bf_thd, bf_trx, victim_trx, signal, FALSE); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { @@ -14134,6 +14146,19 @@ static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) return 0; } +static void +wsrep_fake_trx_id( +/*==================*/ + handlerton *hton, + THD *thd) /*!< in: user thread handle */ +{ + mutex_enter(&kernel_mutex); + trx_id_t trx_id = trx_sys_get_new_trx_id(); + mutex_exit(&kernel_mutex); + + (void *)wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id); +} + #endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index b72bc13f945..798be6fb292 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -385,7 +385,10 @@ extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); -extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); +extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); +extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); +extern "C" const char * wsrep_thd_query_state_str(THD *thd); +extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(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( diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 373c4956ca5..7d98401a093 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -301,7 +301,7 @@ thd_flush_log_at_trx_commit( void* thd); #ifdef WITH_WSREP -UNIV_INTERN int wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, +UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx, ibool signal, ibool have_kernel_mutex); int wsrep_thd_is_brute_force(void *thd_ptr); int wsrep_trx_order_before(void *thd1, void *thd2); diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 36188b03cec..12694687180 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -42,6 +42,7 @@ Created 5/7/1996 Heikki Tuuri #ifdef WITH_WSREP extern my_bool wsrep_debug; +extern my_bool wsrep_log_conflicts; #endif /* Restricts the length of search we will do in the waits-for graph of transactions */ @@ -1533,7 +1534,34 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) { /* cannot release lock, until our lock is in the queue*/ } else if (lock->trx != trx) { - wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE, TRUE); + if (wsrep_log_conflicts) { + if (bf_this) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, trx, 3000); + + if (bf_other) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, lock->trx, 3000); + + fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", + stderr); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(stderr, lock); + } else { + lock_table_print(stderr, lock); + } + } + wsrep_innobase_kill_one_trx( + trx->mysql_thd, trx, lock->trx, TRUE, TRUE); } } } @@ -1715,7 +1743,7 @@ lock_t* lock_rec_create( /*============*/ #ifdef WITH_WSREP - lock_t* c_lock, /* conflicting lock */ + lock_t* c_lock, /* conflicting lock */ #endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and @@ -1783,7 +1811,7 @@ lock_rec_create( #ifdef WITH_WSREP if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock_t *hash = c_lock->hash; + lock_t *hash = c_lock->hash; lock_t *prev = NULL; while (hash && @@ -1802,7 +1830,7 @@ lock_rec_create( * delayed conflict resolution '...kill_one_trx' was not called, * if victim was waiting for some other lock */ - if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->was_chosen_as_deadlock_victim = TRUE; if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { @@ -1824,8 +1852,8 @@ lock_rec_create( } if (wsrep_debug) fprintf( - stderr, - "WSREP: c_lock canceled %llu\n", + stderr, + "WSREP: c_lock canceled %llu\n", (ulonglong) c_lock->trx->id); /* have to bail out here to avoid lock_set_lock... */ @@ -1838,8 +1866,7 @@ lock_rec_create( #else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); -#endif - +#endif /* WITH_WSREP */ lock_sys->rec_num++; if (lock_is_wait_not_by_other(type_mode)) { lock_set_lock_and_trx_wait(lock, trx); @@ -1860,7 +1887,7 @@ enum db_err lock_rec_enqueue_waiting( /*=====================*/ #ifdef WITH_WSREP - lock_t* c_lock, /* conflicting lock */ + lock_t* c_lock, /* conflicting lock */ #endif ulint type_mode,/*!< in: lock mode this transaction is requesting: @@ -2211,7 +2238,7 @@ lock_rec_lock_slow( { trx_t* trx; #ifdef WITH_WSREP - lock_t *c_lock= 0; + lock_t* c_lock = NULL; #endif lock_t* lock; @@ -2261,10 +2288,10 @@ lock_rec_lock_slow( #ifdef WITH_WSREP } else if ((c_lock = lock_rec_other_has_conflicting( - mode, block, heap_no, trx))) { + mode, block, heap_no, trx))) { #else } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { -#endif +#endif /* WITH_WSREP */ /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong @@ -2273,12 +2300,15 @@ lock_rec_lock_slow( ut_ad(lock == NULL); enqueue_waiting: #ifdef WITH_WSREP - return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no, + /* c_lock is NULL here if jump to enqueue_waiting happened + but it's ok because lock is not NULL in that case and c_lock + is not used. */ + return(lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, lock, index, thr)); #else return(lock_rec_enqueue_waiting(mode, block, heap_no, lock, index, thr)); -#endif +#endif /* WITH_WSREP */ } else if (!impl) { /* Set the requested lock on the record */ @@ -3944,7 +3974,8 @@ lock_table_create( if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { if (wsrep_debug) { - fprintf(stderr, "WSREP: table c_lock in wait: %llu new loc: %llu\n", + fprintf(stderr, + "WSREP: table c_lock in wait: %llu new loc: %llu\n", (ulonglong) c_lock->trx->id, lock->trx->id); } @@ -4227,33 +4258,12 @@ lock_table_other_has_incompatible( if ((lock->trx != trx) && (!lock_mode_compatible(lock_get_mode(lock), mode)) && (wait || !(lock_get_wait(lock)))) { - #ifdef WITH_WSREP - int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - int bf_other = wsrep_thd_is_brute_force( - lock->trx->mysql_thd); - if ((bf_this && !bf_other) || - (bf_this && bf_other && - wsrep_trx_order_before( - trx->mysql_thd, lock->trx->mysql_thd) - ) - ) { - if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) fprintf(stderr, - "WSREP: BF victim waiting"); - return(lock); - } else { - if (bf_this && bf_other) - wsrep_innobase_kill_one_trx( - (trx_t *)trx, lock->trx, TRUE, TRUE); - return(lock); - } - } else { - return(lock); - } -#else - return(lock); + if (wsrep_debug) + fprintf(stderr, "WSREP: table lock abort"); + wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); #endif + return(lock); } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 8da75c92a6c..c703d576307 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -397,33 +397,6 @@ case "$mode" in fi fi ;; - 'configtest') - # Safeguard (relative paths, core dumps..) - cd $basedir - echo $echo_n "Testing MySQL configuration syntax" - daemon=$bindir/mysqld - if test -x $libexecdir/mysqld - then - daemon=$libexecdir/mysqld - elif test -x $sbindir/mysqld - then - daemon=$sbindir/mysqld - elif test -x `which mysqld` - then - daemon=`which mysqld` - else - log_failure_msg "Unable to locate the mysqld binary!" - exit 1 - fi - help_out=`$daemon --help 2>&1`; r=$? - if test "$r" != 0 ; then - log_failure_msg "$help_out" - log_failure_msg "There are syntax errors in the server configuration. Please fix them!" - else - log_success_msg "Syntax OK" - fi - exit $r - ;; 'bootstrap') # Bootstrap the cluster, start the first node # that initiate the cluster @@ -433,7 +406,7 @@ case "$mode" in *) # usage basename=`basename "$0"` - echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest|bootstrap} [ MySQL server options ]" + echo "Usage: $basename {start|stop|restart|reload|force-reload|status|bootstrap} [ MySQL server options ]" exit 1 ;; esac diff --git a/wsrep/Makefile.am b/wsrep/Makefile.am index 40e4b501e86..a748ece92e9 100644 --- a/wsrep/Makefile.am +++ b/wsrep/Makefile.am @@ -1,2 +1,7 @@ noinst_LIBRARIES = libwsrep.a -libwsrep_a_SOURCES = wsrep_api.h wsrep_loader.c wsrep_dummy.c wsrep_uuid.c +libwsrep_a_SOURCES = wsrep_api.h wsrep_loader.c wsrep_dummy.c wsrep_uuid.c wsrep_gtid.c +noinst_PROGRAMS = wsrep_listener +wsrep_listener_SOURCES = wsrep_listener.c +wsrep_listener_LDADD = $(noinst_LIBRARIES) +wsrep_listener_LDFLAGS = -static -ldl + diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index 2cd10afc7ff..f713de66d57 100644 --- a/wsrep/wsrep_api.h +++ b/wsrep/wsrep_api.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2011 Codership Oy +/* Copyright (C) 2009-2013 Codership Oy 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 @@ -9,11 +9,41 @@ 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 + 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 @@ -27,55 +57,17 @@ extern "C" { #endif -/*! - * wsrep replication API - */ +/************************************************************************** + * * + * wsrep replication API * + * * + **************************************************************************/ -#define WSREP_INTERFACE_VERSION "23" +#define WSREP_INTERFACE_VERSION "25" -/*! - * Certain provider capabilities application may need to know - */ -#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_WRITE_SET_INCREMENTS ( 1ULL << 8 ) -#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) -#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) -#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) - -/*! - * Write set replication flags - */ -#define WSREP_FLAG_PA_SAFE ( 1ULL << 0 ) - -/* Empty backend spec */ +/*! Empty backend spec */ #define WSREP_NONE "none" -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. - -/*! undefined seqno */ -#define WSREP_SEQNO_UNDEFINED (-1) - -/*! wsrep 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_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; /*! * @brief log severity levels, passed as first argument to log handler @@ -92,7 +84,7 @@ typedef enum wsrep_log_level /*! * @brief error log handler * - * All messages from wsrep library are directed to this + * All messages from wsrep provider are directed to this * handler, if present. * * @param level log level @@ -100,33 +92,160 @@ typedef enum wsrep_log_level */ 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. +typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool + +/*! 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 uuid[16]; + 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 ssize_t +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 ssize_t +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 */ @@ -163,15 +282,14 @@ typedef enum wsrep_view_status { * view of the group */ typedef struct wsrep_view_info { - wsrep_uuid_t uuid; //!< global state UUID - wsrep_seqno_t seqno; //!< global state seqno + wsrep_gtid_t state_id; //!< global state ID wsrep_seqno_t view; //!< global view number wsrep_view_status_t status; //!< view status - bool state_gap; //!< gap between global and local states + 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 in the view - wsrep_member_info_t members[1]; //!< array of member information + int proto_ver; //!< application protocol agreed on the view + wsrep_member_info_t members[1];//!< array of member information } wsrep_view_info_t; /*! @@ -208,37 +326,45 @@ typedef struct wsrep_view_info { * @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 + * @param sst_req_len location to store SST request length or error code, * value of 0 means no SST. */ -typedef void (*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, - ssize_t* sst_req_len); +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 write set + * 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 write set + * @param data data buffer containing the writeset * @param size data buffer size - * @param seqno global seqno part of the write set to be applied + * @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 write set format - * @retval WSREP_ERROR failed to apply the write set + * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format + * @retval WSREP_ERROR failed to apply the writeset */ -typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, - const void* data, - size_t size, - wsrep_seqno_t seqno); +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 @@ -246,16 +372,40 @@ typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, * This handler is called to commit the changes made by apply callback. * * @param recv_ctx receiver context pointer provided by the application - * @param seqno global seqno part of the write set to be committed + * @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_status (*wsrep_commit_cb_t) (void* recv_ctx, - wsrep_seqno_t seqno, - bool commit); +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 @@ -270,22 +420,22 @@ typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, * @param recv_ctx receiver context * @param msg state transfer request message * @param msg_len state transfer request message length - * @param uuid current state uuid on this node - * @param seqno current state seqno on this node + * @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 - * @return 0 for success or negative error code */ -typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, - void* recv_ctx, - const void* msg, - size_t msg_len, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len, - bool bypass); +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 @@ -296,11 +446,11 @@ typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, * * @param app_ctx application context */ -typedef void (*wsrep_synced_cb_t)(void* app_ctx); +typedef void (*wsrep_synced_cb_t) (void* app_ctx); /*! - * Initialization parameters for wsrep, used as arguments for wsrep_init() + * Initialization parameters for wsrep provider. */ struct wsrep_init_args { @@ -315,24 +465,25 @@ struct wsrep_init_args int proto_ver; //!< Max supported application protocol version /* Application initial state information. */ - const wsrep_uuid_t* state_uuid; //!< Application state sequence UUID - wsrep_seqno_t state_seqno; //!< Applicaiton state sequence number - const char* state; //!< Initial state for wsrep implementation + 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 */ + /* 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 */ + /* 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 { @@ -355,60 +506,94 @@ struct wsrep_stats_var }; -/*! Key part structure */ -typedef struct wsrep_key_part_ +/*! Abstract data buffer structure */ +typedef struct wsrep_buf { - const void* buf; /*!< Buffer containing key part data */ - size_t buf_len; /*!< Length of buffer */ -} wsrep_key_part_t; + 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_ +typedef struct wsrep_key { - const wsrep_key_part_t* key_parts; /*!< Array of key parts */ - size_t key_parts_len; /*!< Length of key parts array */ + 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_trx_handle_ +typedef struct wsrep_ws_handle { wsrep_trx_id_t trx_id; //!< transaction ID void* opaque; //!< opaque provider transaction context data -} wsrep_trx_handle_t; +} wsrep_ws_handle_t; /*! - * @brief Helper method to reset trx handle state when trx id changes + * @brief Helper method to reset trx writeset handle state when trx id changes * - * Instead of passing wsrep_trx_handle_t directly for wsrep calls, + * Instead of passing wsrep_ws_handle_t directly to wsrep calls, * wrapping handle with this call offloads bookkeeping from * application. */ -static inline wsrep_trx_handle_t* wsrep_trx_handle_for_id( - wsrep_trx_handle_t* trx_handle, - wsrep_trx_id_t trx_id) +static inline wsrep_ws_handle_t* wsrep_ws_handle_for_trx( + wsrep_ws_handle_t* ws_handle, + wsrep_trx_id_t trx_id) { - if (trx_handle->trx_id != trx_id) + if (ws_handle->trx_id != trx_id) { - trx_handle->trx_id = trx_id; - trx_handle->opaque = NULL; + ws_handle->trx_id = trx_id; + ws_handle->opaque = NULL; } - return trx_handle; + return ws_handle; } -typedef struct wsrep_ wsrep_t; +/*! + * 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_ { +struct wsrep { const char *version; //!< interface version string /*! * @brief Initializes wsrep provider * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param args wsrep initialization parameters */ wsrep_status_t (*init) (wsrep_t* wsrep, @@ -417,14 +602,14 @@ struct wsrep_ { /*! * @brief Returns provider capabilities flag bitmap * - * @param wsrep this wsrep handle + * @param wsrep provider handle */ uint64_t (*capabilities) (wsrep_t* wsrep); /*! * @brief Passes provider-specific configuration string to provider. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conf configuration string * * @retval WSREP_OK configuration string was parsed successfully @@ -435,7 +620,7 @@ struct wsrep_ { /*! * @brief Returns provider-specific string with current configuration values. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * * @return a dynamically allocated string with current configuration * parameter values @@ -448,15 +633,20 @@ struct wsrep_ { * Returns when either node is ready to operate as a part of the clsuter * or fails to reach operating status. * - * @param wsrep this wsrep handle + * @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_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. @@ -473,7 +663,7 @@ struct wsrep_ { * * This function never returns * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param recv_ctx receiver context */ wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx); @@ -487,59 +677,55 @@ struct wsrep_ { * In case of WSREP_OK, starts commit critical section, transaction can * commit. Otherwise transaction must rollback. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @param conn_id connection ID - * @param app_data application specific applying data - * @param data_len the size of the applying data * @param flags fine tuning the replication WSREP_FLAG_* - * @param seqno seqno part of the global transaction ID + * @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_trx_handle_t* trx_handle, - const void* app_data, - size_t data_len, - uint64_t flags, - wsrep_seqno_t* seqno); + 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 this wsrep handle - * @param trx_handle transaction which is committing + * @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_trx_handle_t* trx_handle); + wsrep_ws_handle_t* ws_handle); /*! * @brief Releases resources after transaction rollback. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @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_trx_handle_t* trx_handle); + wsrep_ws_handle_t* ws_handle); /*! - * @brief Replay trx as a slave write set + * @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 write sets and certification + * 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 this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @param trx_ctx transaction context * * @retval WSREP_OK cluster commit succeeded @@ -550,7 +736,7 @@ struct wsrep_ { * @retval WSREP_NODE_FAIL must close all connections and reinit */ wsrep_status_t (*replay_trx)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, + wsrep_ws_handle_t* ws_handle, void* trx_ctx); /*! @@ -562,76 +748,72 @@ struct wsrep_ { * The kill routine checks that abort is not attmpted against a transaction * which is front of the caller (in total order). * - * @param wsrep this wsrep handle + * @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 + * @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 query in transaction's write set + * @brief Appends a row reference to transaction writeset * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param query SQL statement string - * @param timeval time to use for time functions - * @param randseed seed for rand - */ - wsrep_status_t (*append_query)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const char* query, - time_t timeval, - uint32_t randseed); - - /*! - * @brief Appends a row reference in transaction's write set + * Both copy flag and key_type can be ignored by provider (key type + * interpreted as WSREP_KEY_EXCLUSIVE). * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param key array of keys - * @param key_len length of the array of keys - * @param shared boolean denoting if key corresponds to shared resource + * @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_trx_handle_t* trx_handle, - const wsrep_key_t* key, - size_t key_len, - bool shared); - /*! - * @brief Appends data in transaction's write set - * - * This method can be called any time before commit and it - * appends data block into transaction's write set. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param data data buffer - * @param data_len data buffer length - */ - wsrep_status_t (*append_data)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const void* data, - size_t data_len); + 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 - * seqno is non-null, the call stores the global transaction ID + * 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 this wsrep handle - * @param seqno location to store global transaction ID + * @param wsrep provider handle + * @param gtid location to store GTID */ - wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_seqno_t* seqno); + wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid); /*! * @brief Clears allocated connection context. @@ -641,7 +823,7 @@ struct wsrep_ { * connection. This call is to explicitly notify provider fo connection * closing. * - * @param wsrep this wsrep handle + * @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) @@ -652,29 +834,28 @@ struct wsrep_ { /*! * @brief Replicates a query and starts "total order isolation" section. * - * Replicates the query and returns success code, which - * caller must check. Total order isolation continues - * until to_execute_end() is called. + * Replicates the action spec and returns success code, which caller must + * check. Total order isolation continues until to_execute_end() is called. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conn_id connection ID - * @param key array of keys - * @param key_len lenght of the array of keys - * @param query query to be executed - * @param query_len length of the query string - * @param seqno seqno part of the action 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* key, - size_t key_len, - const void* query, - size_t query_len, - wsrep_seqno_t* seqno); + 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. @@ -682,7 +863,7 @@ struct wsrep_ { * Marks the end of total order isolation. TO locks are freed * and other transactions are free to commit from this point on. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conn_id connection ID * * @retval WSREP_OK cluster commit succeeded @@ -691,33 +872,82 @@ struct wsrep_ { */ 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 this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation + * @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_uuid_t* uuid, - wsrep_seqno_t seqno); + 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 this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation + * @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_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len); + const wsrep_gtid_t* state_id, + const void* state, + size_t state_len, + int rcode); /*! @@ -729,9 +959,9 @@ struct wsrep_ { * called only locally. This call will block until sst_sent is called * from callback. * - * @param wsrep this wsrep handle - * @param msg context message for SST donate callback - * @param msg_len length of context message + * @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, @@ -743,7 +973,7 @@ struct wsrep_ { * @brief Returns an array fo status variables. * Array is terminated by Null variable name. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @return array of struct wsrep_status_var. */ struct wsrep_stats_var* (*stats_get) (wsrep_t* wsrep); @@ -751,10 +981,18 @@ struct wsrep_ { /*! * @brief Release resources that might be associated with the array. * - * @param wsrep this wsrep handle. + * @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. * @@ -786,28 +1024,30 @@ struct wsrep_ { /*! * @brief Acquire global named lock * - * @param wsrep wsrep provider handle - * @param name lock name - * @param owner 64-bit owner ID - * @param tout timeout in nanoseconds. - * 0 - return immediately, -1 wait forever. - * @return wsrep status or negative error code + * @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, int64_t owner, - int64_t tout); + 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 + * @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, int64_t owner); + wsrep_status_t (*unlock) (wsrep_t* wsrep, const char* name, uint64_t owner); /*! * @brief Check if global named lock is locked @@ -818,8 +1058,8 @@ struct wsrep_ { * @param node if not NULL will contain owner's node UUID * @return true if lock is locked */ - bool (*is_locked) (wsrep_t* wsrep, const char* name, int64_t* conn, - wsrep_uuid_t* node); + wsrep_bool_t (*is_locked) (wsrep_t* wsrep, const char* name, uint64_t* conn, + wsrep_uuid_t* node); /*! * wsrep provider name @@ -838,7 +1078,7 @@ struct wsrep_ { /*! * @brief Frees allocated resources before unloading the library. - * @param wsrep this wsrep handle + * @param wsrep provider handle */ void (*free)(wsrep_t* wsrep); @@ -846,7 +1086,6 @@ struct wsrep_ { void *ctx; //!< reserved for implemetation private context }; -typedef int (*wsrep_loader_fun)(wsrep_t*); /*! * diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index 6d01ce14b4e..3c7a7c2e354 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -16,10 +16,11 @@ /*! @file Dummy wsrep API implementation. */ -#include - #include "wsrep_api.h" +#include +#include + /*! Dummy backend context. */ typedef struct wsrep_dummy { @@ -74,9 +75,10 @@ static char* dummy_options_get (wsrep_t* w) static wsrep_status_t dummy_connect( wsrep_t* w, - const char* name __attribute__((unused)), - const char* url __attribute__((unused)), - const char* donor __attribute__((unused))) + 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; @@ -97,12 +99,10 @@ static wsrep_status_t dummy_recv(wsrep_t* w, static wsrep_status_t dummy_pre_commit( wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused)), - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - uint64_t flags __attribute__((unused)), - wsrep_seqno_t* seqno __attribute__((unused))) + 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; @@ -110,7 +110,7 @@ static wsrep_status_t dummy_pre_commit( static wsrep_status_t dummy_post_commit( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -118,7 +118,7 @@ static wsrep_status_t dummy_post_commit( static wsrep_status_t dummy_post_rollback( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -126,7 +126,7 @@ static wsrep_status_t dummy_post_rollback( static wsrep_status_t dummy_replay_trx( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), + wsrep_ws_handle_t* ws_handle __attribute__((unused)), void* trx_ctx __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -142,23 +142,13 @@ static wsrep_status_t dummy_abort_pre_commit( return WSREP_OK; } -static wsrep_status_t dummy_append_query( +static wsrep_status_t dummy_append_key( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const char* query __attribute__((unused)), - const time_t timeval __attribute__((unused)), - const uint32_t randseed __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_row_key( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const wsrep_key_t* key __attribute__((unused)), - const size_t key_len __attribute__((unused)), - const bool shared __attribute__((unused))) + 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 bool copy __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -166,9 +156,11 @@ static wsrep_status_t dummy_append_row_key( static wsrep_status_t dummy_append_data( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const void* data __attribute__((unused)), - size_t data_len __attribute__((unused))) + 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 bool copy __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -176,7 +168,7 @@ static wsrep_status_t dummy_append_data( static wsrep_status_t dummy_causal_read( wsrep_t* w, - wsrep_seqno_t* seqno __attribute__((unused))) + wsrep_gtid_t* gtid __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -192,12 +184,12 @@ static wsrep_status_t dummy_free_connection( 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_len __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - wsrep_seqno_t* seqno __attribute__((unused))) + 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; @@ -211,10 +203,33 @@ static wsrep_status_t dummy_to_execute_end( 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_uuid_t* uuid __attribute__((unused)), - wsrep_seqno_t seqno __attribute__((unused))) + const wsrep_gtid_t* state_id __attribute__((unused)), + const int rcode __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -222,10 +237,10 @@ static wsrep_status_t dummy_sst_sent( static wsrep_status_t dummy_sst_received( wsrep_t* w, - const wsrep_uuid_t* uuid __attribute__((unused)), - const wsrep_seqno_t seqno __attribute__((unused)), - const char* state __attribute__((unused)), - const size_t state_len __attribute__((unused))) + 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; @@ -258,6 +273,11 @@ static void dummy_stats_free ( 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); @@ -284,7 +304,8 @@ static wsrep_status_t dummy_resync (wsrep_t* w) static wsrep_status_t dummy_lock (wsrep_t* w, const char* s __attribute__((unused)), - int64_t o __attribute__((unused)), + bool r __attribute__((unused)), + uint64_t o __attribute__((unused)), int64_t t __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -293,7 +314,7 @@ static wsrep_status_t dummy_lock (wsrep_t* w, static wsrep_status_t dummy_unlock (wsrep_t* w, const char* s __attribute__((unused)), - int64_t o __attribute__((unused))) + uint64_t o __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -301,7 +322,7 @@ static wsrep_status_t dummy_unlock (wsrep_t* w, static bool dummy_is_locked (wsrep_t* w, const char* s __attribute__((unused)), - int64_t* o __attribute__((unused)), + uint64_t* o __attribute__((unused)), wsrep_uuid_t* t __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -322,18 +343,20 @@ static wsrep_t dummy_iface = { &dummy_post_rollback, &dummy_replay_trx, &dummy_abort_pre_commit, - &dummy_append_query, - &dummy_append_row_key, + &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, diff --git a/wsrep/wsrep_gtid.c b/wsrep/wsrep_gtid.c new file mode 100644 index 00000000000..e618c5ab7d0 --- /dev/null +++ b/wsrep/wsrep_gtid.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2013 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Helper functions to deal with GTID string representations */ + +#include +#include +#include +#include + +#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 index b4460658f80..8ae6ea962ec 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep/wsrep_loader.c @@ -70,15 +70,18 @@ static int verify(const wsrep_t *wh, const char *iface_ver) VERIFY(wh->post_rollback); VERIFY(wh->replay_trx); VERIFY(wh->abort_pre_commit); - VERIFY(wh->append_query); 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); @@ -93,6 +96,7 @@ static int verify(const wsrep_t *wh, const char *iface_ver) return 0; } +typedef int (*wsrep_loader_fun)(wsrep_t*); static wsrep_loader_fun wsrep_dlf(void *dlh, const char *sym) { @@ -175,7 +179,7 @@ out: *hptr = NULL; } else { snprintf (msg, msg_len, - "wsrep_load(): %s %s by %s loaded succesfully.", + "wsrep_load(): %s %s by %s loaded successfully.", (*hptr)->provider_name, (*hptr)->provider_version, (*hptr)->provider_vendor); logger (WSREP_LOG_INFO, msg); diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c index c99240cc071..baa95b2578a 100644 --- a/wsrep/wsrep_uuid.c +++ b/wsrep/wsrep_uuid.c @@ -26,25 +26,31 @@ * Read UUID from string * @return length of UUID string representation or -EINVAL in case of error */ -ssize_t +int wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) { - size_t uuid_len = 0; - size_t uuid_offt = 0; + unsigned int uuid_len = 0; + unsigned int uuid_offt = 0; while (uuid_len + 1 < str_len) { - if ((4 == uuid_offt || 6 == uuid_offt || 8 == uuid_offt || - 10 == uuid_offt) && str[uuid_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 - sscanf (str + uuid_len, "%2hhx", uuid->uuid + uuid_offt); + // 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->uuid) == uuid_offt) + if (sizeof (uuid->data) == uuid_offt) return uuid_len; } else { @@ -61,11 +67,11 @@ wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) * @return length of UUID string representation or -EMSGSIZE if string is too * short */ -ssize_t +int wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) { if (str_len > 36) { - const unsigned char* u = uuid->uuid; + 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], @@ -75,4 +81,3 @@ wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) return -EMSGSIZE; } } - From 9d5c3731be1395bd19329443e680db11545bb5c4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 9 Jan 2014 23:22:10 -0500 Subject: [PATCH 113/294] Fixes for some compiler warnings. --- sql/mdl.cc | 2 +- sql/wsrep_applier.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mdl.cc b/sql/mdl.cc index 268a6621f65..b35a9a08e09 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -3030,7 +3030,7 @@ void MDL_ticket::wsrep_report(bool debug) { if (debug) { - WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s", + WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)", (get_type() == MDL_INTENTION_EXCLUSIVE) ? "intention exclusive" : ((get_type() == MDL_SHARED) ? "shared" : ((get_type() == MDL_SHARED_HIGH_PRIO ? "shared high prio" : diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index f1016dff902..8e9e8b5ca8d 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -100,7 +100,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, if (!ev) { - WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", + WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %zu", (long long)wsrep_thd_trx_seqno(thd), buf_len); rcode= 1; goto error; From d2c72da610074afe95959094a11f95b29a741f29 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 23 Jan 2014 15:57:47 -0500 Subject: [PATCH 114/294] The bzr revision visible in @@version_comment should represent the last merged revision from codership branch and not the revision of the MGC tree itself. Fixed by adding a cmake variable to hold the revision number of last merged revision from codership branch. --- cmake/wsrep.cmake | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 91b3524c199..849da4e555d 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -20,24 +20,15 @@ # Set the patch version SET(WSREP_PATCH_VERSION "9") -# Obtain patch revision number: -# The script tries to probe the bzr revision number using $ENV{WSREP_REV}, and -# "bzr revno" if the WSREP_REV is not defined. In case both fail, the revision -# information is not appended to the wsrep patch version. +# MariaDB addition: Revision number of the last revision merged from +# codership branch visible in @@visible_comment. +# Branch : codership-mysql/5.5 +SET(WSREP_PATCH_REVNO "3932") # Should be updated on every merge. -# 1: $ENV{WSREP_REV} -SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) - -# 2: bzr revno -IF(NOT WSREP_PATCH_REVNO) - EXECUTE_PROCESS( - COMMAND bzr revno - OUTPUT_VARIABLE WSREP_PATCH_REVNO - RESULT_VARIABLE RESULT - ) - -STRING(REGEX REPLACE "(\r?\n)+$" "" WSREP_PATCH_REVNO "${WSREP_PATCH_REVNO}") -#FILE(WRITE "wsrep_config" "Debug: WSREP_PATCH_REVNO result: ${RESULT}\n") +# MariaDB: Obtain patch revision number: +# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. +IF (DEFINED ENV{WSREP_REV}) + SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) ENDIF() # Obtain wsrep API version From 30b6b39d0b388dc13cbb75aabc539409f19e2f0f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 30 Jan 2014 19:08:00 -0500 Subject: [PATCH 115/294] Updating test result. --- mysql-test/r/mysql_tzinfo_to_sql_symlink.result | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result index 6b3b378e642..1ff20da5b65 100644 --- a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result @@ -27,6 +27,7 @@ Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid in ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # Silent run +SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -50,6 +51,7 @@ ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # # Testing with explicit timezonefile # +SET SESSION wsrep_replicate_myisam=ON; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); @@ -59,5 +61,6 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, # # Testing --leap # +SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone_leap_second; ALTER TABLE time_zone_leap_second ORDER BY Transition_time; From 7ca53d947959fe420c28400c621f427b3008fe19 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 3 Feb 2014 22:55:46 -0500 Subject: [PATCH 116/294] Merging revisions 3934..3944 from codership-mysql/5.5. --- sql/mysqld.cc | 57 +++++++-------------------- sql/mysqld.h | 4 -- sql/sql_connect.cc | 14 +------ sql/sql_parse.cc | 4 -- sql/wsrep_hton.cc | 9 ++++- sql/wsrep_mysqld.cc | 7 ++++ sql/wsrep_var.cc | 9 +++++ storage/innobase/handler/ha_innodb.cc | 14 ++++++- storage/innobase/lock/lock0lock.c | 57 ++++++++++++++++++++++++++- 9 files changed, 105 insertions(+), 70 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4d20dde3610..98d006f8649 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2542,11 +2542,7 @@ static void network_init(void) @note For the connection that is doing shutdown, this is called twice */ -#ifdef WITH_WSREP -void close_connection(THD *thd, uint sql_errno, bool lock) -#else void close_connection(THD *thd, uint sql_errno) -#endif { DBUG_ENTER("close_connection"); @@ -2752,7 +2748,11 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) unlink_thd(thd); /* Mark that current_thd is not valid anymore */ my_pthread_setspecific_ptr(THR_THD, 0); +#ifdef WITH_WSREP + if (put_in_cache && !thd->wsrep_applier) +#else if (put_in_cache) +#endif /* WITH_WSREP */ { mysql_mutex_lock(&LOCK_thread_count); put_in_cache= cache_thread(); @@ -4836,7 +4836,7 @@ pthread_handler_t start_wsrep_THD(void *arg) 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, 1); + close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); @@ -4859,7 +4859,7 @@ pthread_handler_t start_wsrep_THD(void *arg) thd->thread_stack= (char*) &thd; if (thd->store_globals()) { - close_connection(thd, ER_OUT_OF_RESOURCES, 1); + close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); delete thd; @@ -4888,10 +4888,11 @@ pthread_handler_t start_wsrep_THD(void *arg) processor(thd); - close_connection(thd, 0, 1); + 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_signal(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); @@ -4911,6 +4912,7 @@ pthread_handler_t start_wsrep_THD(void *arg) // at server shutdown } +#if 0 if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { mysql_mutex_lock(&LOCK_thread_count); @@ -4918,6 +4920,8 @@ pthread_handler_t start_wsrep_THD(void *arg) thread_count--; mysql_mutex_unlock(&LOCK_thread_count); } +#endif + my_thread_end(); return(NULL); } @@ -4997,23 +5001,6 @@ static bool have_client_connections() return false; } -/* - returns the number of wsrep appliers running. - However, the caller (thd parameter) is not taken in account - */ -static int have_wsrep_appliers(THD *thd) -{ - int ret= 0; - THD *tmp; - - I_List_iterator it(threads); - while ((tmp=it++)) - { - ret+= (tmp != thd && tmp->wsrep_applier); - } - return ret; -} - static void wsrep_close_thread(THD *thd) { thd->killed= KILL_CONNECTION; @@ -5124,7 +5111,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) !is_replaying_connection(tmp)) { WSREP_INFO("killing local connection: %ld",tmp->thread_id); - close_connection(tmp,0,0); + close_connection(tmp,0); } #endif } @@ -5199,7 +5186,7 @@ void wsrep_wait_appliers_close(THD *thd) { /* Wait for wsrep appliers to gracefully exit */ mysql_mutex_lock(&LOCK_thread_count); - while (have_wsrep_appliers(thd) > 1) + 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. @@ -5219,7 +5206,7 @@ void wsrep_wait_appliers_close(THD *thd) wsrep_close_threads (thd); /* and wait for them to die */ mysql_mutex_lock(&LOCK_thread_count); - while (have_wsrep_appliers(thd) > 0) + while (wsrep_running_threads > 0) { if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { @@ -6221,11 +6208,7 @@ void create_thread_to_handle_connection(THD *thd) my_snprintf(error_message_buff, sizeof(error_message_buff), ER_THD(thd, ER_CANT_CREATE_THREAD), error); net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES ,0); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif /* WITH_WSREP */ mysql_mutex_lock(&LOCK_thread_count); delete thd; mysql_mutex_unlock(&LOCK_thread_count); @@ -6268,11 +6251,7 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); DBUG_PRINT("error",("Too many connections")); - #ifdef WITH_WSREP - close_connection(thd, ER_CON_COUNT_ERROR, 1); -#else close_connection(thd, ER_CON_COUNT_ERROR); -#endif /* WITH_WSREP */ statistic_increment(denied_connections, &LOCK_status); delete thd; DBUG_VOID_RETURN; @@ -6658,11 +6637,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || my_net_init(&thd->net, thd->net.vio)) { -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES, 1); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif delete thd; continue; } @@ -6857,11 +6832,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) event_conn_closed)) || my_net_init(&thd->net, thd->net.vio)) { -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES, 1); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif errmsg= 0; goto errorconn; } diff --git a/sql/mysqld.h b/sql/mysqld.h index f392452f56e..99d01c76e0d 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -53,11 +53,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ some places */ /* Function prototypes */ void kill_mysql(void); -#ifdef WITH_WSREP -void close_connection(THD *thd, uint sql_errno= 0, bool lock=1); -#else void close_connection(THD *thd, uint sql_errno= 0); -#endif void handle_connection_in_main_thread(THD *thd); void create_thread_to_handle_connection(THD *thd); void unlink_thd(THD *thd); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index c350334b46c..07290af8f4f 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -993,11 +993,7 @@ bool setup_connection_thread_globals(THD *thd) { if (thd->store_globals()) { -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES, 1); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return 1; // Error @@ -1239,11 +1235,7 @@ void do_handle_one_connection(THD *thd_arg) if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) { -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES, 1); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return; @@ -1302,16 +1294,12 @@ void do_handle_one_connection(THD *thd_arg) } #endif end_thread: -#ifdef WITH_WSREP - close_connection(thd, 0, 1); -#else close_connection(thd); -#endif if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); - if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0)) return; // Probably no-threads /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c091d526220..45581e6a9c3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -622,11 +622,7 @@ void do_handle_bootstrap(THD *thd) if (my_thread_init() || thd->store_globals()) { #ifndef EMBEDDED_LIBRARY -#ifdef WITH_WSREP - close_connection(thd, ER_OUT_OF_RESOURCES, 1); -#else close_connection(thd, ER_OUT_OF_RESOURCES); -#endif /* WITH_WSREP */ #endif thd->fatal_error(); goto end; diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 8eb5340dd58..be60d997265 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -77,8 +77,13 @@ void wsrep_register_hton(THD* thd, bool all) { trans_register_ha(thd, all, wsrep_hton); - /* follow innodb read/write settting */ - if (i->is_trx_read_write()) + /* 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->wsrep_exec_mode == LOCAL_STATE)) { thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 666952e6f52..9b204172f3e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1337,6 +1337,13 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); + if (thd->global_read_lock.can_acquire_protection()) + { + WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lu", + thd->query(), thd->thread_id); + return -1; + } + if (wsrep_debug && thd->mdl_context.has_locks()) { WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 81d436f6116..319c5fca979 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -331,7 +331,16 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) bool 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. + + Note: releasing LOCK_global_system_variables may cause race condition, if + there can be several concurrent clients changing wsrep_provider + */ + mysql_mutex_unlock(&LOCK_global_system_variables); wsrep_stop_replication(thd); + mysql_mutex_lock(&LOCK_global_system_variables); if (wsrep_start_replication()) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 152883a3e4c..0cf6f10c143 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3469,6 +3469,9 @@ ha_innobase::max_supported_key_length() const is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ #ifdef WITH_WSREP + /* this may look like obsolete code, but this ifdef is here + just to make sure we will see bzr merge conflict, if Oracle + changes max key length */ return(3500); #else return(3500); @@ -4617,7 +4620,7 @@ wsrep_innobase_mysql_sort( tmp_length = charset->coll->strnxfrm(charset, str, str_length, tmp_str, str_length); - DBUG_ASSERT(tmp_length == str_length); + DBUG_ASSERT(tmp_length <= str_length); break; } @@ -7443,6 +7446,13 @@ ha_innobase::wsrep_append_keys( } else { ut_a(table->s->keys <= 256); uint i; + bool hasPK= false; + + for (i=0; is->keys && !hasPK; ++i) { + KEY* key_info = table->key_info + i; + if (key_info->flags & HA_NOSAME) hasPK = true; + } + for (i=0; is->keys; ++i) { uint len; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -7463,7 +7473,7 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } - if (key_info->flags & HA_NOSAME || + if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index c500bf44ffa..71b3097d012 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -909,6 +909,9 @@ UNIV_INLINE ibool lock_rec_has_to_wait( /*=================*/ +#ifdef WITH_WSREP + ibool for_locking, /*!< is caller locking or releasing */ +#endif /* WITH_WSREP */ const trx_t* trx, /*!< in: trx of new lock */ ulint type_mode,/*!< in: precise mode of the new lock to set: LOCK_S or LOCK_X, possibly @@ -983,6 +986,44 @@ lock_rec_has_to_wait( return(FALSE); } +#ifdef WITH_WSREP + /* if BF thread is locking and has conflict with another BF + thread, we need to look at trx ordering and lock types */ + if (for_locking && + wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { + + if (wsrep_debug) { + fprintf(stderr, "\n BF-BF lock conflict \n"); + lock_rec_print(stderr, lock2); + } + + if (wsrep_trx_order_before(trx->mysql_thd, + lock2->trx->mysql_thd) && + (type_mode & LOCK_MODE_MASK) == LOCK_X && + (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) + { + /* exclusive lock conflicts are not accepted */ + fprintf(stderr, "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else { + /* if lock2->index->n_uniq <= + lock2->index->n_user_defined_cols + operation is on uniq index + */ + if (wsrep_debug) fprintf(stderr, + "BF conflict, modes: %lu %lu, " + "idx: %s-%s n_uniq %u n_user %u\n", + type_mode, lock2->type_mode, + lock2->index->name, + lock2->index->table_name, + lock2->index->n_uniq, + lock2->index->n_user_defined_cols); + return FALSE; + } + } +#endif /* WITH_WSREP */ return(TRUE); } @@ -1013,7 +1054,11 @@ lock_has_to_wait( /* If this lock request is for a supremum record then the second bit on the lock bitmap is set */ +#ifdef WITH_WSREP + return(lock_rec_has_to_wait(FALSE, lock1->trx, +#else return(lock_rec_has_to_wait(lock1->trx, +#endif /* WITH_WSREP */ lock1->type_mode, lock2, lock_rec_get_nth_bit( lock1, 1))); @@ -1592,7 +1637,11 @@ lock_rec_other_has_conflicting( if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { do { - if (lock_rec_has_to_wait(trx, mode, lock, +#ifdef WITH_WSREP + if (lock_rec_has_to_wait(TRUE, trx, mode, lock, +#else + if (lock_rec_has_to_wait(trx, mode, lock, +#endif /* WITH_WSREP */ TRUE)) { #ifdef WITH_WSREP wsrep_kill_victim(trx, lock); @@ -1605,7 +1654,11 @@ lock_rec_other_has_conflicting( } else { do { - if (lock_rec_has_to_wait(trx, mode, lock, +#ifdef WITH_WSREP + if (lock_rec_has_to_wait(TRUE, trx, mode, lock, +#else + if (lock_rec_has_to_wait(trx, mode, lock, +#endif /* WITH_WSREP */ FALSE)) { #ifdef WITH_WSREP wsrep_kill_victim(trx, lock); From 4cb029b38b914751926c472a3a944fc0e84533be Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 5 Feb 2014 00:28:11 -0500 Subject: [PATCH 117/294] * Merged the missing revision 3934 from codership-mysql/5.5 (missed in the last merge). * Merged changes from Innodb to xtradb. * Updated WSREP_PATCH_REVNO --- cmake/wsrep.cmake | 2 +- include/thr_lock.h | 2 +- mysys/thr_lock.c | 206 ++++++++++++----------- sql/mdl.cc | 8 +- sql/sql_base.cc | 2 +- sql/sql_parse.cc | 2 +- sql/wsrep_mysqld.cc | 2 +- sql/wsrep_thd.cc | 64 ++++--- sql/wsrep_thd.h | 4 +- storage/innobase/handler/ha_innodb.cc | 3 +- storage/innobase/include/ha_prototypes.h | 3 +- storage/innobase/include/lock0lock.h | 1 - storage/innobase/lock/lock0lock.c | 69 +++----- storage/innobase/row/row0ins.c | 22 --- storage/innobase/row/row0upd.c | 6 + storage/innobase/srv/srv0srv.c | 6 +- storage/xtradb/handler/ha_innodb.cc | 17 +- storage/xtradb/include/ha_prototypes.h | 3 +- storage/xtradb/include/lock0lock.h | 1 - storage/xtradb/lock/lock0lock.c | 126 ++++++++------ storage/xtradb/row/row0ins.c | 23 +-- storage/xtradb/row/row0upd.c | 6 + storage/xtradb/srv/srv0srv.c | 6 +- 23 files changed, 294 insertions(+), 290 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 849da4e555d..391cf505313 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "9") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "3932") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "3944") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. diff --git a/include/thr_lock.h b/include/thr_lock.h index 4551a3160ff..f05db666da9 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -22,7 +22,7 @@ extern "C" { #endif #ifdef WITH_WSREP #include - typedef int (* wsrep_thd_is_brute_force_fun)(void *); + 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 *); void wsrep_thr_lock_init( diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 7c10b0abe8c..914990551b0 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -662,8 +662,111 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, DBUG_RETURN(result); } +#ifdef WITH_WSREP +/* + * If brute force applier would need to wait for a thr lock, + * it needs to make sure that it will get the lock without (too much) + * delay. + * We identify here the owners of blocking locks and ask them to + * abort. We then put our lock request in the first place in the + * wait queue. When lock holders abort (one by one) the lock release + * algorithm should grant the lock to us. We rely on this and proceed + * to wait_for_locks(). + * wsrep_break_locks() should be called in all the cases, where lock + * wait would happen. + * + * TODO: current implementation might not cover all possible lock wait + * situations. This needs an review still. + * TODO: lock release, might favor some other lock (instead our bf). + * This needs an condition to check for bf locks first. + * TODO: we still have a debug fprintf, this should be removed + */ +static inline my_bool +wsrep_break_lock( + THR_LOCK_DATA *data, struct st_lock_list *lock_queue1, + struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue) +{ + if (wsrep_on(data->owner->mysql_thd) && + wsrep_thd_is_brute_force && + wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE)) + { + THR_LOCK_DATA *holder; -static enum enum_thr_lock_result + /* if locking session conversion to transaction has been enabled, + we know that this conflicting lock must be read lock and furthermore, + lock holder is read-only. It is safe to wait for him. + */ +#ifdef TODO + if (wsrep_convert_LOCK_to_trx && + (THD*)(data->owner->mysql_thd)->in_lock_tables) + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n"); + return FALSE; + } +#endif + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n"); + + /* aborting lock holder(s) here */ + for (holder=(lock_queue1) ? lock_queue1->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + for (holder=(lock_queue2) ? lock_queue2->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + + /* Add our lock to the head of the wait queue */ + if (*(wait_queue->last)==wait_queue->data) + { + wait_queue->last=&data->next; + assert(wait_queue->data==0); + } + else + { + assert(wait_queue->data!=0); + wait_queue->data->prev=&data->next; + } + data->next=wait_queue->data; + data->prev=&wait_queue->data; + wait_queue->data=data; + data->cond=get_cond(); + + statistic_increment(locks_immediate,&THR_LOCK_lock); + return TRUE; + } + return FALSE; +} +#endif + +static + enum enum_thr_lock_result thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) { THR_LOCK *lock=data->lock; @@ -1164,108 +1267,7 @@ static void sort_locks(THR_LOCK_DATA **data,uint count) } } -#ifdef WITH_WSREP -/* - * If brute force applier would need to wait for a thr lock, - * it needs to make sure that it will get the lock without (too much) - * delay. - * We identify here the owners of blocking locks and ask them to - * abort. We then put our lock request in the first place in the - * wait queue. When lock holders abort (one by one) the lock release - * algorithm should grant the lock to us. We rely on this and proceed - * to wait_for_locks(). - * wsrep_break_locks() should be called in all the cases, where lock - * wait would happen. - * - * TODO: current implementation might not cover all possible lock wait - * situations. This needs an review still. - * TODO: lock release, might favor some other lock (instead our bf). - * This needs an condition to check for bf locks first. - * TODO: we still have a debug fprintf, this should be removed - */ -static inline my_bool -wsrep_break_lock( - THR_LOCK_DATA *data, struct st_lock_list *lock_queue1, - struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue) -{ - if (wsrep_on(data->owner->mysql_thd) && - wsrep_thd_is_brute_force && - wsrep_thd_is_brute_force(data->owner->mysql_thd)) - { - THR_LOCK_DATA *holder; - /* if locking session conversion to transaction has been enabled, - we know that this conflicting lock must be read lock and furthermore, - lock holder is read-only. It is safe to wait for him. - */ -#ifdef TODO - if (wsrep_convert_LOCK_to_trx && - (THD*)(data->owner->mysql_thd)->in_lock_tables) - { - if (wsrep_debug) - fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n"); - return FALSE; - } -#endif - if (wsrep_debug) - fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n"); - - /* aborting lock holder(s) here */ - for (holder=(lock_queue1) ? lock_queue1->data : NULL; - holder; - holder=holder->next) - { - if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) - { - wsrep_abort_thd(data->owner->mysql_thd, - holder->owner->mysql_thd, FALSE); - } - else - { - if (wsrep_debug) - fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); - return FALSE; - } - } - for (holder=(lock_queue2) ? lock_queue2->data : NULL; - holder; - holder=holder->next) - { - if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) - { - wsrep_abort_thd(data->owner->mysql_thd, - holder->owner->mysql_thd, FALSE); - } - else - { - if (wsrep_debug) - fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); - return FALSE; - } - } - - /* Add our lock to the head of the wait queue */ - if (*(wait_queue->last)==wait_queue->data) - { - wait_queue->last=&data->next; - assert(wait_queue->data==0); - } - else - { - assert(wait_queue->data!=0); - wait_queue->data->prev=&data->next; - } - data->next=wait_queue->data; - data->prev=&wait_queue->data; - wait_queue->data=data; - data->cond=get_cond(); - - statistic_increment(locks_immediate,&THR_LOCK_lock); - return TRUE; - } - return FALSE; -} -#endif enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, diff --git a/sql/mdl.cc b/sql/mdl.cc index b35a9a08e09..56f005d0eeb 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1267,7 +1267,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) DBUG_ASSERT(ticket->get_lock()); #ifdef WITH_WSREP if ((this == &(ticket->get_lock()->m_waiting)) && - wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->get_thd()))) + wsrep_thd_is_BF((void *)(ticket->get_ctx()->get_thd()), false)) { Ticket_iterator itw(ticket->get_lock()->m_waiting); Ticket_iterator itg(ticket->get_lock()->m_granted); @@ -1278,7 +1278,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) while ((waiting= itw++) && !added) { - if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->get_thd()))) + if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->get_thd()), true)) { WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", wsrep_thd_thread_id(waiting->get_ctx()->get_thd()), @@ -1669,7 +1669,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, ticket->is_incompatible_when_granted(type_arg)) #ifdef WITH_WSREP { - if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) && key.mdl_namespace() == MDL_key::GLOBAL) { WSREP_DEBUG("global lock granted for BF: %lu %s", @@ -1710,7 +1710,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, #ifdef WITH_WSREP else { - if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) && key.mdl_namespace() == MDL_key::GLOBAL) { WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b2a22152149..9eb88e90b6b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9386,7 +9386,7 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, #ifdef WITH_WSREP { signalled|= mysql_lock_abort_for_thread(thd, thd_table); - if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd)) + if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true)) { WSREP_DEBUG("remove_table_from_cache: %llu", (unsigned long long) thd->real_id); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 45581e6a9c3..52de2659a9f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7254,7 +7254,7 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal) #ifdef WITH_WSREP if (((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) && - !wsrep_thd_is_brute_force((void *)tmp)) + !wsrep_thd_is_BF((void *)tmp, true)) #else if ((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9b204172f3e..708409a40f9 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -642,7 +642,7 @@ void wsrep_init_startup (bool first) { if (wsrep_init()) unireg_abort(1); - wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd, + wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd, wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); /* Skip replication start if no cluster address */ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index d9c30e501e6..3fed6db6d0d 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -406,27 +406,51 @@ void wsrep_create_rollbacker() } extern "C" -int wsrep_thd_is_brute_force(void *thd_ptr) -{ - /* - Brute force: - Appliers and replaying are running in REPL_RECV mode. TOI statements - in TOTAL_ORDER mode. Locally committing transaction that has got - past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode. - - Everything else is running in LOCAL_STATE and should not be considered - brute force. - */ - if (thd_ptr) { - switch (((THD *)thd_ptr)->wsrep_exec_mode) { - case LOCAL_STATE: return 0; - case REPL_RECV: return 1; - case TOTAL_ORDER: return 2; - case LOCAL_COMMIT: return 3; - } +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync) +{ + my_bool status = FALSE; + if (thd_ptr) + { + THD* thd = (THD*)thd_ptr; + if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + status = ((thd->wsrep_exec_mode == REPL_RECV) || + (thd->wsrep_exec_mode == TOTAL_ORDER)); + if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } - DBUG_ASSERT(0); - return 0; + return status; +} + +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_wsrep_thd); + + 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_wsrep_thd); + } + return status; +} + +extern "C" +my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) +{ + bool status = FALSE; + if (thd_ptr) + { + THD* thd = (THD*)thd_ptr; + if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + status = (thd->wsrep_exec_mode == LOCAL_STATE); + if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + return status; } extern "C" diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index bded13b5684..74e3bff120c 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -24,7 +24,9 @@ void wsrep_replay_transaction(THD *thd); void wsrep_create_appliers(long threads); void wsrep_create_rollbacker(); -extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); +extern "C" my_bool wsrep_thd_is_BF(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_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal); extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0cf6f10c143..f4b437e7668 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12566,8 +12566,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) (long long)bf_seqno, (long long)victim_seqno); abort(); } -/*******************************************************************//** -This function is used to kill one transaction in BF. */ + int wsrep_innobase_kill_one_trx( void *bf_thd_ptr, /*!< in: BF thd */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 4ed11d8e410..7b6774fd53b 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -288,7 +288,8 @@ thd_set_lock_wait_time( #ifdef WITH_WSREP UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx, ibool signal, ibool have_kernel_mutex); -int wsrep_thd_is_brute_force(void *thd_ptr); +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +//int64_t wsrep_thd_trx_seqno(THD *thd); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length); diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index e2033470c3c..237e43b7882 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -799,7 +799,6 @@ lock_rec_get_page_no( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 71b3097d012..98cb239befc 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -932,11 +932,6 @@ lock_rec_has_to_wait( if (trx != lock2->trx && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, lock_get_mode(lock2))) { -#ifdef WITH_WSREP - if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { - return FALSE; - } -#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1565,9 +1560,8 @@ lock_rec_other_has_expl_req( #ifdef WITH_WSREP static void wsrep_kill_victim(trx_t *trx, lock_t *lock) { - int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - int bf_other = - wsrep_thd_is_brute_force(lock->trx->mysql_thd); + my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); if ((bf_this && !bf_other) || (bf_this && bf_other && wsrep_trx_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { @@ -1842,11 +1836,6 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock->type_mode |= WSREP_BF; - } -#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1862,13 +1851,15 @@ lock_rec_create( lock_rec_set_nth_bit(lock, heap_no); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = c_lock->hash; lock_t *prev = NULL; while (hash && - wsrep_thd_is_brute_force(hash->trx->mysql_thd) && - wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){ + wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) && + wsrep_trx_order_before( + hash->trx->mysql_thd, trx->mysql_thd)) + { prev = hash; hash = hash->hash; } @@ -2208,11 +2199,6 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL);); @@ -2297,11 +2283,6 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2400,17 +2381,7 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { - mode |= WSREP_BF; - } -#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3845,11 +3816,11 @@ lock_deadlock_recursive( #ifdef WITH_WSREP if (wsrep_debug) fputs("WSREP: Deadlock detected\n", stderr); - if (wsrep_thd_is_brute_force(start->mysql_thd) && - wsrep_thd_is_brute_force( - wait_lock->trx->mysql_thd) && - (start != wait_lock->trx)) { - + if ((start != wait_lock->trx) && + wsrep_thd_is_BF(start->mysql_thd, TRUE) && + wsrep_thd_is_BF( + wait_lock->trx->mysql_thd, TRUE)) + { if (wsrep_trx_order_before( start->mysql_thd, wait_lock->trx->mysql_thd)) { @@ -3870,8 +3841,9 @@ lock_deadlock_recursive( back it */ #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force( - start->mysql_thd)) { + if (!wsrep_thd_is_BF( + start->mysql_thd, FALSE)) + { return(LOCK_VICTIM_IS_START); } #else @@ -3879,8 +3851,9 @@ lock_deadlock_recursive( #endif } #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force( - wait_lock->trx->mysql_thd)) { + if (wsrep_thd_is_BF( + wait_lock->trx->mysql_thd, TRUE)) + { return(LOCK_VICTIM_IS_START); } #endif @@ -4008,7 +3981,7 @@ lock_table_create( lock->un_member.tab_lock.table = table; #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( un_member.tab_lock.locks, table->locks, c_lock, lock); } else { @@ -5641,7 +5614,7 @@ lock_rec_insert_check_and_lock( #ifdef WITH_WSREP if ((c_lock = lock_rec_other_has_conflicting( - LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF, + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, trx))) { #else if (lock_rec_other_has_conflicting( @@ -5745,7 +5718,7 @@ lock_rec_convert_impl_to_expl( if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) #ifdef WITH_WSREP - && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE) /* BF-BF conflict is possible if advancing into lock_rec_other_has_conflicting*/ #endif /* WITH_WSREP */ diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 758a1ed5189..67cc68738a9 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1682,9 +1682,6 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { -#ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr); -#endif ulint n_unique; ulint i; int cmp; @@ -1748,15 +1745,8 @@ row_ins_scan_sec_index_for_duplicate( } else { lock_type = LOCK_ORDINARY; } -#ifdef WITH_WSREP - /* slave applier must not get duplicate error */ - if (allow_duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (allow_duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1872,13 +1862,7 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1922,13 +1906,7 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 186be33d2bd..bcb5837198b 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -370,6 +370,12 @@ wsrep_row_upd_check_foreign_constraints( } trx = thr_get_trx(thr); + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + + return(DB_SUCCESS); + } + + /* TODO: make native slave thread bail out here */ rec = btr_pcur_get_rec(pcur); ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index c231e697c3d..ff69ed4a386 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1214,7 +1214,7 @@ srv_conc_enter_innodb( #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { srv_conc_force_enter_innodb(trx); return; } @@ -1844,7 +1844,7 @@ srv_suspend_mysql_thread( #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, TRUE)) { fprintf(stderr, "WSREP: BF long lock wait ended after %.f sec\n", wait_time); @@ -2421,7 +2421,7 @@ wsrep_is_BF_lock_timeout( srv_slot_t* slot) /* in: lock slot to check for lock priority */ { if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && - wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + wsrep_thd_is_BF((thr_get_trx(slot->thr))->mysql_thd, TRUE)) { fprintf(stderr, "WSREP: BF lock wait long\n"); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 322a5b722e6..696a426cdd2 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4172,6 +4172,9 @@ ha_innobase::max_supported_key_length() const is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ #ifdef WITH_WSREP + /* this may look like obsolete code, but this ifdef is here + just to make sure we will see bzr merge conflict, if Oracle + changes max key length */ return(3500); #else return(3500); @@ -5335,7 +5338,7 @@ wsrep_innobase_mysql_sort( tmp_length = charset->coll->strnxfrm(charset, str, str_length, tmp_str, str_length); - DBUG_ASSERT(tmp_length == str_length); + DBUG_ASSERT(tmp_length <= str_length); break; } @@ -8486,6 +8489,13 @@ ha_innobase::wsrep_append_keys( } else { ut_a(table->s->keys <= 256); uint i; + bool hasPK= false; + + for (i=0; is->keys && !hasPK; ++i) { + KEY* key_info = table->key_info + i; + if (key_info->flags & HA_NOSAME) hasPK = true; + } + for (i=0; is->keys; ++i) { uint len; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -8506,7 +8516,7 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } - if (key_info->flags & HA_NOSAME || + if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { @@ -13891,8 +13901,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) (long long)bf_seqno, (long long)victim_seqno); abort(); } -/*******************************************************************//** -This function is used to kill one transaction in BF. */ + int wsrep_innobase_kill_one_trx( void *bf_thd_ptr, /*!< in: BF thd */ diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 7d98401a093..cff6478570f 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -303,7 +303,8 @@ thd_flush_log_at_trx_commit( #ifdef WITH_WSREP UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx, ibool signal, ibool have_kernel_mutex); -int wsrep_thd_is_brute_force(void *thd_ptr); +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +//int64_t wsrep_thd_trx_seqno(THD *thd); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length); diff --git a/storage/xtradb/include/lock0lock.h b/storage/xtradb/include/lock0lock.h index 7a0b000bcfe..0d6d45c5ad4 100644 --- a/storage/xtradb/include/lock0lock.h +++ b/storage/xtradb/include/lock0lock.h @@ -800,7 +800,6 @@ lock_rec_get_page_no( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 12694687180..35196559595 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -910,6 +910,9 @@ UNIV_INLINE ibool lock_rec_has_to_wait( /*=================*/ +#ifdef WITH_WSREP + ibool for_locking, /*!< is caller locking or releasing */ +#endif /* WITH_WSREP */ const trx_t* trx, /*!< in: trx of new lock */ ulint type_mode,/*!< in: precise mode of the new lock to set: LOCK_S or LOCK_X, possibly @@ -930,11 +933,6 @@ lock_rec_has_to_wait( if (trx != lock2->trx && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, lock_get_mode(lock2))) { -#ifdef WITH_WSREP - if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { - return FALSE; - } -#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -984,6 +982,44 @@ lock_rec_has_to_wait( return(FALSE); } +#ifdef WITH_WSREP + /* if BF thread is locking and has conflict with another BF + thread, we need to look at trx ordering and lock types */ + if (for_locking && + wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { + + if (wsrep_debug) { + fprintf(stderr, "\n BF-BF lock conflict \n"); + lock_rec_print(stderr, lock2); + } + + if (wsrep_trx_order_before(trx->mysql_thd, + lock2->trx->mysql_thd) && + (type_mode & LOCK_MODE_MASK) == LOCK_X && + (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) + { + /* exclusive lock conflicts are not accepted */ + fprintf(stderr, "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else { + /* if lock2->index->n_uniq <= + lock2->index->n_user_defined_cols + operation is on uniq index + */ + if (wsrep_debug) fprintf(stderr, + "BF conflict, modes: %lu %lu, " + "idx: %s-%s n_uniq %u n_user %u\n", + type_mode, lock2->type_mode, + lock2->index->name, + lock2->index->table_name, + lock2->index->n_uniq, + lock2->index->n_user_defined_cols); + return FALSE; + } + } +#endif /* WITH_WSREP */ return(TRUE); } @@ -1014,7 +1050,11 @@ lock_has_to_wait( /* If this lock request is for a supremum record then the second bit on the lock bitmap is set */ +#ifdef WITH_WSREP + return(lock_rec_has_to_wait(FALSE, lock1->trx, +#else return(lock_rec_has_to_wait(lock1->trx, +#endif /* WITH_WSREP */ lock1->type_mode, lock2, lock_rec_get_nth_bit( lock1, 1))); @@ -1521,9 +1561,8 @@ lock_rec_other_has_expl_req( #ifdef WITH_WSREP static void wsrep_kill_victim(trx_t *trx, lock_t *lock) { - int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - int bf_other = - wsrep_thd_is_brute_force(lock->trx->mysql_thd); + my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); if ((bf_this && !bf_other) || (bf_this && bf_other && wsrep_trx_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { @@ -1593,7 +1632,11 @@ lock_rec_other_has_conflicting( if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { do { - if (lock_rec_has_to_wait(trx, mode, lock, +#ifdef WITH_WSREP + if (lock_rec_has_to_wait(TRUE, trx, mode, lock, +#else + if (lock_rec_has_to_wait(trx, mode, lock, +#endif /* WITH_WSREP */ TRUE)) { #ifdef WITH_WSREP wsrep_kill_victim(trx, lock); @@ -1606,7 +1649,11 @@ lock_rec_other_has_conflicting( } else { do { - if (lock_rec_has_to_wait(trx, mode, lock, +#ifdef WITH_WSREP + if (lock_rec_has_to_wait(TRUE, trx, mode, lock, +#else + if (lock_rec_has_to_wait(trx, mode, lock, +#endif /* WITH_WSREP */ FALSE)) { #ifdef WITH_WSREP wsrep_kill_victim(trx, lock); @@ -1790,11 +1837,6 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock->type_mode |= WSREP_BF; - } -#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1810,13 +1852,15 @@ lock_rec_create( lock_rec_set_nth_bit(lock, heap_no); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = c_lock->hash; lock_t *prev = NULL; while (hash && - wsrep_thd_is_brute_force(hash->trx->mysql_thd) && - wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){ + wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) && + wsrep_trx_order_before( + hash->trx->mysql_thd, trx->mysql_thd)) + { prev = hash; hash = hash->hash; } @@ -2162,11 +2206,6 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL);); @@ -2251,11 +2290,6 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2354,17 +2388,7 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { - mode |= WSREP_BF; - } -#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3802,11 +3826,11 @@ lock_deadlock_recursive( #ifdef WITH_WSREP if (wsrep_debug) fputs("WSREP: Deadlock detected\n", stderr); - if (wsrep_thd_is_brute_force(start->mysql_thd) && - wsrep_thd_is_brute_force( - wait_lock->trx->mysql_thd) && - (start != wait_lock->trx)) { - + if ((start != wait_lock->trx) && + wsrep_thd_is_BF(start->mysql_thd, TRUE) && + wsrep_thd_is_BF( + wait_lock->trx->mysql_thd, TRUE)) + { if (wsrep_trx_order_before( start->mysql_thd, wait_lock->trx->mysql_thd)) { @@ -3827,8 +3851,9 @@ lock_deadlock_recursive( back it */ #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force( - start->mysql_thd)) { + if (!wsrep_thd_is_BF( + start->mysql_thd, FALSE)) + { return(LOCK_VICTIM_IS_START); } #else @@ -3836,8 +3861,9 @@ lock_deadlock_recursive( #endif } #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force( - wait_lock->trx->mysql_thd)) { + if (wsrep_thd_is_BF( + wait_lock->trx->mysql_thd, TRUE)) + { return(LOCK_VICTIM_IS_START); } #endif @@ -3965,7 +3991,7 @@ lock_table_create( lock->un_member.tab_lock.table = table; #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( un_member.tab_lock.locks, table->locks, c_lock, lock); } else { @@ -5619,7 +5645,7 @@ lock_rec_insert_check_and_lock( #ifdef WITH_WSREP if ((c_lock = lock_rec_other_has_conflicting( - LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF, + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, trx))) { #else if (lock_rec_other_has_conflicting( @@ -5723,7 +5749,7 @@ lock_rec_convert_impl_to_expl( if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) #ifdef WITH_WSREP - && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE) /* BF-BF conflict is possible if advancing into lock_rec_other_has_conflicting*/ #endif /* WITH_WSREP */ diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index dcc4447e8e0..077730ab1ce 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1694,9 +1694,6 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { -#ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr); -#endif ulint n_unique; ulint i; int cmp; @@ -1760,14 +1757,8 @@ row_ins_scan_sec_index_for_duplicate( } else { lock_type = LOCK_ORDINARY; } -#ifdef WITH_WSREP - /* slave applier must not get duplicate error */ - if (allow_duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else + if (allow_duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1883,13 +1874,7 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1933,13 +1918,7 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 36215c1fd46..e145b604a33 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -370,6 +370,12 @@ wsrep_row_upd_check_foreign_constraints( } trx = thr_get_trx(thr); + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + + return(DB_SUCCESS); + } + + /* TODO: make native slave thread bail out here */ rec = btr_pcur_get_rec(pcur); ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index a402b182391..de0da290225 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -1401,7 +1401,7 @@ srv_conc_enter_innodb( #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { srv_conc_force_enter_innodb(trx); return; } @@ -2070,7 +2070,7 @@ srv_suspend_mysql_thread( #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, TRUE)) { fprintf(stderr, "WSREP: BF long lock wait ended after %.f sec\n", wait_time); @@ -2891,7 +2891,7 @@ wsrep_is_BF_lock_timeout( srv_slot_t* slot) /* in: lock slot to check for lock priority */ { if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && - wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + wsrep_thd_is_BF((thr_get_trx(slot->thr))->mysql_thd, TRUE)) { fprintf(stderr, "WSREP: BF lock wait long\n"); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; From e0f0f5f6d0b983619a67725c6a3351c31a547852 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 10 Feb 2014 23:54:18 -0500 Subject: [PATCH 118/294] Reverting the change erroneously got introduced during merge. --- sql/sql_connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 07290af8f4f..075b3aeffcb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1299,7 +1299,7 @@ end_thread: if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); - if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0)) + if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) return; // Probably no-threads /* From 8e476e6cbe313fadb6e0cd4402ff8c9d2d487406 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Feb 2014 11:38:46 -0500 Subject: [PATCH 119/294] MDEV#5534: mysql_tzinfo_to_sql generates wrong query mysql_tzinfo_to_sql tries to set wsrep_replicate_myisam as SESSION variable, while its a GLOBAL-only system variable, and thus the resulting sql would fail to load. Fixed by changing the scope to GLOBAL in the SET command. Also added following include files to facilitate testing : * include/have_wsrep.inc * include/not_wsrep.inc * include/have_wsrep_enabled.inc --- mysql-test/include/have_wsrep.inc | 12 ++-- mysql-test/include/have_wsrep_enabled.inc | 9 +++ mysql-test/include/not_wsrep.inc | 7 ++ .../r/mysql_tzinfo_to_sql_symlink.result | 4 -- mysql-test/r/not_wsrep.require | 2 + mysql-test/suite/wsrep/r/binlog_format.result | 2 + .../r/mysql_tzinfo_to_sql_symlink.result | 70 +++++++++++++++++++ mysql-test/suite/wsrep/r/variables.result | 14 ++++ mysql-test/suite/wsrep/t/binlog_format.test | 5 +- .../wsrep/t/mysql_tzinfo_to_sql_symlink.test | 40 +++++++++++ mysql-test/suite/wsrep/t/variables.test | 19 +++++ mysql-test/t/mysql_tzinfo_to_sql_symlink.test | 5 ++ sql/handler.cc | 2 +- sql/tztime.cc | 9 ++- 14 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 mysql-test/include/have_wsrep_enabled.inc create mode 100644 mysql-test/include/not_wsrep.inc create mode 100644 mysql-test/r/not_wsrep.require create mode 100644 mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result create mode 100644 mysql-test/suite/wsrep/r/variables.result create mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test create mode 100644 mysql-test/suite/wsrep/t/variables.test diff --git a/mysql-test/include/have_wsrep.inc b/mysql-test/include/have_wsrep.inc index f8f7e7a82fc..a3ceae41d40 100644 --- a/mysql-test/include/have_wsrep.inc +++ b/mysql-test/include/have_wsrep.inc @@ -1,4 +1,8 @@ --- require r/have_wsrep.require -disable_query_log; -show variables like 'wsrep_on'; -enable_query_log; +# To be used in a test which requires server to be compiled with wsrep support +# (-DWITH_WSREP=ON) and wsrep plugin is ACTIVE. + +if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`) +{ + --skip Test required wsrep plugin. +} + diff --git a/mysql-test/include/have_wsrep_enabled.inc b/mysql-test/include/have_wsrep_enabled.inc new file mode 100644 index 00000000000..edb919fd852 --- /dev/null +++ b/mysql-test/include/have_wsrep_enabled.inc @@ -0,0 +1,9 @@ +# 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 + +--require r/have_wsrep.require +disable_query_log; +SHOW VARIABLES LIKE 'wsrep_on'; +enable_query_log; diff --git a/mysql-test/include/not_wsrep.inc b/mysql-test/include/not_wsrep.inc new file mode 100644 index 00000000000..3314b5c8717 --- /dev/null +++ b/mysql-test/include/not_wsrep.inc @@ -0,0 +1,7 @@ +# To be used in a test which should be skipped if server is compiled with wsrep +# support (-DWITH_WSREP=ON) and wsrep plugin is ACTIVE. + +-- require r/not_wsrep.require +disable_query_log; +SELECT VERSION() LIKE '%wsrep%' AS 'HAVE_WSREP'; +enable_query_log; diff --git a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result index 1ff20da5b65..dda732937ee 100644 --- a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result @@ -2,7 +2,6 @@ # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above # # Verbose run -SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -27,7 +26,6 @@ Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid in ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # Silent run -SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -51,7 +49,6 @@ ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; # # Testing with explicit timezonefile # -SET SESSION wsrep_replicate_myisam=ON; INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); SET @time_zone_id= LAST_INSERT_ID(); INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); @@ -61,6 +58,5 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, # # Testing --leap # -SET SESSION wsrep_replicate_myisam=ON; TRUNCATE TABLE time_zone_leap_second; ALTER TABLE time_zone_leap_second ORDER BY Transition_time; diff --git a/mysql-test/r/not_wsrep.require b/mysql-test/r/not_wsrep.require new file mode 100644 index 00000000000..7c8e74af144 --- /dev/null +++ b/mysql-test/r/not_wsrep.require @@ -0,0 +1,2 @@ +HAVE_WSREP +0 diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index d87cd3bf1a8..5b8da51f829 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -1,3 +1,5 @@ +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); +call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result new file mode 100644 index 00000000000..f77a655773a --- /dev/null +++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result @@ -0,0 +1,70 @@ +# +# MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above +# +# Verbose run +SET GLOBAL wsrep_replicate_myisam= ON; +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/ignored.tab' as time zone. Skipping it. +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. +Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. +ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; +ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; +SET GLOBAL wsrep_replicate_myisam= OFF; +# Silent run +SET GLOBAL wsrep_replicate_myisam= ON; +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. +ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; +ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; +SET GLOBAL wsrep_replicate_myisam= OFF; +# +# Testing with explicit timezonefile +# +SET GLOBAL wsrep_replicate_myisam= ON; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +SET GLOBAL wsrep_replicate_myisam= OFF; +# +# Testing --leap +# +SET GLOBAL wsrep_replicate_myisam= ON; +TRUNCATE TABLE time_zone_leap_second; +ALTER TABLE time_zone_leap_second ORDER BY Transition_time; +SET GLOBAL wsrep_replicate_myisam= OFF; diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result new file mode 100644 index 00000000000..01b5abe5661 --- /dev/null +++ b/mysql-test/suite/wsrep/r/variables.result @@ -0,0 +1,14 @@ + +# MDEV#5534: mysql_tzinfo_to_sql generates wrong query +# +# Testing wsrep_replicate_myisam variable. +SELECT @@session.wsrep_replicate_myisam; +ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable +SELECT @@global.wsrep_replicate_myisam; +@@global.wsrep_replicate_myisam +0 +SET SESSION wsrep_replicate_myisam= ON; +ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable and should be set with SET GLOBAL +SET GLOBAL wsrep_replicate_myisam= ON; +SET GLOBAL wsrep_replicate_myisam= OFF; +# End of test. diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 907fae5f4fb..99d34873512 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,8 +1,11 @@ ---source include/have_wsrep.inc +--source include/have_wsrep_enabled.inc --source include/have_binlog_format_row.inc # # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT # +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); +call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); + SHOW VARIABLES LIKE 'binlog_format'; -- error ER_WRONG_VALUE_FOR_VAR SET binlog_format=STATEMENT; diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test new file mode 100644 index 00000000000..100e09d3afb --- /dev/null +++ b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test @@ -0,0 +1,40 @@ +--source include/have_wsrep.inc +--source include/have_symlink.inc +--source include/not_windows.inc + +--echo # +--echo # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above +--echo # + +--exec mkdir $MYSQLTEST_VARDIR/zoneinfo +--exec ln -s $MYSQLTEST_VARDIR/zoneinfo $MYSQLTEST_VARDIR/zoneinfo/posix +--copy_file std_data/zoneinfo/GMT $MYSQLTEST_VARDIR/zoneinfo/GMT +--copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/garbage +--copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/ignored.tab + +--echo # Verbose run +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --verbose $MYSQLTEST_VARDIR/zoneinfo 2>&1 + +--echo # Silent run +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL $MYSQLTEST_VARDIR/zoneinfo 2>&1 + +--echo # +--echo # Testing with explicit timezonefile +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL $MYSQLTEST_VARDIR/zoneinfo/GMT XXX 2>&1 + +--echo # +--echo # Testing --leap +--echo # + +--exec $MYSQL_TZINFO_TO_SQL --leap $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 + +# +# Cleanup +# + +--exec rm -rf $MYSQLTEST_VARDIR/zoneinfo diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test new file mode 100644 index 00000000000..306cdf9b2c9 --- /dev/null +++ b/mysql-test/suite/wsrep/t/variables.test @@ -0,0 +1,19 @@ +--source include/have_wsrep.inc + +--echo +--echo # MDEV#5534: mysql_tzinfo_to_sql generates wrong query +--echo # +--echo # Testing wsrep_replicate_myisam variable. + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_replicate_myisam; +SELECT @@global.wsrep_replicate_myisam; + +--error ER_GLOBAL_VARIABLE +SET SESSION wsrep_replicate_myisam= ON; +SET GLOBAL wsrep_replicate_myisam= ON; + +# Reset it back. +SET GLOBAL wsrep_replicate_myisam= OFF; + +--echo # End of test. diff --git a/mysql-test/t/mysql_tzinfo_to_sql_symlink.test b/mysql-test/t/mysql_tzinfo_to_sql_symlink.test index 1ba4e91be3c..61ae3d2bffd 100644 --- a/mysql-test/t/mysql_tzinfo_to_sql_symlink.test +++ b/mysql-test/t/mysql_tzinfo_to_sql_symlink.test @@ -1,6 +1,11 @@ --source include/have_symlink.inc --source include/not_windows.inc +# Note: The output of mysql_tzinfo_to_sql is different if server is compiled +# with wsrep. Hence a copy of this test has been placed under wsrep suite with +# the updated result. (lp:1161432) +--source include/not_wsrep.inc + --echo # --echo # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above --echo # diff --git a/sql/handler.cc b/sql/handler.cc index a392171ec18..5f12a6b5c96 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5407,7 +5407,7 @@ void ha_wsrep_fake_trx_id(THD *thd) } else { - WSREP_WARN("cannot get get fake InnoDB transaction ID"); + WSREP_WARN("cannot get fake InnoDB transaction ID"); } DBUG_VOID_RETURN; diff --git a/sql/tztime.cc b/sql/tztime.cc index 70a79f809df..405f5dd1f56 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2707,8 +2707,10 @@ main(int argc, char **argv) return 1; } +#ifdef WITH_WSREP // Replicate MyISAM DDL for this session, cf. lp:1161432 - printf("SET SESSION wsrep_replicate_myisam=ON;\n"); + printf("SET GLOBAL wsrep_replicate_myisam= ON;\n"); +#endif /* WITH_WSREP */ if (argc == 1 && !opt_leap) { @@ -2757,6 +2759,11 @@ main(int argc, char **argv) free_root(&tz_storage, MYF(0)); } +#ifdef WITH_WSREP + // Reset wsrep_replicate_myisam. lp:1161432 + printf("SET GLOBAL wsrep_replicate_myisam= OFF;\n"); +#endif /* WITH_WSREP */ + free_defaults(default_argv); my_end(0); return 0; From 6e3fc511c452f075f61f01c156d96a95654420ca Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 20 Feb 2014 13:49:50 -0500 Subject: [PATCH 120/294] MDEV #5682 : Incompatible galera / mariadb-galera-server version on Debian Updated galera package version to >=25.2 in Debian/Ubuntu control files. --- debian/dist/Debian/control | 12 ++++-------- debian/dist/Ubuntu/control | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 6d692773abb..50b216aae7c 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -187,20 +187,16 @@ Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=23.2) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mariadb-galera-server, mysql-server, virtual-mysql-server -Conflicts: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}), galera (>=25.2) +Provides: mariadb-server, mysql-server, virtual-mysql-server, mariadb-galera-server +Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 -Replaces: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), +Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 9e8f491cfcb..f6a1e492008 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -181,20 +181,16 @@ Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=23.2) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mariadb-galera-server, mysql-server, virtual-mysql-server -Conflicts: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}), galera (>=25.2) +Provides: mariadb-server, mysql-server, virtual-mysql-server, mariadb-galera-server +Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 -Replaces: mariadb-server, mysql-server, mariadb-galera-server (<< ${source:Version}), +Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database From e36fe045c03038b3bc2d9d21b4bbce66077985f5 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 25 Feb 2014 13:13:39 -0500 Subject: [PATCH 121/294] Added MTR support for galera. * include/galera_cluster.inc : Configures galera cluster with 2 nodes. * include/galera_init.inc : Opens named connection with all the nodes. * include/galera_end.inc : Closes all the connections. * include/galera_connect.inc : Opens a named connection with a single node. * include/galera_diff.inc : Runs a specified SQL query on all the nodes and diffs the output. --- mysql-test/include/galera_cluster.inc | 10 +++ mysql-test/include/galera_connect.inc | 45 ++++++++++ mysql-test/include/galera_diff.inc | 100 ++++++++++++++++++++++ mysql-test/include/galera_end.inc | 25 ++++++ mysql-test/include/galera_init.inc | 26 ++++++ mysql-test/include/mtr_warnings.sql | 8 ++ mysql-test/lib/mtr_cases.pm | 3 + mysql-test/mysql-test-run.pl | 4 + mysql-test/suite/galera/galera_2nodes.cnf | 21 +++++ mysql-test/suite/galera/my.cnf | 1 + mysql-test/suite/galera/r/basic.result | 30 +++++++ mysql-test/suite/galera/t/basic.test | 26 ++++++ mysql-test/suite/wsrep/README | 7 ++ mysql-test/suite/wsrep/t/trans.test | 1 + 14 files changed, 307 insertions(+) create mode 100644 mysql-test/include/galera_cluster.inc create mode 100644 mysql-test/include/galera_connect.inc create mode 100644 mysql-test/include/galera_diff.inc create mode 100644 mysql-test/include/galera_end.inc create mode 100644 mysql-test/include/galera_init.inc create mode 100644 mysql-test/suite/galera/galera_2nodes.cnf create mode 100644 mysql-test/suite/galera/my.cnf create mode 100644 mysql-test/suite/galera/r/basic.result create mode 100644 mysql-test/suite/galera/t/basic.test create mode 100644 mysql-test/suite/wsrep/README diff --git a/mysql-test/include/galera_cluster.inc b/mysql-test/include/galera_cluster.inc new file mode 100644 index 00000000000..bc652225722 --- /dev/null +++ b/mysql-test/include/galera_cluster.inc @@ -0,0 +1,10 @@ +# galera_cluster.inc +# ================== +# +# Description +# ----------- +# Configure galera cluster with 2 nodes. +# + +--let $galera_cluster_size = 2 +--source include/galera_init.inc diff --git a/mysql-test/include/galera_connect.inc b/mysql-test/include/galera_connect.inc new file mode 100644 index 00000000000..bfd9b188667 --- /dev/null +++ b/mysql-test/include/galera_connect.inc @@ -0,0 +1,45 @@ +# galera_connect.inc +# ================== +# +# Description +# ----------- +# Open a connection to the specified server number ($galera_server_number). +# The connection itself would be identified by $galera_connection_name. +# +# Parameters +# ---------- +# $galera_connection_name +# Name of the resulting connection. +# +# $galera_server_number +# Sequence number of the node in the galera cluster. +# +# $galera_debug +# Print debug information. +# + +if (!$galera_connection_name) +{ + --die ERROR IN TEST: $galera_connection_name must be set before sourcing include/galera_connect.inc +} + +if (!$galera_server_number) +{ + --die ERROR IN TEST: $galera_server_number must be set before sourcing include/galera_connect.inc +} + +--let $_galera_port= \$NODE_MYPORT_$galera_server_number +if (!$_galera_port) +{ + --echo Bug in test case: '\$NODE_MYPORT_$galera_server_number' not initialized. Check the test's .cfg file. + --die Not all NODE_MYPORT_* environment variables are setup correctly. +} + +if ($galera_debug) +{ + --echo connect($galera_connection_name,127.0.0.1,root,,test,$_galera_port,) +} + +# Open a connection +--connect($galera_connection_name,127.0.0.1,root,,test,$_galera_port,) + diff --git a/mysql-test/include/galera_diff.inc b/mysql-test/include/galera_diff.inc new file mode 100644 index 00000000000..6043b582647 --- /dev/null +++ b/mysql-test/include/galera_diff.inc @@ -0,0 +1,100 @@ +# galera_diff.inc +# =============== +# +# Description +# ----------- +# Compare the output of the given statement on all the nodes of the cluster. +# +# Parameters +# ---------- +# $galera_diff_statement +# Statement for which the output would be compared. +# +# $galera_diff_database +# Database against which the above statement would be executed. +# (Default : test) +# +# $galera_diff_servers +# Comma separated list of servers to executed the diff statement on. If not +# set, a list of servers will be generated based on $galera_cluster_size. +# +# $galerra_debug +# Print debug information. +# + +if (!$galera_diff_statement) +{ + --die ERROR IN TEST: $galera_diff_statement must be set before sourcing include/galera_diff.inc +} + +--let $_galera_diff_database = $galera_diff_database +if (!$_galera_diff_database) +{ + --let $_galera_diff_database = test +} + +--let $_galera_diff_servers= $galera_diff_servers +if (!$_galera_diff_servers) +{ + --let $_i= $galera_cluster_size + --let $_galera_diff_servers= + while ($_i) + { + --let $_galera_diff_servers= $_i,$_galera_diff_servers + --dec $_i + } +} +if ($galera_debug) +{ + --echo \$galera_diff_servers= '$_galera_diff_servers' +} + +if (!$galera_debug) +{ + --disable_query_log +} + +# Generate file containing $galera_diff_statement. We don't pass the +# statement on the command line, because it would be subject to shell +# substitutions. +--let $write_to_file= GENERATE +--let $write_var= $galera_diff_statement +--source include/write_var_to_file.inc +--let $_galera_diff_statement_file= $write_to_file + +if (!$galera_debug) +{ + --enable_query_log +} + +# Compare all servers. +--let $_galera_diff_first= 1 +while ($_galera_diff_servers) +{ + # Set $_galera_diff_server_i to the first number in the list + --let $_galera_diff_server_i= `SELECT SUBSTRING_INDEX('$_galera_diff_servers', ',', 1)` + # Remove $_galera_diff_server_i from the list + --let $_galera_diff_servers= `SELECT SUBSTRING('$_galera_diff_servers', LENGTH('$_galera_diff_server_i') + 2)` + + # Execute statement + --let $_galera_diff_file= $MYSQLTEST_VARDIR/tmp/_galera_diff_server-$_galera_diff_server_i.tmp + --exec $MYSQL --defaults-group-suffix=.$_galera_diff_server_i $_galera_diff_database < $_galera_diff_statement_file > $_galera_diff_file + + # Compare + if (!$_galera_diff_first) + { + if ($galera_debug) + { + --echo diffing $_galera_diff_file and $_galera_diff_prev_file + } + --diff_files $_galera_diff_file $_galera_diff_prev_file + --remove_file $_galera_diff_prev_file + } + --let $_galera_diff_prev_file= $_galera_diff_file + --let $_galera_diff_first= 0 +} + +# Cleanup +--remove_file $_galera_diff_prev_file +--remove_file $_galera_diff_statement_file + diff --git a/mysql-test/include/galera_end.inc b/mysql-test/include/galera_end.inc new file mode 100644 index 00000000000..0fb5479844e --- /dev/null +++ b/mysql-test/include/galera_end.inc @@ -0,0 +1,25 @@ +# galera_end.inc +# ============== +# +# Description +# ----------- +# Closes the connections opened via include/galera_init.inc +# +# Parameters +# ---------- +# $galera_cluster_size +# Number of nodes in the cluster. +# + +--let $_galera_node= $galera_cluster_size + +while ($_galera_node) +{ + if ($galera_debug) + { + --echo Disconnecting node_$_galera_node + } + --disconnect node_$_galera_node + --dec $_galera_node +} + diff --git a/mysql-test/include/galera_init.inc b/mysql-test/include/galera_init.inc new file mode 100644 index 00000000000..79591973862 --- /dev/null +++ b/mysql-test/include/galera_init.inc @@ -0,0 +1,26 @@ +# galera_init.inc +# =============== +# +# Description +# ----------- +# Set up a Galera cluster with $wsrep_cluster_size nodes. +# +# Parameters +# ---------- +# $galera_cluster_size +# Number of nodes in the cluster. +# + +--source include/have_wsrep_enabled.inc + +--let $_galera_node= $galera_cluster_size + +while ($_galera_node) +{ + --let $galera_connection_name= node_$_galera_node + --let $galera_server_number= $_galera_node + --source include/galera_connect.inc + + --dec $_galera_node +} + diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 37a17a8133e..4c2c39a6047 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -224,6 +224,14 @@ INSERT INTO global_suppressions VALUES ("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum on master.*"), ("Slave I/O: Get master BINLOG_CHECKSUM failed with error.*"), ("Slave I/O: Notifying master by SET @master_binlog_checksum= @@global.binlog_checksum failed with error.*"), + + /* + Galera-related warnings. + */ + ("WSREP: Could not open saved state file for reading: .*"), + ("WSREP: last inactive check more than .* skipping check"), + ("WSREP: Gap in state sequence. Need state transfer."), + ("WSREP: Failed to prepare for incremental state transfer: .*"), ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 870df115f58..3434b70bb3c 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -856,6 +856,8 @@ sub collect_one_test_case { # Suite has no config, autodetect which one to use if ($tinfo->{rpl_test}) { $config= "suite/rpl/my.cnf"; + } elsif ($tinfo->{galera_test}) { + $config= "suite/galera/my.cnf"; } else { $config= "include/default_my.cnf"; } @@ -976,6 +978,7 @@ my $tags_map= {'big_test' => ['big_test', 1], 'master-slave' => ['rpl_test', 1], 'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1], 'long_test' => ['long_test', 1], + 'galera_init' => ['galera_test', 1], }; my $tags_regex_string= join('|', keys %$tags_map); my $tags_regex= qr:include/($tags_regex_string)\.inc:o; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index d909391f033..101f29aa204 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4812,6 +4812,10 @@ sub extract_warning_lines ($$) { qr|feedback plugin: failed to retrieve the MAC address|, qr|Plugin 'FEEDBACK' init function returned error|, qr|Plugin 'FEEDBACK' registration as a INFORMATION SCHEMA failed|, + + # Galera-related warnings. + qr|WSREP:.*down context.*|, + qr|WSREP: Failed to send state UUID:.*|, ); my $matched_lines= []; diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf new file mode 100644 index 00000000000..b950ae1fe4d --- /dev/null +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -0,0 +1,21 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld.1] +binlog-format=row +wsrep_provider=/usr/lib/libgalera_smm.so +wsrep_cluster_address='gcomm://' + +[mysqld.2] +binlog-format=row +wsrep_provider=/usr/lib/libgalera_smm.so +wsrep_cluster_address='gcomm://127.0.0.1:4567' +wsrep_provider_options='gmcast.listen_addr=tcp://127.0.0.1:4568' + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +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/my.cnf b/mysql-test/suite/galera/my.cnf new file mode 100644 index 00000000000..ca163a540d9 --- /dev/null +++ b/mysql-test/suite/galera/my.cnf @@ -0,0 +1 @@ +!include galera_2nodes.cnf diff --git a/mysql-test/suite/galera/r/basic.result b/mysql-test/suite/galera/r/basic.result new file mode 100644 index 00000000000..d4efe348b61 --- /dev/null +++ b/mysql-test/suite/galera/r/basic.result @@ -0,0 +1,30 @@ +USE test; +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +SELECT * FROM t1; +c1 +1 +2 +3 +4 +5 + +# On node_1 +SELECT * FROM test.t1; +c1 +1 +2 +3 +4 +5 + +# On node_2 +SELECT * FROM test.t1; +c1 +1 +2 +3 +4 +5 +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/t/basic.test b/mysql-test/suite/galera/t/basic.test new file mode 100644 index 00000000000..8fc6eee3b3b --- /dev/null +++ b/mysql-test/suite/galera/t/basic.test @@ -0,0 +1,26 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +USE test; +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +SELECT * FROM t1; + +--echo +--echo # On node_1 +--connection node_1 +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + +--let $galera_diff_statement = SELECT * FROM t1 +--source include/galera_diff.inc + +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test diff --git a/mysql-test/suite/wsrep/README b/mysql-test/suite/wsrep/README new file mode 100644 index 00000000000..988096071a4 --- /dev/null +++ b/mysql-test/suite/wsrep/README @@ -0,0 +1,7 @@ +* 'wsrep' suite is designated for tests which do not require a multi-node + galera cluster. + +* As these tests are specific to wsrep-related functionalities, they must skip + on server built without wsrep patch (vanilla). (-DWITH_WSREP=OFF) + See : include/have_wsrep.inc, include/have_wsrep_enabled.inc, not_wsrep.inc + diff --git a/mysql-test/suite/wsrep/t/trans.test b/mysql-test/suite/wsrep/t/trans.test index 9278ef12072..d8c4a4722a0 100644 --- a/mysql-test/suite/wsrep/t/trans.test +++ b/mysql-test/suite/wsrep/t/trans.test @@ -1,3 +1,4 @@ +--source include/have_wsrep.inc --source include/have_innodb.inc --echo # From c3a2394641e2f7b199977bcf699ad64c1bb1367f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 28 Feb 2014 13:56:08 -0500 Subject: [PATCH 122/294] * Merged revisions 3945, 3946..3950, 3951..3961 from codership-mysql/5.5. * Merged changes in innobase to xtradb. * Updated WSREP_PATCH_REVNO. --- cmake/wsrep.cmake | 2 +- mysql-test/suite/galera/galera_2nodes.cnf | 4 +- mysql-test/suite/wsrep/t/binlog_format.opt | 2 +- scripts/wsrep_sst_rsync.sh | 24 +++++++----- sql/ha_partition.cc | 8 +++- sql/ha_partition.h | 1 + sql/handler.cc | 44 ++++++++++++++++------ sql/log_event.cc | 7 +++- sql/mysqld.cc | 4 +- sql/sql_partition_admin.cc | 13 +++++++ sql/sql_truncate.cc | 12 +++--- sql/wsrep_binlog.cc | 7 ++-- sql/wsrep_check_opts.cc | 13 ------- sql/wsrep_hton.cc | 19 +++------- sql/wsrep_mysqld.cc | 2 +- sql/wsrep_mysqld.h | 9 +++-- storage/innobase/handler/ha_innodb.cc | 16 +++++--- storage/innobase/row/row0ins.c | 4 ++ storage/xtradb/handler/ha_innodb.cc | 16 +++++--- storage/xtradb/row/row0ins.c | 4 ++ 20 files changed, 130 insertions(+), 81 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 391cf505313..a5ca4508da4 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "9") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "3944") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "3961") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index b950ae1fe4d..1ef673e9582 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -3,12 +3,12 @@ [mysqld.1] binlog-format=row -wsrep_provider=/usr/lib/libgalera_smm.so +wsrep_provider=/usr/lib/galera/libgalera_smm.so wsrep_cluster_address='gcomm://' [mysqld.2] binlog-format=row -wsrep_provider=/usr/lib/libgalera_smm.so +wsrep_provider=/usr/lib/galera/libgalera_smm.so wsrep_cluster_address='gcomm://127.0.0.1:4567' wsrep_provider_options='gmcast.listen_addr=tcp://127.0.0.1:4568' diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt index 901ead9a41d..771d9b05e1e 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.opt +++ b/mysql-test/suite/wsrep/t/binlog_format.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/libgalera_smm.so --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin \ No newline at end of file +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/galera/libgalera_smm.so --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index b3535480c67..4b78071542c 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -67,12 +67,22 @@ check_pid_and_port() MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" rm -rf "$MAGIC_FILE" -SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P) -WSREP_LOG_DIR=${WSREP_LOG_DIR:-$($SCRIPT_DIR/my_print_defaults --defaults-file "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \ - | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' | cut -b 29- )} -if [ -n "${WSREP_LOG_DIR:-""}" ]; then +WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} + +# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$WSREP_LOG_DIR" ]; then + SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)" + WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \ + "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \ + | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ + | cut -b 29- ) +fi + +if [ -n "$WSREP_LOG_DIR" ]; then + # handle both relative and absolute paths WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P) else + # default to datadir WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P) fi @@ -158,7 +168,7 @@ then find . -maxdepth 1 -mindepth 1 -type d -print0 | xargs -I{} -0 -P $count \ rsync --owner --group --perms --links --specials \ --ignore-times --inplace --recursive --delete --quiet \ - $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ + $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$? popd >/dev/null @@ -208,8 +218,6 @@ then trap "exit 3" INT TERM ABRT trap cleanup_joiner EXIT - MYUID=$(id -u) - MYGID=$(id -g) RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" cat << EOF > "$RSYNC_CONF" @@ -217,8 +225,6 @@ pid file = $RSYNC_PID use chroot = no read only = no timeout = 300 -uid = $MYUID -gid = $MYGID [$MODULE] path = $WSREP_SST_OPT_DATA [$MODULE-log_dir] diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0d30265ce9a..25bb6f44284 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -308,7 +308,13 @@ const char *ha_partition::table_type() const // we can do this since we only support a single engine type return m_file && m_file[0] ? m_file[0]->table_type() : "Unknown"; } - +#ifdef WITH_WSREP +int ha_partition::wsrep_db_type() const +{ + // we can do this since we only support a single engine type + return ha_legacy_type(m_file[0]->ht); +} +#endif /* WITH_WSREP */ /* Destructor method diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 68ce1e47764..db8863a36b6 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1178,6 +1178,7 @@ public: for (uint i=0; i < m_tot_parts; i++) m_file[i]->ha_start_of_new_statement(); } + virtual int wsrep_db_type() const; #endif /* WITH_WSREP */ }; diff --git a/sql/handler.cc b/sql/handler.cc index 5f12a6b5c96..dc7e3cb3084 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1302,18 +1302,27 @@ int ha_commit_trans(THD *thd, bool all) if (err) { #ifdef WITH_WSREP - if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) - { - error= 1; - /* avoid sending error, if we need to replay */ - if (thd->wsrep_conflict_state!= MUST_REPLAY) - { - my_error(ER_LOCK_DEADLOCK, MYF(0), err); - } - } - else - { - /* not wsrep hton, bail to native mysql behavior */ + if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) + { + error= 1; + switch (err) + { + case WSREP_TRX_SIZE_EXCEEDED: + /* give user size exeeded erro from wsrep_api.h */ + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED); + break; + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + /* avoid sending error, if we need to replay */ + if (thd->wsrep_conflict_state!= MUST_REPLAY) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), err); + } + } + } + else + { + /* not wsrep hton, bail to native mysql behavior */ #endif /* WITH_WSREP */ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); error= 1; @@ -5119,6 +5128,17 @@ static int binlog_log_row(TABLE* table, bool error= 0; THD *const thd= table->in_use; +#ifdef WITH_WSREP + /* only InnoDB tables will be replicated through binlog emulation */ + if (WSREP_EMULATE_BINLOG(thd) && + table->file->ht->db_type != DB_TYPE_INNODB && + !(table->file->ht->db_type == DB_TYPE_PARTITION_DB && + (((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB))) + // !strcmp(table->file->table_type(), "InnoDB")) + { + return 0; + } +#endif /* WITH_WSREP */ if (check_table_binlog_row_based(thd, table)) { MY_BITMAP cols; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9bfeaed5ac5..5d402cdeb3a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2829,7 +2829,12 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, { time_t end_time; #ifdef WITH_WSREP - thd->wsrep_PA_safe= false; + /* + If Query_log_event will contain non trans keyword (not BEGIN, COMMIT, + SAVEPOINT or ROLLBACK) we disable PA for this transaction. + */ + if (!is_trans_keyword()) + thd->wsrep_PA_safe= false; #endif /* WITH_WSREP */ memset(&user, 0, sizeof(user)); memset(&host, 0, sizeof(host)); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8ad51a03237..4703d426b51 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4883,7 +4883,7 @@ pthread_handler_t start_wsrep_THD(void *arg) mysql_mutex_lock(&LOCK_thread_count); wsrep_running_threads++; - mysql_cond_signal(&COND_thread_count); + mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); processor(thd); @@ -4893,7 +4893,7 @@ pthread_handler_t start_wsrep_THD(void *arg) mysql_mutex_lock(&LOCK_thread_count); wsrep_running_threads--; WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads); - mysql_cond_signal(&COND_thread_count); + mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); // Note: We can't call THD destructor without crashing diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index a03dcc5c16e..bb5208a16ff 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -134,6 +134,19 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd) if (check_one_table_access(thd, DROP_ACL, first_table)) DBUG_RETURN(TRUE); +#ifdef WITH_WSREP + TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); + + if ((!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, first_table)) && + wsrep_to_isolation_begin( + thd, first_table->db, first_table->table_name, NULL) + ) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ if (open_and_lock_tables(thd, first_table, FALSE, 0)) DBUG_RETURN(TRUE); diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 22b5b676420..c018ddc8e7c 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -449,6 +449,12 @@ bool Truncate_statement::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, + table_ref->table_name, NULL)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ if (lock_table(thd, table_ref, &hton_can_recreate)) DBUG_RETURN(TRUE); @@ -525,12 +531,6 @@ bool Truncate_statement::execute(THD *thd) if (check_one_table_access(thd, DROP_ACL, first_table)) DBUG_RETURN(res); -#ifdef WITH_WSREP - if (WSREP(thd) && wsrep_to_isolation_begin(thd, - first_table->db, - first_table->table_name, NULL)) - DBUG_RETURN(TRUE); -#endif /* WITH_WSREP */ if (! (res= truncate_table(thd, first_table))) my_ok(thd); DBUG_RETURN(res); diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index a0c56ce9299..933ef3dc31f 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -166,6 +166,7 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep, { WSREP_WARN("transaction size limit (%lu) exceeded: %zu", wsrep_max_ws_size, total_length); + err = WSREP_TRX_SIZE_EXCEEDED; goto cleanup; } @@ -177,7 +178,7 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep, { WSREP_ERROR("could not (re)allocate buffer: %zu + %u", allocated, length); - err = WSREP_SIZE_EXCEEDED; + err = WSREP_TRX_SIZE_EXCEEDED; goto cleanup; } @@ -232,7 +233,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep, if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) { WSREP_ERROR("failed to initialize io-cache"); - return WSREP_TRX_ROLLBACK; + return WSREP_TRX_ERROR; } int err(WSREP_OK); @@ -253,7 +254,7 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep, { WSREP_WARN("transaction size limit (%lu) exceeded: %zu", wsrep_max_ws_size, total_length); - err = WSREP_SIZE_EXCEEDED; + err = WSREP_TRX_SIZE_EXCEEDED; goto cleanup; } diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc index ce8a46c6bd5..5ec18c79978 100644 --- a/sql/wsrep_check_opts.cc +++ b/sql/wsrep_check_opts.cc @@ -303,19 +303,6 @@ check_opts (int const argc, const char* const argv[], struct opt opts[]) } } - long long query_cache_size, query_cache_type; - if ((err = get_long_long (opts[QUERY_CACHE_SIZE], &query_cache_size, 10))) - return err; - if ((err = get_long_long (opts[QUERY_CACHE_TYPE], &query_cache_type, 10))) - return err; - - if (0 != query_cache_size && 0 != query_cache_type) - { - WSREP_ERROR ("Query cache is not supported (size=%lld type=%lld)", - query_cache_size, query_cache_type); - rcode = EINVAL; - } - bool locked_in_memory; err = get_bool (opts[LOCKED_IN_MEMORY], &locked_in_memory); if (err) { WSREP_ERROR("get_bool error: %s", strerror(err)); return err; } diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index be60d997265..c5627ff97fb 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -139,7 +139,7 @@ wsrep_close_connection(handlerton* hton, THD* thd) - certification test or an equivalent. As a result, the current transaction just rolls back Error codes: - WSREP_TRX_ROLLBACK, WSREP_TRX_ERROR + 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 */ @@ -160,14 +160,7 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all) !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) { - switch (wsrep_run_wsrep_commit(thd, hton, all)) - { - case WSREP_TRX_OK: - break; - case WSREP_TRX_ROLLBACK: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); - } + DBUG_RETURN (wsrep_run_wsrep_commit(thd, hton, all)); } DBUG_RETURN(0); } @@ -324,7 +317,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) WSREP_INFO("innobase_commit, abort %s", (thd->query()) ? thd->query() : "void"); } - DBUG_RETURN(WSREP_TRX_ROLLBACK); + DBUG_RETURN(WSREP_TRX_CERT_FAIL); } mysql_mutex_lock(&LOCK_wsrep_replaying); @@ -375,7 +368,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) mysql_mutex_unlock(&thd->LOCK_wsrep_thd); WSREP_DEBUG("innobase_commit abort after replaying wait %s", (thd->query()) ? thd->query() : "void"); - DBUG_RETURN(WSREP_TRX_ROLLBACK); + DBUG_RETURN(WSREP_TRX_CERT_FAIL); } thd->wsrep_query_state = QUERY_COMMITTING; @@ -388,7 +381,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) 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_ROLLBACK); + DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED); } } @@ -510,7 +503,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - DBUG_RETURN(WSREP_TRX_ROLLBACK); + DBUG_RETURN(WSREP_TRX_CERT_FAIL); case WSREP_CONN_FAIL: WSREP_ERROR("connection failure"); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 708409a40f9..5867b063426 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -126,7 +126,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { sql_print_error("WSREP: %s", msg); break; case WSREP_LOG_DEBUG: - if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); + sql_print_information ("[Debug] WSREP: %s", msg); default: break; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 815990ba9d4..5cf0d9dc0c5 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -232,8 +232,9 @@ extern void wsrep_ready_wait(); enum wsrep_trx_status { WSREP_TRX_OK, - WSREP_TRX_ROLLBACK, - WSREP_TRX_ERROR, + WSREP_TRX_CERT_FAIL, /* certification failure, must abort */ + WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */ + WSREP_TRX_ERROR, /* native mysql error */ }; extern enum wsrep_trx_status @@ -269,7 +270,7 @@ extern mysql_mutex_t LOCK_wsrep_desync; extern wsrep_aborting_thd_t wsrep_aborting_thd; extern my_bool wsrep_emulate_bin_log; extern int wsrep_to_isolation; - +#ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready; extern PSI_mutex_key key_LOCK_wsrep_sst; @@ -284,7 +285,7 @@ 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; - +#endif /* HAVE_PSI_INTERFACE */ struct TABLE_LIST; int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index de36dedff19..bb2e94cef8b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5665,7 +5665,9 @@ ha_innobase::write_row( || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP || (wsrep_on(user_thd) && wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD) + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) #endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { @@ -5713,7 +5715,8 @@ no_commit: { case WSREP_TRX_OK: break; - case WSREP_TRX_ROLLBACK: + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: DBUG_RETURN(1); } @@ -5737,7 +5740,8 @@ no_commit: { case WSREP_TRX_OK: break; - case WSREP_TRX_ROLLBACK: + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: DBUG_RETURN(1); } @@ -7478,9 +7482,6 @@ ha_innobase::wsrep_append_keys( dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, record0, &is_null); @@ -7489,6 +7490,9 @@ ha_innobase::wsrep_append_keys( thd, trx, table_share, table, keyval0, len+1, shared); if (rcode) DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; } else { diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 67cc68738a9..c5857492fc4 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1757,6 +1757,10 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 696a426cdd2..8179852005e 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6629,7 +6629,9 @@ ha_innobase::write_row( || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP || (wsrep_on(user_thd) && wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD) + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) #endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { @@ -6677,7 +6679,8 @@ no_commit: { case WSREP_TRX_OK: break; - case WSREP_TRX_ROLLBACK: + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: DBUG_RETURN(1); } @@ -6701,7 +6704,8 @@ no_commit: { case WSREP_TRX_OK: break; - case WSREP_TRX_ROLLBACK: + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: DBUG_RETURN(1); } @@ -8521,9 +8525,6 @@ ha_innobase::wsrep_append_keys( dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, record0, &is_null); @@ -8532,6 +8533,9 @@ ha_innobase::wsrep_append_keys( thd, trx, table_share, table, keyval0, len+1, shared); if (rcode) DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; } else { diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 077730ab1ce..579d279a906 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1769,6 +1769,10 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } From 689aaab0f8d5ac98a08bc33b3e2edc3c2cd0fcf6 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 28 Feb 2014 23:15:35 -0500 Subject: [PATCH 123/294] MDEV#5552 Deadlock when inserting NULL column value in column with UNIQUE index References: lp:1276424 --- mysql-test/suite/galera/r/unique_key.result | 47 ++++++++++++++++++ mysql-test/suite/galera/t/unique_key.test | 54 +++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 mysql-test/suite/galera/r/unique_key.result create mode 100644 mysql-test/suite/galera/t/unique_key.test diff --git a/mysql-test/suite/galera/r/unique_key.result b/mysql-test/suite/galera/r/unique_key.result new file mode 100644 index 00000000000..ffb4f01c1f8 --- /dev/null +++ b/mysql-test/suite/galera/r/unique_key.result @@ -0,0 +1,47 @@ +# +# MDEV#5552 Deadlock when inserting NULL column value in column with +# UNIQUE index +# +USE test; + +# On node_1 +CREATE TABLE t1(c1 INT DEFAULT NULL, UNIQUE KEY c1(c1)) ENGINE=INNODB; +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (NULL); +SELECT * FROM test.t1; +c1 +NULL +NULL + +# On node_2 +SELECT * FROM test.t1; +c1 +NULL +NULL + +# On node_1 +INSERT INTO t1 VALUES (1); +UPDATE t1 SET c1=NULL WHERE c1=1; +SELECT * FROM test.t1; +c1 +NULL +NULL +NULL + +# On node_2 +SELECT * FROM test.t1; +c1 +NULL +NULL +NULL + +# On node_1 +DELETE FROM t1 WHERE c1<=>NULL; +SELECT * FROM test.t1; +c1 + +# On node_2 +SELECT * FROM test.t1; +c1 +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/t/unique_key.test b/mysql-test/suite/galera/t/unique_key.test new file mode 100644 index 00000000000..00b85d57165 --- /dev/null +++ b/mysql-test/suite/galera/t/unique_key.test @@ -0,0 +1,54 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV#5552 Deadlock when inserting NULL column value in column with +--echo # UNIQUE index +--echo # + +USE test; +--echo +--echo # On node_1 +--connection node_1 +CREATE TABLE t1(c1 INT DEFAULT NULL, UNIQUE KEY c1(c1)) ENGINE=INNODB; +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (NULL); +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + + +--echo +--echo # On node_1 +--connection node_1 +INSERT INTO t1 VALUES (1); +UPDATE t1 SET c1=NULL WHERE c1=1; +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + +--echo +--echo # On node_1 +--connection node_1 +DELETE FROM t1 WHERE c1<=>NULL; +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + +--let $galera_diff_statement = SELECT * FROM t1 +--source include/galera_diff.inc + +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test From 653ef22336a5c14404b9690bb44df702292463b2 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 6 Mar 2014 18:44:16 -0500 Subject: [PATCH 124/294] MDEV#5687: Maria doesn't shutdown following upgrade to 5.5.35-galera Restored patch for MDEV#4136 and added a test. --- mysql-test/suite/wsrep/r/pool_of_threads.result | 8 ++++++++ mysql-test/suite/wsrep/t/pool_of_threads.opt | 1 + mysql-test/suite/wsrep/t/pool_of_threads.test | 11 +++++++++++ sql/mysqld.cc | 4 +--- 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/pool_of_threads.result create mode 100644 mysql-test/suite/wsrep/t/pool_of_threads.opt create mode 100644 mysql-test/suite/wsrep/t/pool_of_threads.test diff --git a/mysql-test/suite/wsrep/r/pool_of_threads.result b/mysql-test/suite/wsrep/r/pool_of_threads.result new file mode 100644 index 00000000000..ffe309f2580 --- /dev/null +++ b/mysql-test/suite/wsrep/r/pool_of_threads.result @@ -0,0 +1,8 @@ + +# +# MDEV#5687: Maria doesn't shutdown following upgrade to 5.5.35-galera +# +SELECT @@GLOBAL.thread_handling; +@@GLOBAL.thread_handling +pool-of-threads +# End of test. diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.opt b/mysql-test/suite/wsrep/t/pool_of_threads.opt new file mode 100644 index 00000000000..92994ddfb68 --- /dev/null +++ b/mysql-test/suite/wsrep/t/pool_of_threads.opt @@ -0,0 +1 @@ +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/galera/libgalera_smm.so --wsrep-cluster-address=gcomm:// --thread_handling=pool-of-threads diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.test b/mysql-test/suite/wsrep/t/pool_of_threads.test new file mode 100644 index 00000000000..f4fffaf4f9a --- /dev/null +++ b/mysql-test/suite/wsrep/t/pool_of_threads.test @@ -0,0 +1,11 @@ +--source include/have_wsrep.inc + +--echo +--echo # +--echo # MDEV#5687: Maria doesn't shutdown following upgrade to 5.5.35-galera +--echo # + +# Note: This test is to ensure that server shuts down properly. +SELECT @@GLOBAL.thread_handling; + +--echo # End of test. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4703d426b51..829bc0be763 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4912,7 +4912,7 @@ pthread_handler_t start_wsrep_THD(void *arg) // at server shutdown } -#if 0 + my_thread_end(); if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { mysql_mutex_lock(&LOCK_thread_count); @@ -4920,8 +4920,6 @@ pthread_handler_t start_wsrep_THD(void *arg) thread_count--; mysql_mutex_unlock(&LOCK_thread_count); } -#endif - my_thread_end(); return(NULL); } From 57ba177dafef33bac544498e66bfd705e6cfc476 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 11 Mar 2014 23:12:18 -0400 Subject: [PATCH 125/294] MDEV#5812 Memory leaks while running mysqld in bootstrap mode Added calls to deinit functions at appropriate places. --- extra/my_print_defaults.c | 11 ++++++++--- sql/mysqld.cc | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 7558d6d00ae..8e2ca4ee662 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -96,6 +96,11 @@ static struct my_option my_long_options[] = {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; +void cleanup_and_exit(int exit_code) +{ + my_end(0); + exit(exit_code); +} static void usage(my_bool version) { @@ -110,7 +115,7 @@ static void usage(my_bool version) my_print_default_files(config_file); my_print_variables(my_long_options); printf("\nExample usage:\n%s --defaults-file=example.cnf client client-server mysql\n", my_progname); - exit(0); + cleanup_and_exit(0); } @@ -123,7 +128,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_defaults_file_used= 1; break; case 'n': - exit(0); + cleanup_and_exit(0); case 'I': case '?': usage(0); @@ -172,7 +177,7 @@ int main(int argc, char **argv) /* Check out the args */ if (get_options(&argc,&argv)) - exit(1); + cleanup_and_exit(1); nargs= argc + 1; if (opt_mysqld) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 829bc0be763..91fdb27ffe7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1868,6 +1868,10 @@ extern "C" void unireg_abort(int exit_code) wsrep_close_threads(thd); /* 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."); + + /* In bootstrap mode we deinitialize wsrep here. */ + if (opt_bootstrap && wsrep_inited) + wsrep_deinit(); } #endif // WITH_WSREP From d395440d0f63314894eb11b5f53408c0036d14cf Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 13 Mar 2014 11:51:31 -0400 Subject: [PATCH 126/294] Debian script fixes. --- debian/dist/Debian/control | 24 ++++- .../Debian/mariadb-galera-server-5.5.dirs | 1 - .../Debian/mariadb-galera-server-5.5.files.in | 26 ----- debian/dist/Debian/rules | 2 + debian/dist/Ubuntu/control | 22 +++- .../Ubuntu/mariadb-galera-server-5.5.dirs | 1 - .../Ubuntu/mariadb-galera-server-5.5.files.in | 26 ----- debian/dist/Ubuntu/rules | 2 + debian/libmariadbclient-dev.README.Maintainer | 4 + debian/libmariadbclient-dev.dirs | 2 + debian/libmariadbclient-dev.examples | 1 + debian/libmariadbclient-dev.files | 7 ++ debian/libmariadbclient-dev.links | 2 + debian/libmariadbclient18.dirs | 1 + debian/libmariadbclient18.files | 3 + debian/libmariadbclient18.postinst | 12 +++ debian/libmariadbd-dev.files | 2 + debian/mariadb-client-5.5.README.Debian | 4 + debian/mariadb-client-5.5.dirs | 3 + debian/mariadb-client-5.5.docs | 2 + debian/mariadb-client-5.5.files | 31 ++++++ debian/mariadb-client-5.5.links | 3 + debian/mariadb-client-5.5.lintian-overrides | 3 + debian/mariadb-client-5.5.menu | 3 + debian/mariadb-client-core-5.5.files | 4 + debian/mariadb-common.files | 1 + debian/mariadb-common.postrm | 8 ++ debian/mariadb-server-core-5.5.files | 26 +++++ debian/mariadb-test-5.5.dirs | 101 ++++++++++++++++++ debian/mariadb-test-5.5.files | 15 +++ debian/mariadb-test-5.5.links | 2 + debian/mysql-common.dirs | 1 + debian/mysql-common.files | 3 + debian/mysql-common.lintian-overrides | 2 + debian/mysql-common.postrm | 7 ++ 35 files changed, 300 insertions(+), 57 deletions(-) create mode 100644 debian/libmariadbclient-dev.README.Maintainer create mode 100644 debian/libmariadbclient-dev.dirs create mode 100644 debian/libmariadbclient-dev.examples create mode 100644 debian/libmariadbclient-dev.files create mode 100644 debian/libmariadbclient-dev.links create mode 100644 debian/libmariadbclient18.dirs create mode 100644 debian/libmariadbclient18.files create mode 100644 debian/libmariadbclient18.postinst create mode 100644 debian/libmariadbd-dev.files create mode 100644 debian/mariadb-client-5.5.README.Debian create mode 100644 debian/mariadb-client-5.5.dirs create mode 100644 debian/mariadb-client-5.5.docs create mode 100644 debian/mariadb-client-5.5.files create mode 100644 debian/mariadb-client-5.5.links create mode 100644 debian/mariadb-client-5.5.lintian-overrides create mode 100644 debian/mariadb-client-5.5.menu create mode 100644 debian/mariadb-client-core-5.5.files create mode 100644 debian/mariadb-common.files create mode 100644 debian/mariadb-common.postrm create mode 100644 debian/mariadb-server-core-5.5.files create mode 100644 debian/mariadb-test-5.5.dirs create mode 100644 debian/mariadb-test-5.5.files create mode 100644 debian/mariadb-test-5.5.links create mode 100644 debian/mysql-common.dirs create mode 100644 debian/mysql-common.files create mode 100644 debian/mysql-common.lintian-overrides create mode 100644 debian/mysql-common.postrm diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 50b216aae7c..021246d51f5 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -167,7 +167,7 @@ Description: MariaDB database core server files Package: mariadb-test-5.5 Section: database Architecture: any -Depends: mariadb-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) +Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) Conflicts: mariadb-test (<< ${source:Version}), mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33) @@ -193,7 +193,7 @@ Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Vers mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, mariadb-tokudb-engine-5.5 -Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), +Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), @@ -221,3 +221,23 @@ Description: MariaDB database server with Galera cluster (metapackage depending server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. + +Package: mariadb-client +Section: database +Architecture: all +Depends: mariadb-client-5.5 (= ${source:Version}), ${misc:Depends} +Description: MariaDB database client (metapackage depending on the latest version) + This is an empty package that depends on the current "best" version of + mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB + maintainers. Install this package if in doubt about which MariaDB version + you want, as this is the one we consider to be in the best shape. + +Package: mariadb-test +Section: database +Architecture: all +Depends: mariadb-test-5.5 (= ${source:Version}) +Description: MariaDB database regression test suite (metapackage depending on the latest version) + This is an empty package that depends on the current "best" version of + mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB + maintainers. + diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.dirs b/debian/dist/Debian/mariadb-galera-server-5.5.dirs index 0e3b2ce5af8..39fa440b07f 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Debian/mariadb-galera-server-5.5.dirs @@ -6,6 +6,5 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-galera-server-5.5 -usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index fba6d8b2208..ed1ca3f71b9 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -1,4 +1,3 @@ -usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -69,31 +68,6 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index 2d3db49356f..ae22fdbfcc4 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -190,7 +190,9 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ + cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 + cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index f6a1e492008..5b76594f0e1 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -161,7 +161,7 @@ Description: MariaDB database core server files Package: mariadb-test-5.5 Section: database Architecture: any -Depends: mariadb-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) +Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) Suggests: patch Conflicts: mariadb-test (<< ${source:Version}), mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, @@ -215,3 +215,23 @@ Description: MariaDB database server with Galera cluster (metapackage depending server. SQL (Structured Query Language) is the most popular database query language in the world. The main goals of MariaDB are speed, robustness and ease of use. + +Package: mariadb-client +Section: database +Architecture: all +Depends: mariadb-client-5.5 (= ${source:Version}), ${misc:Depends} +Description: MariaDB database client (metapackage depending on the latest version) + This is an empty package that depends on the current "best" version of + mariadb-client (currently mariadb-client-5.5), as determined by the MariaDB + maintainers. Install this package if in doubt about which MariaDB version + you want, as this is the one we consider to be in the best shape. + +Package: mariadb-test +Section: database +Architecture: all +Depends: mariadb-test-5.5 (= ${source:Version}) +Description: MariaDB database regression test suite (metapackage depending on the latest version) + This is an empty package that depends on the current "best" version of + mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB + maintainers. + diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs index 0e3b2ce5af8..39fa440b07f 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.dirs @@ -6,6 +6,5 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-galera-server-5.5 -usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in index acf5acb036f..9ef18c4c0f2 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in @@ -1,4 +1,3 @@ -usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -71,31 +70,6 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 5e9609b6c8c..9b214e5422a 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -190,7 +190,9 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ + cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 + cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ diff --git a/debian/libmariadbclient-dev.README.Maintainer b/debian/libmariadbclient-dev.README.Maintainer new file mode 100644 index 00000000000..f24cdcd519d --- /dev/null +++ b/debian/libmariadbclient-dev.README.Maintainer @@ -0,0 +1,4 @@ +The examples directory includes files that might be needed by some +developers: +- header files not installed by default +- the example file udf_example.c diff --git a/debian/libmariadbclient-dev.dirs b/debian/libmariadbclient-dev.dirs new file mode 100644 index 00000000000..f6ad2870431 --- /dev/null +++ b/debian/libmariadbclient-dev.dirs @@ -0,0 +1,2 @@ +usr/include/ +usr/lib/ diff --git a/debian/libmariadbclient-dev.examples b/debian/libmariadbclient-dev.examples new file mode 100644 index 00000000000..f1649c311c4 --- /dev/null +++ b/debian/libmariadbclient-dev.examples @@ -0,0 +1 @@ +sql/udf_example.c diff --git a/debian/libmariadbclient-dev.files b/debian/libmariadbclient-dev.files new file mode 100644 index 00000000000..8f56a3065d5 --- /dev/null +++ b/debian/libmariadbclient-dev.files @@ -0,0 +1,7 @@ +usr/bin/mysql_config +usr/include/mysql +usr/lib/libmysqlclient.a +usr/lib/libmysqlclient_r.a +usr/lib/libmysqlservices.a +usr/share/aclocal/mysql.m4 +usr/share/man/man1/mysql_config.1 diff --git a/debian/libmariadbclient-dev.links b/debian/libmariadbclient-dev.links new file mode 100644 index 00000000000..0076791dcfa --- /dev/null +++ b/debian/libmariadbclient-dev.links @@ -0,0 +1,2 @@ +usr/lib/libmysqlclient.so.18 usr/lib/libmysqlclient.so +usr/lib/libmysqlclient_r.so.18 usr/lib/libmysqlclient_r.so diff --git a/debian/libmariadbclient18.dirs b/debian/libmariadbclient18.dirs new file mode 100644 index 00000000000..2964de6141b --- /dev/null +++ b/debian/libmariadbclient18.dirs @@ -0,0 +1 @@ +usr/lib/ diff --git a/debian/libmariadbclient18.files b/debian/libmariadbclient18.files new file mode 100644 index 00000000000..75020ecbd16 --- /dev/null +++ b/debian/libmariadbclient18.files @@ -0,0 +1,3 @@ +usr/lib/libmysqlclient*.so.* +usr/lib/mysql/plugin/mysql_clear_password.so +usr/lib/mysql/plugin/dialog.so diff --git a/debian/libmariadbclient18.postinst b/debian/libmariadbclient18.postinst new file mode 100644 index 00000000000..29d3b86f978 --- /dev/null +++ b/debian/libmariadbclient18.postinst @@ -0,0 +1,12 @@ +#!/bin/bash -e + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + +# vim: ts=4 + + diff --git a/debian/libmariadbd-dev.files b/debian/libmariadbd-dev.files new file mode 100644 index 00000000000..26cb8d0a606 --- /dev/null +++ b/debian/libmariadbd-dev.files @@ -0,0 +1,2 @@ +usr/lib/mysql/*.a +usr/lib/mysql/*.la diff --git a/debian/mariadb-client-5.5.README.Debian b/debian/mariadb-client-5.5.README.Debian new file mode 100644 index 00000000000..b245638f9c9 --- /dev/null +++ b/debian/mariadb-client-5.5.README.Debian @@ -0,0 +1,4 @@ +FAQ: + +Q: My completition is gone, why? +A: You have "no-auto-rehash" in the "[mysql]" section of /etc/mysql/my.cnf! diff --git a/debian/mariadb-client-5.5.dirs b/debian/mariadb-client-5.5.dirs new file mode 100644 index 00000000000..ceda5922c5d --- /dev/null +++ b/debian/mariadb-client-5.5.dirs @@ -0,0 +1,3 @@ +usr/bin/ +usr/share/man/man1/ +usr/share/perl5/ diff --git a/debian/mariadb-client-5.5.docs b/debian/mariadb-client-5.5.docs new file mode 100644 index 00000000000..21446855f51 --- /dev/null +++ b/debian/mariadb-client-5.5.docs @@ -0,0 +1,2 @@ +debian/additions/innotop/changelog.innotop +README diff --git a/debian/mariadb-client-5.5.files b/debian/mariadb-client-5.5.files new file mode 100644 index 00000000000..9cb949ea53e --- /dev/null +++ b/debian/mariadb-client-5.5.files @@ -0,0 +1,31 @@ +usr/bin/innochecksum +usr/bin/innotop +usr/bin/mysqlaccess +usr/bin/mysqladmin +usr/bin/mysqlbug +usr/bin/mysqldump +usr/bin/mysqldumpslow +usr/bin/mysql_find_rows +usr/bin/mysql_fix_extensions +usr/bin/mysqlimport +usr/bin/mysqlreport +usr/bin/mysqlshow +usr/bin/mysqlslap +usr/bin/mysql_waitpid +usr/share/lintian/overrides/mariadb-client-5.5 +usr/share/man/man1/innotop.1 +usr/share/man/man1/mysqlaccess.1 +usr/share/man/man1/mysqladmin.1 +usr/share/man/man1/mysqlbug.1 +usr/share/man/man1/mysqldump.1 +usr/share/man/man1/mysqldumpslow.1 +usr/share/man/man1/mysql_find_rows.1 +usr/share/man/man1/mysql_fix_extensions.1 +usr/share/man/man1/mysqlimport.1 +usr/share/man/man1/mysqlman.1 +usr/share/man/man1/mysqlreport.1 +usr/share/man/man1/mysqlshow.1 +usr/share/man/man1/mysqlslap.1 +usr/share/man/man1/mysql_tableinfo.1 +usr/share/man/man1/mysql_waitpid.1 +usr/share/man/man8/mysqlmanager.8 diff --git a/debian/mariadb-client-5.5.links b/debian/mariadb-client-5.5.links new file mode 100644 index 00000000000..247369fa218 --- /dev/null +++ b/debian/mariadb-client-5.5.links @@ -0,0 +1,3 @@ +usr/bin/mysqlcheck usr/bin/mysqlrepair +usr/bin/mysqlcheck usr/bin/mysqlanalyze +usr/bin/mysqlcheck usr/bin/mysqloptimize diff --git a/debian/mariadb-client-5.5.lintian-overrides b/debian/mariadb-client-5.5.lintian-overrides new file mode 100644 index 00000000000..d4dc1a70b1e --- /dev/null +++ b/debian/mariadb-client-5.5.lintian-overrides @@ -0,0 +1,3 @@ +mariadb-client-5.3: package-has-a-duplicate-relation +mariadb-client-5.3: wrong-name-for-upstream-changelog usr/share/doc/mariadb-client-5.3/changelog.innotop.gz +mariadb-client-5.3: pkg-not-in-package-test innotop diff --git a/debian/mariadb-client-5.5.menu b/debian/mariadb-client-5.5.menu new file mode 100644 index 00000000000..1378555c423 --- /dev/null +++ b/debian/mariadb-client-5.5.menu @@ -0,0 +1,3 @@ +# According to /usr/share/menu/ policy 1.4, not /usr/share/doc/debian-policy/ +?package(innotop):needs="text" section="Applications/Data Management"\ + title="innotop" command="/usr/bin/innotop" diff --git a/debian/mariadb-client-core-5.5.files b/debian/mariadb-client-core-5.5.files new file mode 100644 index 00000000000..a2781309439 --- /dev/null +++ b/debian/mariadb-client-core-5.5.files @@ -0,0 +1,4 @@ +usr/bin/mysql +usr/bin/mysqlcheck +usr/share/man/man1/mysql.1 +usr/share/man/man1/mysqlcheck.1 diff --git a/debian/mariadb-common.files b/debian/mariadb-common.files new file mode 100644 index 00000000000..f37e46c45fe --- /dev/null +++ b/debian/mariadb-common.files @@ -0,0 +1 @@ +etc/mysql/conf.d/mariadb.cnf diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm new file mode 100644 index 00000000000..027592f816e --- /dev/null +++ b/debian/mariadb-common.postrm @@ -0,0 +1,8 @@ +#!/bin/bash -e + +if [ "$1" = "purge" ]; then + rmdir /etc/mysql/conf.d 2>/dev/null || true + rmdir /etc/mysql 2>/dev/null || true +fi + +#DEBHELPER# diff --git a/debian/mariadb-server-core-5.5.files b/debian/mariadb-server-core-5.5.files new file mode 100644 index 00000000000..5c60ca5ec67 --- /dev/null +++ b/debian/mariadb-server-core-5.5.files @@ -0,0 +1,26 @@ +usr/sbin/mysqld +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian diff --git a/debian/mariadb-test-5.5.dirs b/debian/mariadb-test-5.5.dirs new file mode 100644 index 00000000000..2ab1fb61def --- /dev/null +++ b/debian/mariadb-test-5.5.dirs @@ -0,0 +1,101 @@ +usr/bin +usr/share/man/man1 +usr/share/mysql/mysql-test +usr/share/mysql/mysql-test/extra +usr/share/mysql/mysql-test/extra/binlog_tests +usr/share/mysql/mysql-test/extra/rpl_tests +usr/share/mysql/mysql-test/lib +usr/share/mysql/mysql-test/lib/My +usr/share/mysql/mysql-test/lib/My/SafeProcess +usr/share/mysql/mysql-test/lib/My/File +usr/share/mysql/mysql-test/lib/v1 +usr/share/mysql/mysql-test/lib/v1/My +usr/share/mysql/mysql-test/collections +usr/share/mysql/mysql-test/t +usr/share/mysql/mysql-test/r +usr/share/mysql/mysql-test/include +usr/share/mysql/mysql-test/suite +usr/share/mysql/mysql-test/suite/parts +usr/share/mysql/mysql-test/suite/parts/inc +usr/share/mysql/mysql-test/suite/parts/t +usr/share/mysql/mysql-test/suite/parts/r +usr/share/mysql/mysql-test/suite/rpl_ndb +usr/share/mysql/mysql-test/suite/rpl_ndb/t +usr/share/mysql/mysql-test/suite/rpl_ndb/r +usr/share/mysql/mysql-test/suite/bugs +usr/share/mysql/mysql-test/suite/bugs/t +usr/share/mysql/mysql-test/suite/bugs/r +usr/share/mysql/mysql-test/suite/bugs/data +usr/share/mysql/mysql-test/suite/rpl +usr/share/mysql/mysql-test/suite/rpl/t +usr/share/mysql/mysql-test/suite/rpl/r +usr/share/mysql/mysql-test/suite/rpl/include +usr/share/mysql/mysql-test/suite/innodb +usr/share/mysql/mysql-test/suite/innodb/t +usr/share/mysql/mysql-test/suite/innodb/r +usr/share/mysql/mysql-test/suite/innodb/include +usr/share/mysql/mysql-test/suite/manual +usr/share/mysql/mysql-test/suite/manual/t +usr/share/mysql/mysql-test/suite/manual/r +usr/share/mysql/mysql-test/suite/stress +usr/share/mysql/mysql-test/suite/stress/t +usr/share/mysql/mysql-test/suite/stress/r +usr/share/mysql/mysql-test/suite/stress/include +usr/share/mysql/mysql-test/suite/jp +usr/share/mysql/mysql-test/suite/jp/t +usr/share/mysql/mysql-test/suite/jp/r +usr/share/mysql/mysql-test/suite/jp/include +usr/share/mysql/mysql-test/suite/jp/std_data +usr/share/mysql/mysql-test/suite/ndb +usr/share/mysql/mysql-test/suite/ndb/t +usr/share/mysql/mysql-test/suite/ndb/r +usr/share/mysql/mysql-test/suite/maria +usr/share/mysql/mysql-test/suite/maria/t +usr/share/mysql/mysql-test/suite/maria/r +usr/share/mysql/mysql-test/suite/funcs_2 +usr/share/mysql/mysql-test/suite/funcs_2/lib +usr/share/mysql/mysql-test/suite/funcs_2/t +usr/share/mysql/mysql-test/suite/funcs_2/charset +usr/share/mysql/mysql-test/suite/funcs_2/r +usr/share/mysql/mysql-test/suite/funcs_2/include +usr/share/mysql/mysql-test/suite/funcs_2/data +usr/share/mysql/mysql-test/suite/binlog +usr/share/mysql/mysql-test/suite/binlog/t +usr/share/mysql/mysql-test/suite/binlog/r +usr/share/mysql/mysql-test/suite/binlog/std_data +usr/share/mysql/mysql-test/suite/ndb_team +usr/share/mysql/mysql-test/suite/ndb_team/t +usr/share/mysql/mysql-test/suite/ndb_team/r +usr/share/mysql/mysql-test/suite/federated +usr/share/mysql/mysql-test/suite/funcs_1 +usr/share/mysql/mysql-test/suite/funcs_1/cursors +usr/share/mysql/mysql-test/suite/funcs_1/bitdata +usr/share/mysql/mysql-test/suite/funcs_1/views +usr/share/mysql/mysql-test/suite/funcs_1/storedproc +usr/share/mysql/mysql-test/suite/funcs_1/triggers +usr/share/mysql/mysql-test/suite/funcs_1/lib +usr/share/mysql/mysql-test/suite/funcs_1/t +usr/share/mysql/mysql-test/suite/funcs_1/r +usr/share/mysql/mysql-test/suite/funcs_1/include +usr/share/mysql/mysql-test/suite/funcs_1/datadict +usr/share/mysql/mysql-test/suite/vcol +usr/share/mysql/mysql-test/suite/vcol/inc +usr/share/mysql/mysql-test/suite/vcol/t +usr/share/mysql/mysql-test/suite/vcol/r +usr/share/mysql/mysql-test/suite/oqgraph +usr/share/mysql/mysql-test/suite/oqgraph/t +usr/share/mysql/mysql-test/suite/oqgraph/r +usr/share/mysql/mysql-test/suite/oqgraph/include +usr/share/mysql/mysql-test/suite/galera +usr/share/mysql/mysql-test/suite/galera/t +usr/share/mysql/mysql-test/suite/galera/r +usr/share/mysql/mysql-test/suite/wsrep +usr/share/mysql/mysql-test/suite/wsrep/t +usr/share/mysql/mysql-test/suite/wsrep/r +usr/share/mysql/mysql-test/std_data +usr/share/mysql/mysql-test/std_data/ndb_backup50 +usr/share/mysql/mysql-test/std_data/parts +usr/share/mysql/mysql-test/std_data/ndb_backup51_data_le +usr/share/mysql/mysql-test/std_data/ndb_backup51_data_be +usr/share/mysql/mysql-test/std_data/ndb_backup51 +usr/share/mysql/mysql-test/std_data/funcs_1 diff --git a/debian/mariadb-test-5.5.files b/debian/mariadb-test-5.5.files new file mode 100644 index 00000000000..79eb9520607 --- /dev/null +++ b/debian/mariadb-test-5.5.files @@ -0,0 +1,15 @@ +usr/lib/mysql/plugin/dialog_examples.so +usr/lib/mysql/plugin/auth_test_plugin.so +usr/lib/mysql/plugin/qa_auth_interface.so +usr/lib/mysql/plugin/qa_auth_server.so +usr/lib/mysql/plugin/qa_auth_client.so +usr/lib/mysql/plugin/auth_0x0100.so +usr/lib/mysql/plugin/mypluglib.so +usr/lib/mysql/plugin/daemon_example.ini +usr/lib/mysql/plugin/libdaemon_example.so +usr/lib/mysql/plugin/adt_null.so +usr/bin/mysql_client_test +usr/share/man/man1/mysql_client_test.1 +usr/bin/mysqltest +usr/share/man/man1/mysqltest.1 +usr/share/mysql/mysql-test diff --git a/debian/mariadb-test-5.5.links b/debian/mariadb-test-5.5.links new file mode 100644 index 00000000000..082680fe5ed --- /dev/null +++ b/debian/mariadb-test-5.5.links @@ -0,0 +1,2 @@ +usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mysql-test-run +usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mtr diff --git a/debian/mysql-common.dirs b/debian/mysql-common.dirs new file mode 100644 index 00000000000..a5a88ede9c1 --- /dev/null +++ b/debian/mysql-common.dirs @@ -0,0 +1 @@ +etc/mysql/conf.d/ diff --git a/debian/mysql-common.files b/debian/mysql-common.files new file mode 100644 index 00000000000..d167569e892 --- /dev/null +++ b/debian/mysql-common.files @@ -0,0 +1,3 @@ +etc/mysql/my.cnf +usr/share/mysql-common/internal-use-only +usr/share/lintian/overrides/mysql-common diff --git a/debian/mysql-common.lintian-overrides b/debian/mysql-common.lintian-overrides new file mode 100644 index 00000000000..c6c60ccdc71 --- /dev/null +++ b/debian/mysql-common.lintian-overrides @@ -0,0 +1,2 @@ +script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_init.d_mysql +script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_mysql_debian-start diff --git a/debian/mysql-common.postrm b/debian/mysql-common.postrm new file mode 100644 index 00000000000..0d3f8aed83d --- /dev/null +++ b/debian/mysql-common.postrm @@ -0,0 +1,7 @@ +#!/bin/bash -e + +if [ "$1" = "purge" ]; then + rmdir /etc/mysql 2>/dev/null || true +fi + +#DEBHELPER# From 4154f3aa058ee4fb7a7633874038c122a5e8985a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Mar 2014 17:54:53 -0400 Subject: [PATCH 127/294] Modified debian scripts to make galera packages self-contained. --- debian/dist/Debian/control | 181 +----------------- .../Debian/mariadb-galera-server-5.5.files.in | 26 +++ debian/dist/Debian/rules | 2 - debian/dist/Ubuntu/control | 175 +---------------- .../Ubuntu/mariadb-galera-server-5.5.files.in | 26 +++ debian/dist/Ubuntu/rules | 2 - debian/libmariadbclient-dev.README.Maintainer | 4 - debian/libmariadbclient-dev.dirs | 2 - debian/libmariadbclient-dev.examples | 1 - debian/libmariadbclient-dev.files | 7 - debian/libmariadbclient-dev.links | 2 - debian/libmariadbclient18.dirs | 1 - debian/libmariadbclient18.files | 3 - debian/libmariadbclient18.postinst | 12 -- debian/libmariadbd-dev.files | 2 - debian/mariadb-client-5.5.README.Debian | 4 - debian/mariadb-client-5.5.dirs | 3 - debian/mariadb-client-5.5.docs | 2 - debian/mariadb-client-5.5.files | 31 --- debian/mariadb-client-5.5.links | 3 - debian/mariadb-client-5.5.lintian-overrides | 3 - debian/mariadb-client-5.5.menu | 3 - debian/mariadb-client-core-5.5.files | 4 - debian/mariadb-common.files | 1 - debian/mariadb-common.postrm | 8 - debian/mariadb-server-core-5.5.files | 26 --- debian/mariadb-test-5.5.dirs | 101 ---------- debian/mariadb-test-5.5.files | 15 -- debian/mariadb-test-5.5.links | 2 - debian/mysql-common.dirs | 1 - debian/mysql-common.files | 3 - debian/mysql-common.lintian-overrides | 2 - debian/mysql-common.postrm | 7 - 33 files changed, 64 insertions(+), 601 deletions(-) delete mode 100644 debian/libmariadbclient-dev.README.Maintainer delete mode 100644 debian/libmariadbclient-dev.dirs delete mode 100644 debian/libmariadbclient-dev.examples delete mode 100644 debian/libmariadbclient-dev.files delete mode 100644 debian/libmariadbclient-dev.links delete mode 100644 debian/libmariadbclient18.dirs delete mode 100644 debian/libmariadbclient18.files delete mode 100644 debian/libmariadbclient18.postinst delete mode 100644 debian/libmariadbd-dev.files delete mode 100644 debian/mariadb-client-5.5.README.Debian delete mode 100644 debian/mariadb-client-5.5.dirs delete mode 100644 debian/mariadb-client-5.5.docs delete mode 100644 debian/mariadb-client-5.5.files delete mode 100644 debian/mariadb-client-5.5.links delete mode 100644 debian/mariadb-client-5.5.lintian-overrides delete mode 100644 debian/mariadb-client-5.5.menu delete mode 100644 debian/mariadb-client-core-5.5.files delete mode 100644 debian/mariadb-common.files delete mode 100644 debian/mariadb-common.postrm delete mode 100644 debian/mariadb-server-core-5.5.files delete mode 100644 debian/mariadb-test-5.5.dirs delete mode 100644 debian/mariadb-test-5.5.files delete mode 100644 debian/mariadb-test-5.5.links delete mode 100644 debian/mysql-common.dirs delete mode 100644 debian/mysql-common.files delete mode 100644 debian/mysql-common.lintian-overrides delete mode 100644 debian/mysql-common.postrm diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 021246d51f5..9a6f4b9f881 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -10,193 +10,25 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria -Package: libmariadbclient18 -Section: libs -Architecture: any -Depends: mariadb-common, libmysqlclient18 (= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Conflicts: mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33), - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 -Description: MariaDB database client library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client library. - -Package: libmysqlclient18 -Section: libs -Architecture: any -Depends: libmariadbclient18 (= ${source:Version}) -Replaces: libmysqlclient18 (<< ${source:Version}) -Description: Virtual package to satisfy external depends - This is an empty package that provides an updated "best" version of - libmysqlclient18 that does not conflict with the libmariadbclient18 - package. - . - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - -Package: libmariadbd-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient-dev (>= ${source:Version}), ${misc:Depends} -Provides: libmysqld-dev -Conflicts: libmysqld-dev -Replaces: libmysqld-dev -Description: MariaDB embedded database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the embedded server library and header files. - -Package: libmariadbclient-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient18 (>= ${source:Version}), zlib1g-dev, , ${shlibs:Depends}, ${misc:Depends} -Replaces: libmariadbclient16-dev, libmysqlclient16-dev -Conflicts: libmysqlclient-dev, libmariadbclient16-dev, libmysqlclient14-dev, libmysqlclient12-dev, libmysqlclient10-dev, libmysqlclient15-dev, libmysqlclient16-dev -Provides: libmysqlclient-dev -Description: MariaDB database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes development libraries and header files. - -Package: mysql-common -Section: database -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/my.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/my.cnf). - -Package: mariadb-common -Section: database -Architecture: all -Depends: mysql-common, ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/conf.d/mariadb.cnf). - -Package: mariadb-client-core-5.5 -Architecture: any -Depends: mariadb-common, libmariadbclient18 (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Provides: mysql-client-core, mysql-client-core-5.1, mysql-client-core-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1 (<< ${source:Version}), mysql-client-5.5 (<< ${source:Version}), - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1, mysql-client-5.5, - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Description: MariaDB database core client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core client files, as used by Akonadi. - -Package: mariadb-client-5.5 -Architecture: any -Depends: debianutils (>=1.6), libdbi-perl, libdbd-mysql-perl (>= 1.2202), mariadb-common, libmariadbclient18 (>= ${source:Version}), mariadb-client-core-5.5 (>= ${source:Version}), ${perl:Depends}, ${shlibs:Depends}, ${misc:Depends} -Provides: virtual-mysql-client, mysql-client, - mysql-client-4.1, mysql-client-5.1, mysql-client-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, mysql-client-5.5 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mysql-client-5.5, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3 -Description: MariaDB database client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client binaries and the additional tools - innotop and mysqlreport. - -Package: mariadb-server-core-5.5 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5 -Conflicts: mariadb-server-5.1 (<< 5.1.60), - mariadb-server-5.2 (<< 5.2.10), - mariadb-server-5.3 (<< 5.3.3), - mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Replaces: mariadb-server-5.1 (<< 5.1.60), - mariadb-server-5.2 (<< 5.2.10), - mariadb-server-5.3 (<< 5.3.3), - mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Description: MariaDB database core server files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core server files, as used by Akonadi. - -Package: mariadb-test-5.5 -Section: database -Architecture: any -Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) -Conflicts: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, - mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33) -Suggests: patch -Replaces: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Description: MariaDB database regression test suite - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the regression test suite. - Package: mariadb-galera-server-5.5 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}), galera (>=25.2) -Provides: mariadb-server, mysql-server, virtual-mysql-server, mariadb-galera-server +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) +Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database @@ -240,4 +72,3 @@ Description: MariaDB database regression test suite (metapackage depending on th This is an empty package that depends on the current "best" version of mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB maintainers. - diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index ed1ca3f71b9..fba6d8b2208 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -68,6 +69,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index ae22fdbfcc4..2d3db49356f 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -190,9 +190,7 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 - cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 5b76594f0e1..178771319a2 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -10,187 +10,25 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria -Package: libmariadbclient18 -Section: libs -Architecture: any -Depends: mariadb-common, libmysqlclient18 (= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Conflicts: mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33), - mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3 -Description: MariaDB database client library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client library. - -Package: libmysqlclient18 -Section: libs -Architecture: any -Depends: libmariadbclient18 (= ${source:Version}) -Replaces: libmysqlclient18 (<< ${source:Version}) -Description: Virtual package to satisfy external depends - This is an empty package that provides an updated "best" version of - libmysqlclient18 that does not conflict with the libmariadbclient18 - package. - . - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - -Package: libmariadbd-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient-dev (>= ${source:Version}), ${misc:Depends} -Provides: libmysqld-dev -Conflicts: libmysqld-dev -Replaces: libmysqld-dev -Description: MariaDB embedded database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the embedded server library and header files. - -Package: libmariadbclient-dev -Architecture: any -Section: libdevel -Depends: libmariadbclient18 (>= ${source:Version}), zlib1g-dev, , ${shlibs:Depends}, ${misc:Depends} -Replaces: libmariadbclient16-dev, libmysqlclient16-dev -Conflicts: libmysqlclient-dev, libmariadbclient16-dev, libmysqlclient14-dev, libmysqlclient12-dev, libmysqlclient10-dev, libmysqlclient15-dev, libmysqlclient16-dev -Provides: libmysqlclient-dev -Description: MariaDB database development files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes development libraries and header files. - -Package: mysql-common -Section: database -Architecture: all -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/my.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/my.cnf). - -Package: mariadb-common -Section: database -Architecture: all -Depends: mysql-common, ${shlibs:Depends}, ${misc:Depends} -Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes files needed by all versions of the client library - (e.g. /etc/mysql/conf.d/mariadb.cnf). - -Package: mariadb-client-core-5.5 -Architecture: any -Depends: mariadb-common, libmariadbclient18 (>= ${source:Version}), ${shlibs:Depends}, ${misc:Depends} -Provides: mysql-client-core, mysql-client-core-5.1, mysql-client-core-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1 (<< ${source:Version}), mysql-client-5.5 (<< ${source:Version}), - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, - mysql-client-5.1, mysql-client-5.5, - mysql-client-core-5.1, mysql-client-core-5.5, - mariadb-client-5.1, mariadb-client-core-5.1, - mariadb-client-5.2, mariadb-client-core-5.2, - mariadb-client-5.3, mariadb-client-core-5.3 -Description: MariaDB database core client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core client files, as used by Akonadi. - -Package: mariadb-client-5.5 -Architecture: any -Depends: debianutils (>=1.6), libdbi-perl, libdbd-mysql-perl (>= 1.2202), mariadb-common, libmariadbclient18 (>= ${source:Version}), mariadb-client-core-5.5 (>= ${source:Version}), ${perl:Depends}, ${shlibs:Depends}, ${misc:Depends} -Provides: virtual-mysql-client, mysql-client, - mysql-client-4.1, mysql-client-5.1, mysql-client-5.5 -Conflicts: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, mysql-client-5.5 -Replaces: mysql-client (<< 5.0.51), mysql-client-5.0, mysql-client-5.1, - mysql-client-5.5, - mariadb-client (<< ${source:Version}), - mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3 -Description: MariaDB database client binaries - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client binaries and the additional tools - innotop and mysqlreport. - -Package: mariadb-server-core-5.5 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libmariadbclient18 (>= ${binary:Version}) -Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5 -Conflicts: mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Replaces: mysql-server-5.0, - mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, - mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5 -Description: MariaDB database core server files - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the core server files, as used by Akonadi. - -Package: mariadb-test-5.5 -Section: database -Architecture: any -Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (= ${source:Version}) -Suggests: patch -Conflicts: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, - mariadb-server-5.5 (<< 5.5.33), mariadb-galera-server-5.5 (<< 5.5.33) -Replaces: mariadb-test (<< ${source:Version}), - mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 -Description: MariaDB database regression test suite - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the regression test suite. - Package: mariadb-galera-server-5.5 Architecture: any Suggests: tinyca, mailx, mariadb-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-5.5 (>= ${binary:Version}), galera (>=25.2) -Provides: mariadb-server, mysql-server, virtual-mysql-server, mariadb-galera-server +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) +Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Replaces: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, libmariadbclient16 (<< 5.3.4), libmariadbclient-dev (<< 5.5.0), + mysql-server-core-5.0, mysql-server-core-5.1, mysql-server-core-5.5, + mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.5, mariadb-tokudb-engine-5.5 Description: MariaDB database server with Galera cluster binaries MariaDB is a fast, stable and true multi-user, multi-threaded SQL database @@ -234,4 +72,3 @@ Description: MariaDB database regression test suite (metapackage depending on th This is an empty package that depends on the current "best" version of mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB maintainers. - diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in index 9ef18c4c0f2..acf5acb036f 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in @@ -1,3 +1,4 @@ +usr/sbin/mysqld usr/lib/mysql/plugin/ha_innodb.so usr/lib/mysql/plugin/ha_oqgraph.so usr/lib/mysql/plugin/sphinx.so @@ -70,6 +71,31 @@ usr/share/man/man1/resolveip.1 usr/share/man/man1/resolve_stack_dump.1 usr/share/man/man1/innochecksum.1 usr/share/man/man1/mysql_tzinfo_to_sql.1 +usr/share/man/man8/mysqld.8 +usr/share/mysql/charsets +usr/share/mysql/czech +usr/share/mysql/danish +usr/share/mysql/dutch +usr/share/mysql/english +usr/share/mysql/estonian +usr/share/mysql/french +usr/share/mysql/german +usr/share/mysql/greek +usr/share/mysql/hungarian +usr/share/mysql/italian +usr/share/mysql/japanese +usr/share/mysql/korean +usr/share/mysql/norwegian +usr/share/mysql/norwegian-ny +usr/share/mysql/polish +usr/share/mysql/portuguese +usr/share/mysql/romanian +usr/share/mysql/russian +usr/share/mysql/serbian +usr/share/mysql/slovak +usr/share/mysql/spanish +usr/share/mysql/swedish +usr/share/mysql/ukrainian usr/share/mysql/debian-start.inc.sh usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 9b214e5422a..5e9609b6c8c 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -190,9 +190,7 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common cp debian/mariadb-galera-server-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-galera-server-5.5 - cp debian/mariadb-client-5.5.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-5.5 # For 5.0 -> 5.5 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ diff --git a/debian/libmariadbclient-dev.README.Maintainer b/debian/libmariadbclient-dev.README.Maintainer deleted file mode 100644 index f24cdcd519d..00000000000 --- a/debian/libmariadbclient-dev.README.Maintainer +++ /dev/null @@ -1,4 +0,0 @@ -The examples directory includes files that might be needed by some -developers: -- header files not installed by default -- the example file udf_example.c diff --git a/debian/libmariadbclient-dev.dirs b/debian/libmariadbclient-dev.dirs deleted file mode 100644 index f6ad2870431..00000000000 --- a/debian/libmariadbclient-dev.dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/include/ -usr/lib/ diff --git a/debian/libmariadbclient-dev.examples b/debian/libmariadbclient-dev.examples deleted file mode 100644 index f1649c311c4..00000000000 --- a/debian/libmariadbclient-dev.examples +++ /dev/null @@ -1 +0,0 @@ -sql/udf_example.c diff --git a/debian/libmariadbclient-dev.files b/debian/libmariadbclient-dev.files deleted file mode 100644 index 8f56a3065d5..00000000000 --- a/debian/libmariadbclient-dev.files +++ /dev/null @@ -1,7 +0,0 @@ -usr/bin/mysql_config -usr/include/mysql -usr/lib/libmysqlclient.a -usr/lib/libmysqlclient_r.a -usr/lib/libmysqlservices.a -usr/share/aclocal/mysql.m4 -usr/share/man/man1/mysql_config.1 diff --git a/debian/libmariadbclient-dev.links b/debian/libmariadbclient-dev.links deleted file mode 100644 index 0076791dcfa..00000000000 --- a/debian/libmariadbclient-dev.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/libmysqlclient.so.18 usr/lib/libmysqlclient.so -usr/lib/libmysqlclient_r.so.18 usr/lib/libmysqlclient_r.so diff --git a/debian/libmariadbclient18.dirs b/debian/libmariadbclient18.dirs deleted file mode 100644 index 2964de6141b..00000000000 --- a/debian/libmariadbclient18.dirs +++ /dev/null @@ -1 +0,0 @@ -usr/lib/ diff --git a/debian/libmariadbclient18.files b/debian/libmariadbclient18.files deleted file mode 100644 index 75020ecbd16..00000000000 --- a/debian/libmariadbclient18.files +++ /dev/null @@ -1,3 +0,0 @@ -usr/lib/libmysqlclient*.so.* -usr/lib/mysql/plugin/mysql_clear_password.so -usr/lib/mysql/plugin/dialog.so diff --git a/debian/libmariadbclient18.postinst b/debian/libmariadbclient18.postinst deleted file mode 100644 index 29d3b86f978..00000000000 --- a/debian/libmariadbclient18.postinst +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -e - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - -# vim: ts=4 - - diff --git a/debian/libmariadbd-dev.files b/debian/libmariadbd-dev.files deleted file mode 100644 index 26cb8d0a606..00000000000 --- a/debian/libmariadbd-dev.files +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/mysql/*.a -usr/lib/mysql/*.la diff --git a/debian/mariadb-client-5.5.README.Debian b/debian/mariadb-client-5.5.README.Debian deleted file mode 100644 index b245638f9c9..00000000000 --- a/debian/mariadb-client-5.5.README.Debian +++ /dev/null @@ -1,4 +0,0 @@ -FAQ: - -Q: My completition is gone, why? -A: You have "no-auto-rehash" in the "[mysql]" section of /etc/mysql/my.cnf! diff --git a/debian/mariadb-client-5.5.dirs b/debian/mariadb-client-5.5.dirs deleted file mode 100644 index ceda5922c5d..00000000000 --- a/debian/mariadb-client-5.5.dirs +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/ -usr/share/man/man1/ -usr/share/perl5/ diff --git a/debian/mariadb-client-5.5.docs b/debian/mariadb-client-5.5.docs deleted file mode 100644 index 21446855f51..00000000000 --- a/debian/mariadb-client-5.5.docs +++ /dev/null @@ -1,2 +0,0 @@ -debian/additions/innotop/changelog.innotop -README diff --git a/debian/mariadb-client-5.5.files b/debian/mariadb-client-5.5.files deleted file mode 100644 index 9cb949ea53e..00000000000 --- a/debian/mariadb-client-5.5.files +++ /dev/null @@ -1,31 +0,0 @@ -usr/bin/innochecksum -usr/bin/innotop -usr/bin/mysqlaccess -usr/bin/mysqladmin -usr/bin/mysqlbug -usr/bin/mysqldump -usr/bin/mysqldumpslow -usr/bin/mysql_find_rows -usr/bin/mysql_fix_extensions -usr/bin/mysqlimport -usr/bin/mysqlreport -usr/bin/mysqlshow -usr/bin/mysqlslap -usr/bin/mysql_waitpid -usr/share/lintian/overrides/mariadb-client-5.5 -usr/share/man/man1/innotop.1 -usr/share/man/man1/mysqlaccess.1 -usr/share/man/man1/mysqladmin.1 -usr/share/man/man1/mysqlbug.1 -usr/share/man/man1/mysqldump.1 -usr/share/man/man1/mysqldumpslow.1 -usr/share/man/man1/mysql_find_rows.1 -usr/share/man/man1/mysql_fix_extensions.1 -usr/share/man/man1/mysqlimport.1 -usr/share/man/man1/mysqlman.1 -usr/share/man/man1/mysqlreport.1 -usr/share/man/man1/mysqlshow.1 -usr/share/man/man1/mysqlslap.1 -usr/share/man/man1/mysql_tableinfo.1 -usr/share/man/man1/mysql_waitpid.1 -usr/share/man/man8/mysqlmanager.8 diff --git a/debian/mariadb-client-5.5.links b/debian/mariadb-client-5.5.links deleted file mode 100644 index 247369fa218..00000000000 --- a/debian/mariadb-client-5.5.links +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/mysqlcheck usr/bin/mysqlrepair -usr/bin/mysqlcheck usr/bin/mysqlanalyze -usr/bin/mysqlcheck usr/bin/mysqloptimize diff --git a/debian/mariadb-client-5.5.lintian-overrides b/debian/mariadb-client-5.5.lintian-overrides deleted file mode 100644 index d4dc1a70b1e..00000000000 --- a/debian/mariadb-client-5.5.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -mariadb-client-5.3: package-has-a-duplicate-relation -mariadb-client-5.3: wrong-name-for-upstream-changelog usr/share/doc/mariadb-client-5.3/changelog.innotop.gz -mariadb-client-5.3: pkg-not-in-package-test innotop diff --git a/debian/mariadb-client-5.5.menu b/debian/mariadb-client-5.5.menu deleted file mode 100644 index 1378555c423..00000000000 --- a/debian/mariadb-client-5.5.menu +++ /dev/null @@ -1,3 +0,0 @@ -# According to /usr/share/menu/ policy 1.4, not /usr/share/doc/debian-policy/ -?package(innotop):needs="text" section="Applications/Data Management"\ - title="innotop" command="/usr/bin/innotop" diff --git a/debian/mariadb-client-core-5.5.files b/debian/mariadb-client-core-5.5.files deleted file mode 100644 index a2781309439..00000000000 --- a/debian/mariadb-client-core-5.5.files +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin/mysql -usr/bin/mysqlcheck -usr/share/man/man1/mysql.1 -usr/share/man/man1/mysqlcheck.1 diff --git a/debian/mariadb-common.files b/debian/mariadb-common.files deleted file mode 100644 index f37e46c45fe..00000000000 --- a/debian/mariadb-common.files +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/mariadb.cnf diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm deleted file mode 100644 index 027592f816e..00000000000 --- a/debian/mariadb-common.postrm +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql/conf.d 2>/dev/null || true - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# diff --git a/debian/mariadb-server-core-5.5.files b/debian/mariadb-server-core-5.5.files deleted file mode 100644 index 5c60ca5ec67..00000000000 --- a/debian/mariadb-server-core-5.5.files +++ /dev/null @@ -1,26 +0,0 @@ -usr/sbin/mysqld -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian diff --git a/debian/mariadb-test-5.5.dirs b/debian/mariadb-test-5.5.dirs deleted file mode 100644 index 2ab1fb61def..00000000000 --- a/debian/mariadb-test-5.5.dirs +++ /dev/null @@ -1,101 +0,0 @@ -usr/bin -usr/share/man/man1 -usr/share/mysql/mysql-test -usr/share/mysql/mysql-test/extra -usr/share/mysql/mysql-test/extra/binlog_tests -usr/share/mysql/mysql-test/extra/rpl_tests -usr/share/mysql/mysql-test/lib -usr/share/mysql/mysql-test/lib/My -usr/share/mysql/mysql-test/lib/My/SafeProcess -usr/share/mysql/mysql-test/lib/My/File -usr/share/mysql/mysql-test/lib/v1 -usr/share/mysql/mysql-test/lib/v1/My -usr/share/mysql/mysql-test/collections -usr/share/mysql/mysql-test/t -usr/share/mysql/mysql-test/r -usr/share/mysql/mysql-test/include -usr/share/mysql/mysql-test/suite -usr/share/mysql/mysql-test/suite/parts -usr/share/mysql/mysql-test/suite/parts/inc -usr/share/mysql/mysql-test/suite/parts/t -usr/share/mysql/mysql-test/suite/parts/r -usr/share/mysql/mysql-test/suite/rpl_ndb -usr/share/mysql/mysql-test/suite/rpl_ndb/t -usr/share/mysql/mysql-test/suite/rpl_ndb/r -usr/share/mysql/mysql-test/suite/bugs -usr/share/mysql/mysql-test/suite/bugs/t -usr/share/mysql/mysql-test/suite/bugs/r -usr/share/mysql/mysql-test/suite/bugs/data -usr/share/mysql/mysql-test/suite/rpl -usr/share/mysql/mysql-test/suite/rpl/t -usr/share/mysql/mysql-test/suite/rpl/r -usr/share/mysql/mysql-test/suite/rpl/include -usr/share/mysql/mysql-test/suite/innodb -usr/share/mysql/mysql-test/suite/innodb/t -usr/share/mysql/mysql-test/suite/innodb/r -usr/share/mysql/mysql-test/suite/innodb/include -usr/share/mysql/mysql-test/suite/manual -usr/share/mysql/mysql-test/suite/manual/t -usr/share/mysql/mysql-test/suite/manual/r -usr/share/mysql/mysql-test/suite/stress -usr/share/mysql/mysql-test/suite/stress/t -usr/share/mysql/mysql-test/suite/stress/r -usr/share/mysql/mysql-test/suite/stress/include -usr/share/mysql/mysql-test/suite/jp -usr/share/mysql/mysql-test/suite/jp/t -usr/share/mysql/mysql-test/suite/jp/r -usr/share/mysql/mysql-test/suite/jp/include -usr/share/mysql/mysql-test/suite/jp/std_data -usr/share/mysql/mysql-test/suite/ndb -usr/share/mysql/mysql-test/suite/ndb/t -usr/share/mysql/mysql-test/suite/ndb/r -usr/share/mysql/mysql-test/suite/maria -usr/share/mysql/mysql-test/suite/maria/t -usr/share/mysql/mysql-test/suite/maria/r -usr/share/mysql/mysql-test/suite/funcs_2 -usr/share/mysql/mysql-test/suite/funcs_2/lib -usr/share/mysql/mysql-test/suite/funcs_2/t -usr/share/mysql/mysql-test/suite/funcs_2/charset -usr/share/mysql/mysql-test/suite/funcs_2/r -usr/share/mysql/mysql-test/suite/funcs_2/include -usr/share/mysql/mysql-test/suite/funcs_2/data -usr/share/mysql/mysql-test/suite/binlog -usr/share/mysql/mysql-test/suite/binlog/t -usr/share/mysql/mysql-test/suite/binlog/r -usr/share/mysql/mysql-test/suite/binlog/std_data -usr/share/mysql/mysql-test/suite/ndb_team -usr/share/mysql/mysql-test/suite/ndb_team/t -usr/share/mysql/mysql-test/suite/ndb_team/r -usr/share/mysql/mysql-test/suite/federated -usr/share/mysql/mysql-test/suite/funcs_1 -usr/share/mysql/mysql-test/suite/funcs_1/cursors -usr/share/mysql/mysql-test/suite/funcs_1/bitdata -usr/share/mysql/mysql-test/suite/funcs_1/views -usr/share/mysql/mysql-test/suite/funcs_1/storedproc -usr/share/mysql/mysql-test/suite/funcs_1/triggers -usr/share/mysql/mysql-test/suite/funcs_1/lib -usr/share/mysql/mysql-test/suite/funcs_1/t -usr/share/mysql/mysql-test/suite/funcs_1/r -usr/share/mysql/mysql-test/suite/funcs_1/include -usr/share/mysql/mysql-test/suite/funcs_1/datadict -usr/share/mysql/mysql-test/suite/vcol -usr/share/mysql/mysql-test/suite/vcol/inc -usr/share/mysql/mysql-test/suite/vcol/t -usr/share/mysql/mysql-test/suite/vcol/r -usr/share/mysql/mysql-test/suite/oqgraph -usr/share/mysql/mysql-test/suite/oqgraph/t -usr/share/mysql/mysql-test/suite/oqgraph/r -usr/share/mysql/mysql-test/suite/oqgraph/include -usr/share/mysql/mysql-test/suite/galera -usr/share/mysql/mysql-test/suite/galera/t -usr/share/mysql/mysql-test/suite/galera/r -usr/share/mysql/mysql-test/suite/wsrep -usr/share/mysql/mysql-test/suite/wsrep/t -usr/share/mysql/mysql-test/suite/wsrep/r -usr/share/mysql/mysql-test/std_data -usr/share/mysql/mysql-test/std_data/ndb_backup50 -usr/share/mysql/mysql-test/std_data/parts -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_le -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_be -usr/share/mysql/mysql-test/std_data/ndb_backup51 -usr/share/mysql/mysql-test/std_data/funcs_1 diff --git a/debian/mariadb-test-5.5.files b/debian/mariadb-test-5.5.files deleted file mode 100644 index 79eb9520607..00000000000 --- a/debian/mariadb-test-5.5.files +++ /dev/null @@ -1,15 +0,0 @@ -usr/lib/mysql/plugin/dialog_examples.so -usr/lib/mysql/plugin/auth_test_plugin.so -usr/lib/mysql/plugin/qa_auth_interface.so -usr/lib/mysql/plugin/qa_auth_server.so -usr/lib/mysql/plugin/qa_auth_client.so -usr/lib/mysql/plugin/auth_0x0100.so -usr/lib/mysql/plugin/mypluglib.so -usr/lib/mysql/plugin/daemon_example.ini -usr/lib/mysql/plugin/libdaemon_example.so -usr/lib/mysql/plugin/adt_null.so -usr/bin/mysql_client_test -usr/share/man/man1/mysql_client_test.1 -usr/bin/mysqltest -usr/share/man/man1/mysqltest.1 -usr/share/mysql/mysql-test diff --git a/debian/mariadb-test-5.5.links b/debian/mariadb-test-5.5.links deleted file mode 100644 index 082680fe5ed..00000000000 --- a/debian/mariadb-test-5.5.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mysql-test-run -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mtr diff --git a/debian/mysql-common.dirs b/debian/mysql-common.dirs deleted file mode 100644 index a5a88ede9c1..00000000000 --- a/debian/mysql-common.dirs +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/ diff --git a/debian/mysql-common.files b/debian/mysql-common.files deleted file mode 100644 index d167569e892..00000000000 --- a/debian/mysql-common.files +++ /dev/null @@ -1,3 +0,0 @@ -etc/mysql/my.cnf -usr/share/mysql-common/internal-use-only -usr/share/lintian/overrides/mysql-common diff --git a/debian/mysql-common.lintian-overrides b/debian/mysql-common.lintian-overrides deleted file mode 100644 index c6c60ccdc71..00000000000 --- a/debian/mysql-common.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_init.d_mysql -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_mysql_debian-start diff --git a/debian/mysql-common.postrm b/debian/mysql-common.postrm deleted file mode 100644 index 0d3f8aed83d..00000000000 --- a/debian/mysql-common.postrm +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# From 983366e0eef50b95329bcba154ee4fb38b85df3c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 20 Mar 2014 18:33:23 -0400 Subject: [PATCH 128/294] MDEV#5903 mariadb-galera tree builds too many rpm packages Modified the components list to make sure that only server package gets generated. --- cmake/cpack_rpm.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index b13b167a7f6..6adc27bf83d 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -23,9 +23,7 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared") SET(CPACK_COMPONENT_COMMON_GROUP "common") SET(CPACK_COMPONENT_COMPAT_GROUP "compat") SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts - SupportFiles Development ManPagesDevelopment - ManPagesTest Readme ManPagesClient Test - Common Client SharedLibraries) + SupportFiles Readme) SET(CPACK_RPM_PACKAGE_NAME "MariaDB-Galera") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") From fa18dc394406ad684ab2623e7451c9f3ec7adf08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 16 Apr 2014 13:08:29 +0300 Subject: [PATCH 129/294] Merge lp:codership-mysql/5.5 -r3961..3980. --- cmake/wsrep.cmake | 2 +- scripts/CMakeLists.txt | 8 +- scripts/wsrep_sst_common | 12 +- scripts/wsrep_sst_common.sh | 12 +- scripts/wsrep_sst_rsync.sh | 29 +- scripts/wsrep_sst_xtrabackup-v2 | 879 +++++++++++++++++++++++++++++ scripts/wsrep_sst_xtrabackup-v2.sh | 879 +++++++++++++++++++++++++++++ scripts/wsrep_sst_xtrabackup.sh | 606 ++++++++++++++------ sql/slave.cc | 33 ++ sql/sql_base.cc | 1 + sql/sys_vars.cc | 4 + sql/wsrep_binlog.cc | 56 ++ sql/wsrep_binlog.h | 3 + sql/wsrep_hton.cc | 6 + sql/wsrep_mysqld.cc | 46 +- sql/wsrep_mysqld.h | 2 + sql/wsrep_notify.cc | 19 +- sql/wsrep_sst.cc | 3 +- support-files/mysql.spec.sh | 1 + support-files/wsrep_notify.sh | 1 + wsrep/wsrep_api.h | 4 + wsrep/wsrep_dummy.c | 1 - 22 files changed, 2382 insertions(+), 225 deletions(-) create mode 100755 scripts/wsrep_sst_xtrabackup-v2 create mode 100644 scripts/wsrep_sst_xtrabackup-v2.sh diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index a5ca4508da4..95f3f4fcd8f 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -18,7 +18,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "9") +SET(WSREP_PATCH_VERSION "10") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 57fc70ea508..8be77f590a5 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -328,7 +328,13 @@ IF(WIN32) ENDFOREACH() ELSE() IF(WITH_WSREP) - SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup) + SET(WSREP_BINARIES + wsrep_sst_common + wsrep_sst_mysqldump + wsrep_sst_rsync + wsrep_sst_xtrabackup + wsrep_sst_xtrabackup-v2 + ) ENDIF() # Configure this one, for testing, but do not install it. diff --git a/scripts/wsrep_sst_common b/scripts/wsrep_sst_common index 30303de0779..f9a08c1c695 100755 --- a/scripts/wsrep_sst_common +++ b/scripts/wsrep_sst_common @@ -28,7 +28,7 @@ case "$1" in shift ;; '--auth') - readonly WSREP_SST_OPT_AUTH="$2" + WSREP_SST_OPT_AUTH="$2" shift ;; '--bypass') @@ -87,13 +87,21 @@ shift done readonly WSREP_SST_OPT_BYPASS -if [ -n "$WSREP_SST_OPT_DATA" ] +# For Bug:1200727 +if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then + if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then + WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) + fi +fi + +if [ -n "${WSREP_SST_OPT_DATA:-}" ] then SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" else SST_PROGRESS_FILE="" fi + wsrep_log() { # echo everything to stderr so that it gets into common error log diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 30303de0779..f9a08c1c695 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -28,7 +28,7 @@ case "$1" in shift ;; '--auth') - readonly WSREP_SST_OPT_AUTH="$2" + WSREP_SST_OPT_AUTH="$2" shift ;; '--bypass') @@ -87,13 +87,21 @@ shift done readonly WSREP_SST_OPT_BYPASS -if [ -n "$WSREP_SST_OPT_DATA" ] +# For Bug:1200727 +if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then + if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then + WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) + fi +fi + +if [ -n "${WSREP_SST_OPT_DATA:-}" ] then SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" else SST_PROGRESS_FILE="" fi + wsrep_log() { # echo everything to stderr so that it gets into common error log diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 4b78071542c..960eef2df4b 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -49,19 +49,21 @@ check_pid() check_pid_and_port() { local pid_file=$1 - local rsync_pid=$(cat $pid_file) - local rsync_port=$2 + local rsync_pid=$2 + local rsync_port=$3 - if [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ]; then - # no netstat --program(-p) option in Darwin and FreeBSD - check_pid $pid_file && \ - lsof -i -Pn 2>/dev/null | \ - grep "(LISTEN)" | grep ":$rsync_port" | grep -w '^rsync[[:space:]]\+'"$rsync_pid" >/dev/null - else - check_pid $pid_file && \ - netstat -lnpt 2>/dev/null | \ - grep LISTEN | grep \:$rsync_port | grep $rsync_pid/rsync >/dev/null + local port_info=$(lsof -i :$rsync_port -Pn 2>/dev/null | \ + grep "(LISTEN)") + local is_rsync=$(echo $port_info | \ + grep -w '^rsync[[:space:]]\+'"$rsync_pid" 2>/dev/null) + + if [ -n "$port_info" -a -z "$is_rsync" ]; then + wsrep_log_error "rsync daemon port '$rsync_port' has been taken" + exit 16 # EBUSY fi + check_pid $pid_file && \ + [ -n "$port_info" ] && [ -n "$is_rsync" ] && \ + [ $(cat $pid_file) -eq $rsync_pid ] } MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" @@ -234,9 +236,10 @@ EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around # listen at all interfaces (for firewalled setups) - rsync --daemon --port $RSYNC_PORT --config "$RSYNC_CONF" + rsync --daemon --no-detach --port $RSYNC_PORT --config "$RSYNC_CONF" & + RSYNC_REAL_PID=$! - until check_pid_and_port $RSYNC_PID $RSYNC_PORT + until check_pid_and_port $RSYNC_PID $RSYNC_REAL_PID $RSYNC_PORT do sleep 0.2 done diff --git a/scripts/wsrep_sst_xtrabackup-v2 b/scripts/wsrep_sst_xtrabackup-v2 new file mode 100755 index 00000000000..59017fff8df --- /dev/null +++ b/scripts/wsrep_sst_xtrabackup-v2 @@ -0,0 +1,879 @@ +#!/bin/bash -ue +# Copyright (C) 2013 Percona Inc +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html +# Make sure to read that before proceeding! + + + + +. $(dirname $0)/wsrep_sst_common + +ealgo="" +ekey="" +ekeyfile="" +encrypt=0 +nproc=1 +ecode=0 +XTRABACKUP_PID="" +SST_PORT="" +REMOTEIP="" +tcert="" +tpem="" +tkey="" +sockopt="" +progress="" +ttime=0 +totime=0 +lsn="" +incremental=0 +ecmd="" +rlimit="" +# Initially +stagemsg="${WSREP_SST_OPT_ROLE}" +cpat="" +speciald=0 +ib_home_dir="" +ib_log_dir="" + +sfmt="tar" +strmcmd="" +tfmt="" +tcmd="" +rebuild=0 +rebuildcmd="" +payload=0 +pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' " +pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE " +STATDIR="" +uextra=0 +disver="" + +scomp="" +sdecomp="" + +if which pv &>/dev/null && pv --help | grep -q FORMAT;then + pvopts+=$pvformat +fi +pcmd="pv $pvopts" +declare -a RC + +INNOBACKUPEX_BIN=innobackupex +readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) +DATA="${WSREP_SST_OPT_DATA}" +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" +MAGIC_FILE="${DATA}/${INFO_FILE}" + +# Setting the path for ss and ip +export PATH="/usr/sbin:/sbin:$PATH" + +timeit(){ + local stage=$1 + shift + local cmd="$@" + local x1 x2 took extcode + + if [[ $ttime -eq 1 ]];then + x1=$(date +%s) + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + x2=$(date +%s) + took=$(( x2-x1 )) + wsrep_log_info "NOTE: $stage took $took seconds" + totime=$(( totime+took )) + else + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + fi + return $extcode +} + +get_keys() +{ + # $encrypt -eq 1 is for internal purposes only + if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then + return + fi + + if [[ $encrypt -eq 0 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " + fi + return + fi + + if [[ $sfmt == 'tar' ]];then + wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" + encrypt=-1 + return + fi + + wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4" + + if [[ -z $ealgo ]];then + wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" + exit 3 + fi + + if [[ -z $ekey && ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Either key or keyfile must be readable" + exit 3 + fi + + if [[ -z $ekey ]];then + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" + else + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" + fi + + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + ecmd+=" -d" + fi + + stagemsg+="-XB-Encrypted" +} + +get_transfer() +{ + if [[ -z $SST_PORT ]];then + TSST_PORT=4444 + else + TSST_PORT=$SST_PORT + fi + + if [[ $tfmt == 'nc' ]];then + if [[ ! -x `which nc` ]];then + wsrep_log_error "nc(netcat) not found in path: $PATH" + exit 2 + fi + wsrep_log_info "Using netcat as streamer" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="nc -dl ${TSST_PORT}" + else + tcmd="nc ${REMOTEIP} ${TSST_PORT}" + fi + else + tfmt='socat' + wsrep_log_info "Using socat as streamer" + if [[ ! -x `which socat` ]];then + wsrep_log_error "socat not found in path: $PATH" + exit 2 + fi + + if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then + wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" + encrypt=-1 + fi + + if [[ $encrypt -eq 2 ]];then + wsrep_log_info "Using openssl based encryption with socat: with crt and pem" + if [[ -z $tpem || -z $tcert ]];then + wsrep_log_error "Both PEM and CRT files required" + exit 22 + fi + stagemsg+="-OpenSSL-Encrypted-2" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" + else + wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" + fi + elif [[ $encrypt -eq 3 ]];then + wsrep_log_info "Using openssl based encryption with socat: with key and crt" + if [[ -z $tpem || -z $tkey ]];then + wsrep_log_error "Both certificate and key files required" + exit 22 + fi + stagemsg+="-OpenSSL-Encrypted-3" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with certificate $tpem, key $tkey" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio" + else + wsrep_log_info "Encrypting with certificate $tpem, key $tkey" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}" + fi + + else + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" + else + tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" + fi + fi + fi + +} + +parse_cnf() +{ + local group=$1 + local var=$2 + reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + if [[ -z $reval ]];then + [[ -n $3 ]] && reval=$3 + fi + echo $reval +} + +get_footprint() +{ + pushd $WSREP_SST_OPT_DATA 1>/dev/null + payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + # QuickLZ has around 50% compression ratio + # When compression/compaction used, the progress is only an approximate. + payload=$(( payload*1/2 )) + fi + popd 1>/dev/null + pcmd+=" -s $payload" + adjust_progress +} + +adjust_progress() +{ + if [[ -n $progress && $progress != '1' ]];then + if [[ -e $progress ]];then + pcmd+=" 2>>$progress" + else + pcmd+=" 2>$progress" + fi + elif [[ -z $progress && -n $rlimit ]];then + # When rlimit is non-zero + pcmd="pv -q" + fi + + if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then + wsrep_log_info "Rate-limiting SST to $rlimit" + pcmd+=" -L \$rlimit" + fi +} + +read_cnf() +{ + sfmt=$(parse_cnf sst streamfmt "xbstream") + tfmt=$(parse_cnf sst transferfmt "socat") + tcert=$(parse_cnf sst tca "") + tpem=$(parse_cnf sst tcert "") + tkey=$(parse_cnf sst tkey "") + encrypt=$(parse_cnf sst encrypt 0) + sockopt=$(parse_cnf sst sockopt "") + progress=$(parse_cnf sst progress "") + rebuild=$(parse_cnf sst rebuild 0) + ttime=$(parse_cnf sst time 0) + cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + incremental=$(parse_cnf sst incremental 0) + ealgo=$(parse_cnf xtrabackup encrypt "") + ekey=$(parse_cnf xtrabackup encrypt-key "") + ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") + scomp=$(parse_cnf sst compressor "") + sdecomp=$(parse_cnf sst decompressor "") + + + # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html + if [[ -z $ealgo ]];then + ealgo=$(parse_cnf sst encrypt-algo "") + ekey=$(parse_cnf sst encrypt-key "") + ekeyfile=$(parse_cnf sst encrypt-key-file "") + fi + rlimit=$(parse_cnf sst rlimit "") + uextra=$(parse_cnf sst use_extra 0) + speciald=$(parse_cnf sst sst-special-dirs 1) + iopts=$(parse_cnf sst inno-backup-opts "") + iapts=$(parse_cnf sst inno-apply-opts "") + impts=$(parse_cnf sst inno-move-opts "") +} + +get_stream() +{ + if [[ $sfmt == 'xbstream' ]];then + wsrep_log_info "Streaming with xbstream" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + strmcmd="xbstream -x" + else + strmcmd="xbstream -c \${INFO_FILE}" + fi + else + sfmt="tar" + wsrep_log_info "Streaming with tar" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + strmcmd="tar xfi - " + else + strmcmd="tar cf - \${INFO_FILE} " + fi + + fi +} + +get_proc() +{ + set +e + nproc=$(grep -c processor /proc/cpuinfo) + [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 + set -e +} + +sig_joiner_cleanup() +{ + wsrep_log_error "Removing $MAGIC_FILE file due to signal" + rm -f "$MAGIC_FILE" +} + +cleanup_joiner() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + wsrep_log_info "Removing the sst_in_progress file" + wsrep_cleanup_progress_file + fi + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi + if [[ -n ${STATDIR:-} ]];then + [[ -d $STATDIR ]] && rm -rf $STATDIR + fi +} + +check_pid() +{ + local pid_file="$1" + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 +} + +cleanup_donor() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + + if [[ -n $XTRABACKUP_PID ]];then + if check_pid $XTRABACKUP_PID + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + fi + + rm -f $XTRABACKUP_PID + fi + rm -f ${DATA}/${IST_FILE} + + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi +} + +kill_xtrabackup() +{ + local PID=$(cat $XTRABACKUP_PID) + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$XTRABACKUP_PID" +} + +setup_ports() +{ + if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then + SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') + REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') + lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') + else + SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') + fi +} + +# waits ~10 seconds for nc to open the port and then reports ready +# (regardless of timeout) +wait_for_listen() +{ + local PORT=$1 + local ADDR=$2 + local MODULE=$3 + for i in {1..50} + do + ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break + sleep 0.2 + done + if [[ $incremental -eq 1 ]];then + echo "ready ${ADDR}/${MODULE}/$lsn" + else + echo "ready ${ADDR}/${MODULE}" + fi +} + +check_extra() +{ + local use_socket=1 + if [[ $uextra -eq 1 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if [[ -n $eport ]];then + # Xtrabackup works only locally. + # Hence, setting host to 127.0.0.1 unconditionally. + wsrep_log_info "SST through extra_port $eport" + INNOEXTRA+=" --host=127.0.0.1 --port=$eport " + use_socket=0 + else + wsrep_log_error "Extra port $eport null, failing" + exit 1 + fi + else + wsrep_log_info "Thread pool not set, ignore the option use_extra" + fi + fi + if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then + INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" + fi +} + +recv_joiner() +{ + local dir=$1 + local msg=$2 + + pushd ${dir} 1>/dev/null + set +e + timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + popd 1>/dev/null + + + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while getting data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done + + if [ ! -r "${MAGIC_FILE}" ];then + # this message should cause joiner to abort + wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" + wsrep_log_info "Contents of datadir" + wsrep_log_info "$(ls -l ${dir}/*)" + exit 32 + fi +} + + +send_donor() +{ + local dir=$1 + local msg=$2 + + pushd ${dir} 1>/dev/null + set +e + timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + popd 1>/dev/null + + + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while getting data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done + +} + +if [[ ! -x `which innobackupex` ]];then + wsrep_log_error "innobackupex not in path: $PATH" + exit 2 +fi + +rm -f "${MAGIC_FILE}" + +if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then + wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" + exit 22 +fi + +read_cnf +setup_ports +get_stream +get_transfer + +if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then + disver="--no-version-check" +fi + + +INNOEXTRA="" +INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" +INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" +INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" + +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] +then + trap cleanup_donor EXIT + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + + TMPDIR="${TMPDIR:-/tmp}" + + if [ "${AUTH[0]}" != "(null)" ]; then + INNOEXTRA+=" --user=${AUTH[0]}" + fi + + if [ ${#AUTH[*]} -eq 2 ]; then + INNOEXTRA+=" --password=${AUTH[1]}" + elif [ "${AUTH[0]}" != "(null)" ]; then + # Empty password, used for testing, debugging etc. + INNOEXTRA+=" --password=" + fi + + get_keys + if [[ $encrypt -eq 1 ]];then + if [[ -n $ekey ]];then + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " + else + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " + fi + fi + + if [[ -n $lsn ]];then + INNOEXTRA+=" --incremental --incremental-lsn=$lsn " + fi + + check_extra + + wsrep_log_info "Streaming GTID file before SST" + + echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" + + ttcmd="$tcmd" + + if [[ $encrypt -eq 1 ]];then + if [[ -n $scomp ]];then + tcmd=" $ecmd | $scomp | $tcmd " + else + tcmd=" $ecmd | $tcmd " + fi + elif [[ -n $scomp ]];then + tcmd=" $scomp | $tcmd " + fi + + + send_donor $DATA "${stagemsg}-gtid" + + tcmd="$ttcmd" + if [[ -n $progress ]];then + get_footprint + tcmd="$pcmd | $tcmd" + elif [[ -n $rlimit ]];then + adjust_progress + tcmd="$pcmd | $tcmd" + fi + + wsrep_log_info "Sleeping before data transfer for SST" + sleep 10 + + wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" + + if [[ -n $scomp ]];then + tcmd="$scomp | $tcmd" + fi + + set +e + timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + + if [ ${RC[0]} -ne 0 ]; then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ + "Check ${DATA}/innobackup.backup.log" + exit 22 + elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then + wsrep_log_error "$tcmd finished with error: ${RC[1]}" + exit 22 + fi + + # innobackupex implicitly writes PID to fixed location in ${TMPDIR} + XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" + + + else # BYPASS FOR IST + + wsrep_log_info "Bypassing the SST for IST" + echo "continue" # now server can resume updating data + echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" + echo "1" > "${DATA}/${IST_FILE}" + get_keys + if [[ $encrypt -eq 1 ]];then + if [[ -n $scomp ]];then + tcmd=" $ecmd | $scomp | $tcmd " + else + tcmd=" $ecmd | $tcmd " + fi + elif [[ -n $scomp ]];then + tcmd=" $scomp | $tcmd " + fi + strmcmd+=" \${IST_FILE}" + + send_donor $DATA "${stagemsg}-IST" + + fi + + echo "done ${WSREP_SST_OPT_GTID}" + wsrep_log_info "Total time on donor: $totime seconds" + +elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] +then + [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" + [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE + + if [[ $speciald -eq 1 ]];then + wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter." + fi + + if [[ $speciald -eq 1 ]];then + ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "") + ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") + if [[ -z $ib_home_dir && -z $ib_log_dir ]];then + speciald=0 + fi + fi + + stagemsg="Joiner-Recv" + + if [[ ! -e ${DATA}/ibdata1 ]];then + incremental=0 + fi + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet" + lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ') + wsrep_log_info "Recovered LSN: $lsn" + fi + + sencrypted=1 + nthreads=1 + + MODULE="xtrabackup_sst" + + rm -f "${DATA}/${IST_FILE}" + + # May need xtrabackup_checkpoints later on + rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile + + ADDR=${WSREP_SST_OPT_ADDR} + if [ -z "${SST_PORT}" ] + then + SST_PORT=4444 + ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" + fi + + wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & + + trap sig_joiner_cleanup HUP PIPE INT TERM + trap cleanup_joiner EXIT + + if [[ -n $progress ]];then + adjust_progress + tcmd+=" | $pcmd" + fi + + if [[ $incremental -eq 1 ]];then + BDATA=$DATA + DATA=$(mktemp -d) + MAGIC_FILE="${DATA}/${INFO_FILE}" + fi + + get_keys + if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then + if [[ -n $sdecomp ]];then + strmcmd=" $sdecomp | $ecmd | $strmcmd" + else + strmcmd=" $ecmd | $strmcmd" + fi + elif [[ -n $sdecomp ]];then + strmcmd=" $sdecomp | $strmcmd" + fi + + STATDIR=$(mktemp -d) + MAGIC_FILE="${STATDIR}/${INFO_FILE}" + recv_joiner $STATDIR "${stagemsg}-gtid" 1 + + if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null + then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." + exit 32 + fi + + if [ ! -r "${STATDIR}/${IST_FILE}" ] + then + wsrep_log_info "Proceeding with SST" + + if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then + wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST" + fi + + if [[ $incremental -ne 1 ]];then + if [[ $speciald -eq 1 ]];then + wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" + find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ + else + wsrep_log_info "Cleaning the existing datadir" + find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ + fi + tempdir=$(parse_cnf mysqld log-bin "") + if [[ -n ${tempdir:-} ]];then + binlog_dir=$(dirname $tempdir) + binlog_file=$(basename $tempdir) + if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then + pattern="$binlog_dir/$binlog_file\.[0-9]+$" + wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" + find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ + rm $binlog_dir/*.index || true + fi + fi + + else + wsrep_log_info "Removing existing ib_logfile files" + rm -f ${BDATA}/ib_logfile* + fi + + + if [[ $speciald -eq 1 ]];then + mkdir -p ${DATA}/.sst + TDATA=${DATA} + DATA="${DATA}/.sst" + fi + + + MAGIC_FILE="${DATA}/${INFO_FILE}" + recv_joiner $DATA "${stagemsg}-SST" 0 + + get_proc + + # Rebuild indexes for compact backups + if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then + wsrep_log_info "Index compaction detected" + rebuild=1 + fi + + if [[ $rebuild -eq 1 ]];then + nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) + wsrep_log_info "Rebuilding during prepare with $nthreads threads" + rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" + fi + + if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then + + wsrep_log_info "Compressed qpress files found" + + if [[ ! -x `which qpress` ]];then + wsrep_log_error "qpress not found in path: $PATH" + exit 22 + fi + + if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then + count=$(find ${DATA} -type f -name '*.qp' | wc -l) + count=$(( count*2 )) + if pv --help | grep -q FORMAT;then + pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" + else + pvopts="-f -s $count -l -N Decompression" + fi + pcmd="pv $pvopts" + adjust_progress + dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" + else + dcmd="xargs -n 2 qpress -T${nproc}d" + fi + + + # Decompress the qpress files + wsrep_log_info "Decompression with $nproc threads" + timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" + extcode=$? + + if [[ $extcode -eq 0 ]];then + wsrep_log_info "Removing qpress files after decompression" + find ${DATA} -type f -name '*.qp' -delete + if [[ $? -ne 0 ]];then + wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" + fi + else + wsrep_log_error "Decompression failed. Exit code: $extcode" + exit 22 + fi + fi + + if [[ $incremental -eq 1 ]];then + # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. + INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \ + --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" + fi + + wsrep_log_info "Preparing the backup at ${DATA}" + timeit "Xtrabackup prepare stage" "$INNOAPPLY" + + if [ $? -ne 0 ]; + then + wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log" + exit 22 + fi + + if [[ $speciald -eq 1 ]];then + MAGIC_FILE="${TDATA}/${INFO_FILE}" + set +e + rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log + set -e + wsrep_log_info "Moving the backup to ${TDATA}" + timeit "Xtrabackup move stage" "$INNOMOVE" + if [[ $? -eq 0 ]];then + wsrep_log_info "Move successful, removing ${DATA}" + rm -rf $DATA + DATA=${TDATA} + else + wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis" + wsrep_log_error "Check ${DATA}/innobackup.move.log for details" + fi + fi + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Cleaning up ${DATA} after incremental SST" + [[ -d ${DATA} ]] && rm -rf ${DATA} + DATA=$BDATA + fi + + else + wsrep_log_info "${IST_FILE} received from donor: Running IST" + fi + + if [[ ! -r ${MAGIC_FILE} ]];then + wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" + exit 2 + fi + + cat "${MAGIC_FILE}" # output UUID:seqno + wsrep_log_info "Total time on joiner: $totime seconds" +fi + +exit 0 diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh new file mode 100644 index 00000000000..59017fff8df --- /dev/null +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -0,0 +1,879 @@ +#!/bin/bash -ue +# Copyright (C) 2013 Percona Inc +# +# 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; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1301 USA. + +# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html +# Make sure to read that before proceeding! + + + + +. $(dirname $0)/wsrep_sst_common + +ealgo="" +ekey="" +ekeyfile="" +encrypt=0 +nproc=1 +ecode=0 +XTRABACKUP_PID="" +SST_PORT="" +REMOTEIP="" +tcert="" +tpem="" +tkey="" +sockopt="" +progress="" +ttime=0 +totime=0 +lsn="" +incremental=0 +ecmd="" +rlimit="" +# Initially +stagemsg="${WSREP_SST_OPT_ROLE}" +cpat="" +speciald=0 +ib_home_dir="" +ib_log_dir="" + +sfmt="tar" +strmcmd="" +tfmt="" +tcmd="" +rebuild=0 +rebuildcmd="" +payload=0 +pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' " +pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE " +STATDIR="" +uextra=0 +disver="" + +scomp="" +sdecomp="" + +if which pv &>/dev/null && pv --help | grep -q FORMAT;then + pvopts+=$pvformat +fi +pcmd="pv $pvopts" +declare -a RC + +INNOBACKUPEX_BIN=innobackupex +readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) +DATA="${WSREP_SST_OPT_DATA}" +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" +MAGIC_FILE="${DATA}/${INFO_FILE}" + +# Setting the path for ss and ip +export PATH="/usr/sbin:/sbin:$PATH" + +timeit(){ + local stage=$1 + shift + local cmd="$@" + local x1 x2 took extcode + + if [[ $ttime -eq 1 ]];then + x1=$(date +%s) + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + x2=$(date +%s) + took=$(( x2-x1 )) + wsrep_log_info "NOTE: $stage took $took seconds" + totime=$(( totime+took )) + else + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + fi + return $extcode +} + +get_keys() +{ + # $encrypt -eq 1 is for internal purposes only + if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then + return + fi + + if [[ $encrypt -eq 0 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " + fi + return + fi + + if [[ $sfmt == 'tar' ]];then + wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" + encrypt=-1 + return + fi + + wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4" + + if [[ -z $ealgo ]];then + wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" + exit 3 + fi + + if [[ -z $ekey && ! -r $ekeyfile ]];then + wsrep_log_error "FATAL: Either key or keyfile must be readable" + exit 3 + fi + + if [[ -z $ekey ]];then + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" + else + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" + fi + + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + ecmd+=" -d" + fi + + stagemsg+="-XB-Encrypted" +} + +get_transfer() +{ + if [[ -z $SST_PORT ]];then + TSST_PORT=4444 + else + TSST_PORT=$SST_PORT + fi + + if [[ $tfmt == 'nc' ]];then + if [[ ! -x `which nc` ]];then + wsrep_log_error "nc(netcat) not found in path: $PATH" + exit 2 + fi + wsrep_log_info "Using netcat as streamer" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="nc -dl ${TSST_PORT}" + else + tcmd="nc ${REMOTEIP} ${TSST_PORT}" + fi + else + tfmt='socat' + wsrep_log_info "Using socat as streamer" + if [[ ! -x `which socat` ]];then + wsrep_log_error "socat not found in path: $PATH" + exit 2 + fi + + if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then + wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" + encrypt=-1 + fi + + if [[ $encrypt -eq 2 ]];then + wsrep_log_info "Using openssl based encryption with socat: with crt and pem" + if [[ -z $tpem || -z $tcert ]];then + wsrep_log_error "Both PEM and CRT files required" + exit 22 + fi + stagemsg+="-OpenSSL-Encrypted-2" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" + else + wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" + fi + elif [[ $encrypt -eq 3 ]];then + wsrep_log_info "Using openssl based encryption with socat: with key and crt" + if [[ -z $tpem || -z $tkey ]];then + wsrep_log_error "Both certificate and key files required" + exit 22 + fi + stagemsg+="-OpenSSL-Encrypted-3" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with certificate $tpem, key $tkey" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio" + else + wsrep_log_info "Encrypting with certificate $tpem, key $tkey" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}" + fi + + else + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" + else + tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" + fi + fi + fi + +} + +parse_cnf() +{ + local group=$1 + local var=$2 + reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + if [[ -z $reval ]];then + [[ -n $3 ]] && reval=$3 + fi + echo $reval +} + +get_footprint() +{ + pushd $WSREP_SST_OPT_DATA 1>/dev/null + payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + # QuickLZ has around 50% compression ratio + # When compression/compaction used, the progress is only an approximate. + payload=$(( payload*1/2 )) + fi + popd 1>/dev/null + pcmd+=" -s $payload" + adjust_progress +} + +adjust_progress() +{ + if [[ -n $progress && $progress != '1' ]];then + if [[ -e $progress ]];then + pcmd+=" 2>>$progress" + else + pcmd+=" 2>$progress" + fi + elif [[ -z $progress && -n $rlimit ]];then + # When rlimit is non-zero + pcmd="pv -q" + fi + + if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then + wsrep_log_info "Rate-limiting SST to $rlimit" + pcmd+=" -L \$rlimit" + fi +} + +read_cnf() +{ + sfmt=$(parse_cnf sst streamfmt "xbstream") + tfmt=$(parse_cnf sst transferfmt "socat") + tcert=$(parse_cnf sst tca "") + tpem=$(parse_cnf sst tcert "") + tkey=$(parse_cnf sst tkey "") + encrypt=$(parse_cnf sst encrypt 0) + sockopt=$(parse_cnf sst sockopt "") + progress=$(parse_cnf sst progress "") + rebuild=$(parse_cnf sst rebuild 0) + ttime=$(parse_cnf sst time 0) + cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + incremental=$(parse_cnf sst incremental 0) + ealgo=$(parse_cnf xtrabackup encrypt "") + ekey=$(parse_cnf xtrabackup encrypt-key "") + ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") + scomp=$(parse_cnf sst compressor "") + sdecomp=$(parse_cnf sst decompressor "") + + + # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html + if [[ -z $ealgo ]];then + ealgo=$(parse_cnf sst encrypt-algo "") + ekey=$(parse_cnf sst encrypt-key "") + ekeyfile=$(parse_cnf sst encrypt-key-file "") + fi + rlimit=$(parse_cnf sst rlimit "") + uextra=$(parse_cnf sst use_extra 0) + speciald=$(parse_cnf sst sst-special-dirs 1) + iopts=$(parse_cnf sst inno-backup-opts "") + iapts=$(parse_cnf sst inno-apply-opts "") + impts=$(parse_cnf sst inno-move-opts "") +} + +get_stream() +{ + if [[ $sfmt == 'xbstream' ]];then + wsrep_log_info "Streaming with xbstream" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + strmcmd="xbstream -x" + else + strmcmd="xbstream -c \${INFO_FILE}" + fi + else + sfmt="tar" + wsrep_log_info "Streaming with tar" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + strmcmd="tar xfi - " + else + strmcmd="tar cf - \${INFO_FILE} " + fi + + fi +} + +get_proc() +{ + set +e + nproc=$(grep -c processor /proc/cpuinfo) + [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 + set -e +} + +sig_joiner_cleanup() +{ + wsrep_log_error "Removing $MAGIC_FILE file due to signal" + rm -f "$MAGIC_FILE" +} + +cleanup_joiner() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then + wsrep_log_info "Removing the sst_in_progress file" + wsrep_cleanup_progress_file + fi + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi + if [[ -n ${STATDIR:-} ]];then + [[ -d $STATDIR ]] && rm -rf $STATDIR + fi +} + +check_pid() +{ + local pid_file="$1" + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 +} + +cleanup_donor() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [[ $estatus -ne 0 ]];then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + + if [[ -n $XTRABACKUP_PID ]];then + if check_pid $XTRABACKUP_PID + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + fi + + rm -f $XTRABACKUP_PID + fi + rm -f ${DATA}/${IST_FILE} + + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi +} + +kill_xtrabackup() +{ + local PID=$(cat $XTRABACKUP_PID) + [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : + rm -f "$XTRABACKUP_PID" +} + +setup_ports() +{ + if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then + SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') + REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') + lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') + else + SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') + fi +} + +# waits ~10 seconds for nc to open the port and then reports ready +# (regardless of timeout) +wait_for_listen() +{ + local PORT=$1 + local ADDR=$2 + local MODULE=$3 + for i in {1..50} + do + ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break + sleep 0.2 + done + if [[ $incremental -eq 1 ]];then + echo "ready ${ADDR}/${MODULE}/$lsn" + else + echo "ready ${ADDR}/${MODULE}" + fi +} + +check_extra() +{ + local use_socket=1 + if [[ $uextra -eq 1 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if [[ -n $eport ]];then + # Xtrabackup works only locally. + # Hence, setting host to 127.0.0.1 unconditionally. + wsrep_log_info "SST through extra_port $eport" + INNOEXTRA+=" --host=127.0.0.1 --port=$eport " + use_socket=0 + else + wsrep_log_error "Extra port $eport null, failing" + exit 1 + fi + else + wsrep_log_info "Thread pool not set, ignore the option use_extra" + fi + fi + if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then + INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" + fi +} + +recv_joiner() +{ + local dir=$1 + local msg=$2 + + pushd ${dir} 1>/dev/null + set +e + timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + popd 1>/dev/null + + + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while getting data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done + + if [ ! -r "${MAGIC_FILE}" ];then + # this message should cause joiner to abort + wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" + wsrep_log_info "Contents of datadir" + wsrep_log_info "$(ls -l ${dir}/*)" + exit 32 + fi +} + + +send_donor() +{ + local dir=$1 + local msg=$2 + + pushd ${dir} 1>/dev/null + set +e + timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + popd 1>/dev/null + + + for ecode in "${RC[@]}";do + if [[ $ecode -ne 0 ]];then + wsrep_log_error "Error while getting data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done + +} + +if [[ ! -x `which innobackupex` ]];then + wsrep_log_error "innobackupex not in path: $PATH" + exit 2 +fi + +rm -f "${MAGIC_FILE}" + +if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then + wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" + exit 22 +fi + +read_cnf +setup_ports +get_stream +get_transfer + +if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then + disver="--no-version-check" +fi + + +INNOEXTRA="" +INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" +INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" +INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" + +if [ "$WSREP_SST_OPT_ROLE" = "donor" ] +then + trap cleanup_donor EXIT + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + + TMPDIR="${TMPDIR:-/tmp}" + + if [ "${AUTH[0]}" != "(null)" ]; then + INNOEXTRA+=" --user=${AUTH[0]}" + fi + + if [ ${#AUTH[*]} -eq 2 ]; then + INNOEXTRA+=" --password=${AUTH[1]}" + elif [ "${AUTH[0]}" != "(null)" ]; then + # Empty password, used for testing, debugging etc. + INNOEXTRA+=" --password=" + fi + + get_keys + if [[ $encrypt -eq 1 ]];then + if [[ -n $ekey ]];then + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " + else + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " + fi + fi + + if [[ -n $lsn ]];then + INNOEXTRA+=" --incremental --incremental-lsn=$lsn " + fi + + check_extra + + wsrep_log_info "Streaming GTID file before SST" + + echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" + + ttcmd="$tcmd" + + if [[ $encrypt -eq 1 ]];then + if [[ -n $scomp ]];then + tcmd=" $ecmd | $scomp | $tcmd " + else + tcmd=" $ecmd | $tcmd " + fi + elif [[ -n $scomp ]];then + tcmd=" $scomp | $tcmd " + fi + + + send_donor $DATA "${stagemsg}-gtid" + + tcmd="$ttcmd" + if [[ -n $progress ]];then + get_footprint + tcmd="$pcmd | $tcmd" + elif [[ -n $rlimit ]];then + adjust_progress + tcmd="$pcmd | $tcmd" + fi + + wsrep_log_info "Sleeping before data transfer for SST" + sleep 10 + + wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" + + if [[ -n $scomp ]];then + tcmd="$scomp | $tcmd" + fi + + set +e + timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + + if [ ${RC[0]} -ne 0 ]; then + wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ + "Check ${DATA}/innobackup.backup.log" + exit 22 + elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then + wsrep_log_error "$tcmd finished with error: ${RC[1]}" + exit 22 + fi + + # innobackupex implicitly writes PID to fixed location in ${TMPDIR} + XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" + + + else # BYPASS FOR IST + + wsrep_log_info "Bypassing the SST for IST" + echo "continue" # now server can resume updating data + echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" + echo "1" > "${DATA}/${IST_FILE}" + get_keys + if [[ $encrypt -eq 1 ]];then + if [[ -n $scomp ]];then + tcmd=" $ecmd | $scomp | $tcmd " + else + tcmd=" $ecmd | $tcmd " + fi + elif [[ -n $scomp ]];then + tcmd=" $scomp | $tcmd " + fi + strmcmd+=" \${IST_FILE}" + + send_donor $DATA "${stagemsg}-IST" + + fi + + echo "done ${WSREP_SST_OPT_GTID}" + wsrep_log_info "Total time on donor: $totime seconds" + +elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] +then + [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" + [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE + + if [[ $speciald -eq 1 ]];then + wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter." + fi + + if [[ $speciald -eq 1 ]];then + ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "") + ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") + if [[ -z $ib_home_dir && -z $ib_log_dir ]];then + speciald=0 + fi + fi + + stagemsg="Joiner-Recv" + + if [[ ! -e ${DATA}/ibdata1 ]];then + incremental=0 + fi + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet" + lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ') + wsrep_log_info "Recovered LSN: $lsn" + fi + + sencrypted=1 + nthreads=1 + + MODULE="xtrabackup_sst" + + rm -f "${DATA}/${IST_FILE}" + + # May need xtrabackup_checkpoints later on + rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile + + ADDR=${WSREP_SST_OPT_ADDR} + if [ -z "${SST_PORT}" ] + then + SST_PORT=4444 + ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" + fi + + wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & + + trap sig_joiner_cleanup HUP PIPE INT TERM + trap cleanup_joiner EXIT + + if [[ -n $progress ]];then + adjust_progress + tcmd+=" | $pcmd" + fi + + if [[ $incremental -eq 1 ]];then + BDATA=$DATA + DATA=$(mktemp -d) + MAGIC_FILE="${DATA}/${INFO_FILE}" + fi + + get_keys + if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then + if [[ -n $sdecomp ]];then + strmcmd=" $sdecomp | $ecmd | $strmcmd" + else + strmcmd=" $ecmd | $strmcmd" + fi + elif [[ -n $sdecomp ]];then + strmcmd=" $sdecomp | $strmcmd" + fi + + STATDIR=$(mktemp -d) + MAGIC_FILE="${STATDIR}/${INFO_FILE}" + recv_joiner $STATDIR "${stagemsg}-gtid" 1 + + if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null + then + wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." + exit 32 + fi + + if [ ! -r "${STATDIR}/${IST_FILE}" ] + then + wsrep_log_info "Proceeding with SST" + + if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then + wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST" + fi + + if [[ $incremental -ne 1 ]];then + if [[ $speciald -eq 1 ]];then + wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" + find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ + else + wsrep_log_info "Cleaning the existing datadir" + find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ + fi + tempdir=$(parse_cnf mysqld log-bin "") + if [[ -n ${tempdir:-} ]];then + binlog_dir=$(dirname $tempdir) + binlog_file=$(basename $tempdir) + if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then + pattern="$binlog_dir/$binlog_file\.[0-9]+$" + wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" + find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ + rm $binlog_dir/*.index || true + fi + fi + + else + wsrep_log_info "Removing existing ib_logfile files" + rm -f ${BDATA}/ib_logfile* + fi + + + if [[ $speciald -eq 1 ]];then + mkdir -p ${DATA}/.sst + TDATA=${DATA} + DATA="${DATA}/.sst" + fi + + + MAGIC_FILE="${DATA}/${INFO_FILE}" + recv_joiner $DATA "${stagemsg}-SST" 0 + + get_proc + + # Rebuild indexes for compact backups + if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then + wsrep_log_info "Index compaction detected" + rebuild=1 + fi + + if [[ $rebuild -eq 1 ]];then + nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) + wsrep_log_info "Rebuilding during prepare with $nthreads threads" + rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" + fi + + if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then + + wsrep_log_info "Compressed qpress files found" + + if [[ ! -x `which qpress` ]];then + wsrep_log_error "qpress not found in path: $PATH" + exit 22 + fi + + if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then + count=$(find ${DATA} -type f -name '*.qp' | wc -l) + count=$(( count*2 )) + if pv --help | grep -q FORMAT;then + pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" + else + pvopts="-f -s $count -l -N Decompression" + fi + pcmd="pv $pvopts" + adjust_progress + dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" + else + dcmd="xargs -n 2 qpress -T${nproc}d" + fi + + + # Decompress the qpress files + wsrep_log_info "Decompression with $nproc threads" + timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" + extcode=$? + + if [[ $extcode -eq 0 ]];then + wsrep_log_info "Removing qpress files after decompression" + find ${DATA} -type f -name '*.qp' -delete + if [[ $? -ne 0 ]];then + wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" + fi + else + wsrep_log_error "Decompression failed. Exit code: $extcode" + exit 22 + fi + fi + + if [[ $incremental -eq 1 ]];then + # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. + INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \ + --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" + fi + + wsrep_log_info "Preparing the backup at ${DATA}" + timeit "Xtrabackup prepare stage" "$INNOAPPLY" + + if [ $? -ne 0 ]; + then + wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log" + exit 22 + fi + + if [[ $speciald -eq 1 ]];then + MAGIC_FILE="${TDATA}/${INFO_FILE}" + set +e + rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log + set -e + wsrep_log_info "Moving the backup to ${TDATA}" + timeit "Xtrabackup move stage" "$INNOMOVE" + if [[ $? -eq 0 ]];then + wsrep_log_info "Move successful, removing ${DATA}" + rm -rf $DATA + DATA=${TDATA} + else + wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis" + wsrep_log_error "Check ${DATA}/innobackup.move.log for details" + fi + fi + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Cleaning up ${DATA} after incremental SST" + [[ -d ${DATA} ]] && rm -rf ${DATA} + DATA=$BDATA + fi + + else + wsrep_log_info "${IST_FILE} received from donor: Running IST" + fi + + if [[ ! -r ${MAGIC_FILE} ]];then + wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" + exit 2 + fi + + cat "${MAGIC_FILE}" # output UUID:seqno + wsrep_log_info "Total time on joiner: $totime seconds" +fi + +exit 0 diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 75ffe3eb15f..01c9c3f3049 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -15,25 +15,11 @@ # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston # MA 02110-1301 USA. -############################################################################################################# -# This is a reference script for Percona XtraBackup-based state snapshot transfer # -# Dependencies: (depending on configuration) # -# xbcrypt for encryption/decryption. # -# qpress for decompression. Download from http://www.quicklz.com/qpress-11-linux-x64.tar till # -# https://blueprints.launchpad.net/percona-xtrabackup/+spec/package-qpress is fixed. # -# my_print_defaults to extract values from my.cnf. # -# netcat for transfer. # -# xbstream/tar for streaming. (and xtrabackup ofc) # -# # -# Currently only option in cnf is read specifically for SST # -# [sst] # -# streamfmt=tar|xbstream # -# # -# Default is tar till lp:1193240 is fixed # -# You need to use xbstream for encryption, compression etc., however, # -# lp:1193240 requires you to manually cleanup the directory prior to SST # -# # -############################################################################################################# +# Optional dependencies and options documented here: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html +# Make sure to read that before proceeding! + + + . $(dirname $0)/wsrep_sst_common @@ -44,28 +30,89 @@ encrypt=0 nproc=1 ecode=0 XTRABACKUP_PID="" +SST_PORT="" +REMOTEIP="" +tcert="" +tpem="" +sockopt="" +progress="" +ttime=0 +totime=0 +lsn="" +incremental=0 +ecmd="" +rlimit="" sfmt="tar" strmcmd="" +tfmt="" +tcmd="" +rebuild=0 +rebuildcmd="" +payload=0 +pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' " +pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE " +uextra=0 + +if which pv &>/dev/null && pv --help | grep -q FORMAT;then + pvopts+=$pvformat +fi +pcmd="pv $pvopts" declare -a RC +INNOBACKUPEX_BIN=innobackupex +readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) +DATA="${WSREP_SST_OPT_DATA}" +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" +MAGIC_FILE="${DATA}/${INFO_FILE}" + +# Setting the path for ss and ip +export PATH="/usr/sbin:/sbin:$PATH" + +timeit(){ + local stage=$1 + shift + local cmd="$@" + local x1 x2 took extcode + + if [[ $ttime -eq 1 ]];then + x1=$(date +%s) + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + x2=$(date +%s) + took=$(( x2-x1 )) + wsrep_log_info "NOTE: $stage took $took seconds" + totime=$(( totime+took )) + else + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + fi + return $extcode +} + get_keys() { - # There is no metadata in the stream to indicate that it is encrypted - # So, if the cnf file on joiner contains 'encrypt' under [xtrabackup] section then - # it means encryption is being used - if ! my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt; then - return + if [[ $encrypt -eq 2 ]];then + return fi - if [[ $sfmt == 'tar' ]];then - wsrep_log_info "NOTE: Encryption cannot be enabled with tar format" + + if [[ $encrypt -eq 0 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " + fi return fi - wsrep_log_info "Encryption enabled in my.cnf - not supported at the moment - Bug in Xtrabackup - lp:1190343" - ealgo=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt=' | cut -d= -f2) - ekey=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key=' | cut -d= -f2) - ekeyfile=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--encrypt-key-file=' | cut -d= -f2) + if [[ $sfmt == 'tar' ]];then + wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" + encrypt=0 + return + fi + + wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4" if [[ -z $ealgo ]];then wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" @@ -76,35 +123,160 @@ get_keys() wsrep_log_error "FATAL: Either key or keyfile must be readable" exit 3 fi - encrypt=1 + + if [[ -z $ekey ]];then + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" + else + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" + fi + + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + ecmd+=" -d" + fi +} + +get_transfer() +{ + if [[ -z $SST_PORT ]];then + TSST_PORT=4444 + else + TSST_PORT=$SST_PORT + fi + + if [[ $tfmt == 'nc' ]];then + if [[ ! -x `which nc` ]];then + wsrep_log_error "nc(netcat) not found in path: $PATH" + exit 2 + fi + wsrep_log_info "Using netcat as streamer" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="nc -dl ${TSST_PORT}" + else + tcmd="nc ${REMOTEIP} ${TSST_PORT}" + fi + else + tfmt='socat' + wsrep_log_info "Using socat as streamer" + if [[ ! -x `which socat` ]];then + wsrep_log_error "socat not found in path: $PATH" + exit 2 + fi + + if [[ $encrypt -eq 2 ]] && ! socat -V | grep -q OPENSSL;then + wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" + encrypt=0 + fi + + if [[ $encrypt -eq 2 ]];then + wsrep_log_info "Using openssl based encryption with socat" + if [[ -z $tpem || -z $tcert ]];then + wsrep_log_error "Both PEM and CRT files required" + exit 22 + fi + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" + else + wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" + fi + else + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" + else + tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" + fi + fi + fi + +} + +parse_cnf() +{ + local group=$1 + local var=$2 + reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + if [[ -z $reval ]];then + [[ -n $3 ]] && reval=$3 + fi + echo $reval +} + +get_footprint() +{ + pushd $WSREP_SST_OPT_DATA 1>/dev/null + payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') + if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + # QuickLZ has around 50% compression ratio + # When compression/compaction used, the progress is only an approximate. + payload=$(( payload*1/2 )) + fi + popd 1>/dev/null + pcmd+=" -s $payload" + adjust_progress +} + +adjust_progress() +{ + if [[ -n $progress && $progress != '1' ]];then + if [[ -e $progress ]];then + pcmd+=" 2>>$progress" + else + pcmd+=" 2>$progress" + fi + elif [[ -z $progress && -n $rlimit ]];then + # When rlimit is non-zero + pcmd="pv -q" + fi + + if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then + wsrep_log_info "Rate-limiting SST to $rlimit" + pcmd+=" -L \$rlimit" + fi } read_cnf() { - sfmt=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- '--streamfmt' | cut -d= -f2) + sfmt=$(parse_cnf sst streamfmt "tar") + tfmt=$(parse_cnf sst transferfmt "socat") + tcert=$(parse_cnf sst tca "") + tpem=$(parse_cnf sst tcert "") + encrypt=$(parse_cnf sst encrypt 0) + sockopt=$(parse_cnf sst sockopt "") + progress=$(parse_cnf sst progress "") + rebuild=$(parse_cnf sst rebuild 0) + ttime=$(parse_cnf sst time 0) + incremental=$(parse_cnf sst incremental 0) + ealgo=$(parse_cnf xtrabackup encrypt "") + ekey=$(parse_cnf xtrabackup encrypt-key "") + ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") + + # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html + if [[ -z $ealgo ]];then + ealgo=$(parse_cnf sst encrypt-algo "") + ekey=$(parse_cnf sst encrypt-key "") + ekeyfile=$(parse_cnf sst encrypt-key-file "") + fi + rlimit=$(parse_cnf sst rlimit "") + uextra=$(parse_cnf sst use_extra 0) +} + +get_stream() +{ if [[ $sfmt == 'xbstream' ]];then wsrep_log_info "Streaming with xbstream" if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "xbstream requires manual cleanup of data directory before SST - lp:1193240" - strmcmd="xbstream -x -C ${DATA}" - elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - strmcmd="xbstream -c ${INFO_FILE} ${IST_FILE}" + strmcmd="xbstream -x" else - wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" - exit 22 + strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}" fi else sfmt="tar" wsrep_log_info "Streaming with tar" - wsrep_log_info "Note: Advanced xtrabackup features - encryption,compression etc. not available with tar." if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "However, xbstream requires manual cleanup of data directory before SST - lp:1193240." - strmcmd="tar xfi - -C ${DATA}" - elif [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - strmcmd="tar cf - ${INFO_FILE} ${IST_FILE}" - else - wsrep_log_error "Invalid role: $WSREP_SST_OPT_ROLE" - exit 22 + strmcmd="tar xfi - --recursive-unlink -h" + else + strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}" fi fi @@ -118,6 +290,12 @@ get_proc() set -e } +sig_joiner_cleanup() +{ + wsrep_log_error "Removing $MAGIC_FILE file due to signal" + rm -f "$MAGIC_FILE" +} + cleanup_joiner() { # Since this is invoked just after exit NNN @@ -125,18 +303,14 @@ cleanup_joiner() if [[ $estatus -ne 0 ]];then wsrep_log_error "Cleanup after exit with status:$estatus" fi - local PID=$(ps -aef |grep nc| grep $NC_PORT | awk '{ print $2 }') - if [[ $estatus -ne 0 ]];then - wsrep_log_error "Killing nc pid $PID" - else - wsrep_log_info "Killing nc pid $PID" - fi - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$MAGIC_FILE" if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then wsrep_log_info "Removing the sst_in_progress file" wsrep_cleanup_progress_file fi + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi } check_pid() @@ -152,119 +326,161 @@ cleanup_donor() if [[ $estatus -ne 0 ]];then wsrep_log_error "Cleanup after exit with status:$estatus" fi - local pid=$XTRABACKUP_PID - if check_pid "$pid" - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - fi - rm -f "$pid" + if [[ -n $XTRABACKUP_PID ]];then + if check_pid $XTRABACKUP_PID + then + wsrep_log_error "xtrabackup process is still running. Killing... " + kill_xtrabackup + fi + + rm -f $XTRABACKUP_PID + fi rm -f ${DATA}/${IST_FILE} + + if [[ -n $progress && -p $progress ]];then + wsrep_log_info "Cleaning up fifo file $progress" + rm $progress + fi } kill_xtrabackup() { -#set -x local PID=$(cat $XTRABACKUP_PID) [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : rm -f "$XTRABACKUP_PID" -#set +x +} + +setup_ports() +{ + if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then + SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') + REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') + lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') + else + SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') + fi } # waits ~10 seconds for nc to open the port and then reports ready # (regardless of timeout) -wait_for_nc() +wait_for_listen() { local PORT=$1 local ADDR=$2 local MODULE=$3 - for i in $(seq 1 50) + for i in {1..50} do - netstat -nptl 2>/dev/null | grep '/nc\s*$' | awk '{ print $4 }' | \ - sed 's/.*://' | grep \^${PORT}\$ >/dev/null && break + ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break sleep 0.2 done + if [[ $incremental -eq 1 ]];then + echo "ready ${ADDR}/${MODULE}/$lsn" + else echo "ready ${ADDR}/${MODULE}" + fi } -INNOBACKUPEX_BIN=innobackupex -INNOBACKUPEX_ARGS="" -NC_BIN=nc +check_extra() +{ + local use_socket=1 + if [[ $uextra -eq 1 ]];then + if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if [[ -n $eport ]];then + # Xtrabackup works only locally. + # Hence, setting host to 127.0.0.1 unconditionally. + wsrep_log_info "SST through extra_port $eport" + INNOEXTRA+=" --host=127.0.0.1 --port=$eport " + use_socket=0 + else + wsrep_log_error "Extra port $eport null, failing" + exit 1 + fi + else + wsrep_log_info "Thread pool not set, ignore the option use_extra" + fi + fi + if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then + INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" + fi +} -for TOOL_BIN in INNOBACKUPEX_BIN NC_BIN ; do - if ! which ${!TOOL_BIN} > /dev/null 2>&1 - then - echo "Can't find ${!TOOL_BIN} in the path" - exit 22 # EINVAL - fi -done +if [[ ! -x `which innobackupex` ]];then + wsrep_log_error "innobackupex not in path: $PATH" + exit 2 +fi -#ROLE=$1 -#ADDR=$2 -readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) -readonly DATA="${WSREP_SST_OPT_DATA}" -#CONF=$5 - -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" - -MAGIC_FILE="${DATA}/${INFO_FILE}" rm -f "${MAGIC_FILE}" +if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then + wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" + exit 22 +fi + read_cnf +setup_ports +get_stream +get_transfer + +INNOEXTRA="" +INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" +INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then trap cleanup_donor EXIT - NC_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') - REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then - TMPDIR="/tmp" - - INNOBACKUPEX_ARGS="--galera-info --stream=$sfmt - --defaults-file=${WSREP_SST_OPT_CONF} - --socket=${WSREP_SST_OPT_SOCKET}" + TMPDIR="${TMPDIR:-/tmp}" if [ "${AUTH[0]}" != "(null)" ]; then - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --user=${AUTH[0]}" - fi + INNOEXTRA+=" --user=${AUTH[0]}" + fi if [ ${#AUTH[*]} -eq 2 ]; then - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=${AUTH[1]}" - else + INNOEXTRA+=" --password=${AUTH[1]}" + elif [ "${AUTH[0]}" != "(null)" ]; then # Empty password, used for testing, debugging etc. - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --password=" - fi + INNOEXTRA+=" --password=" + fi get_keys if [[ $encrypt -eq 1 ]];then if [[ -n $ekey ]];then - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key=$ekey" + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " else - INNOBACKUPEX_ARGS="${INNOBACKUPEX_ARGS} --encrypt=$ealgo --encrypt-key-file=$ekeyfile" + INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " fi fi - wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${NC_PORT}" + if [[ -n $lsn ]];then + INNOEXTRA+=" --incremental --incremental-lsn=$lsn " + fi + + check_extra + + wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}" + + if [[ -n $progress ]];then + get_footprint + tcmd="$pcmd | $tcmd" + elif [[ -n $rlimit ]];then + adjust_progress + tcmd="$pcmd | $tcmd" + fi set +e - ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ - 2> ${DATA}/innobackup.backup.log | \ - ${NC_BIN} ${REMOTEIP} ${NC_PORT} - - RC=( "${PIPESTATUS[@]}" ) + timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" set -e if [ ${RC[0]} -ne 0 ]; then wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ "Check ${DATA}/innobackup.backup.log" exit 22 - elif [ ${RC[1]} -ne 0 ]; then - wsrep_log_error "${NC_BIN} finished with error: ${RC[1]}" + elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then + wsrep_log_error "$tcmd finished with error: ${RC[1]}" exit 22 fi @@ -272,7 +488,8 @@ then XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" - else # BYPASS + else # BYPASS FOR IST + wsrep_log_info "Bypassing the SST for IST" STATE="${WSREP_SST_OPT_GTID}" echo "continue" # now server can resume updating data @@ -282,15 +499,9 @@ then pushd ${DATA} 1>/dev/null set +e if [[ $encrypt -eq 1 ]];then - if [[ -n $ekey ]];then - xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey | ${NC_BIN} ${REMOTEIP} ${NC_PORT} - else - xbstream -c ${INFO_FILE} ${IST_FILE} | xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | ${NC_BIN} ${REMOTEIP} ${NC_PORT} - fi - else - $strmcmd | ${NC_BIN} ${REMOTEIP} ${NC_PORT} + tcmd=" $ecmd | $tcmd" fi - RC=( "${PIPESTATUS[@]}" ) + timeit "Donor-IST-Unencrypted-transfer" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" set -e popd 1>/dev/null @@ -301,62 +512,81 @@ then exit 1 fi done - #rm -f ${DATA}/${IST_FILE} fi echo "done ${WSREP_SST_OPT_GTID}" + wsrep_log_info "Total time on donor: $totime seconds" elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] then [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" touch $SST_PROGRESS_FILE + if [[ ! -e ${DATA}/ibdata1 ]];then + incremental=0 + fi + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Incremental SST enabled" + #lsn=$(/pxc/bin/mysqld --defaults-file=$WSREP_SST_OPT_CONF --basedir=/pxc --wsrep-recover 2>&1 | grep -o 'log sequence number .*' | cut -d " " -f 4 | head -1) + lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ') + wsrep_log_info "Recovered LSN: $lsn" + fi + sencrypted=1 nthreads=1 MODULE="xtrabackup_sst" - rm -f ${DATA}/xtrabackup_* + # May need xtrabackup_checkpoints later on + rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile ADDR=${WSREP_SST_OPT_ADDR} - NC_PORT=$(echo ${ADDR} | awk -F ':' '{ print $2 }') - if [ -z "${NC_PORT}" ] + if [ -z "${SST_PORT}" ] then - NC_PORT=4444 - ADDR="$(echo ${ADDR} | awk -F ':' '{ print $1 }'):${NC_PORT}" + SST_PORT=4444 + ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" fi - wait_for_nc ${NC_PORT} ${ADDR} ${MODULE} & + wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & - trap "exit 32" HUP PIPE - trap "exit 3" INT TERM + trap sig_joiner_cleanup HUP PIPE INT TERM trap cleanup_joiner EXIT + if [[ -n $progress ]];then + adjust_progress + tcmd+=" | $pcmd" + fi + + if [[ $incremental -eq 1 ]];then + BDATA=$DATA + DATA=$(mktemp -d) + MAGIC_FILE="${DATA}/${INFO_FILE}" + fi + get_keys set +e if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then - if [[ -n $ekey ]];then - ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey | xbstream -x -C ${DATA} - else - ${NC_BIN} -dl ${NC_PORT} | xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile | xbstream -x -C ${DATA} - fi - else - ${NC_BIN} -dl ${NC_PORT} | $strmcmd + strmcmd=" $ecmd | $strmcmd" fi - RC=( "${PIPESTATUS[@]}" ) + + pushd ${DATA} 1>/dev/null + timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + popd 1>/dev/null + set -e if [[ $sfmt == 'xbstream' ]];then # Special handling till lp:1193240 is fixed" if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then wsrep_log_error "Xbstream failed" - wsrep_log_error "Data directory ${DATA} needs to be empty for SST: lp:1193240" \ + wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \ "Manual intervention required in that case" exit 32 fi fi - wait %% # join wait_for_nc thread + wait %% # join for wait_for_listen thread for ecode in "${RC[@]}";do if [[ $ecode -ne 0 ]];then @@ -370,43 +600,25 @@ then then # this message should cause joiner to abort wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" + wsrep_log_info "Contents of datadir" + wsrep_log_info "$(ls -l ${DATA}/**/*)" exit 32 fi - if ! ps -p ${WSREP_SST_OPT_PARENT} >/dev/null + if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null then wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." exit 32 fi - if [ ! -r "${IST_FILE}" ] + if [ ! -r "${DATA}/${IST_FILE}" ] then wsrep_log_info "Proceeding with SST" - rebuild="" wsrep_log_info "Removing existing ib_logfile files" - rm -f ${DATA}/ib_logfile* - - # Decrypt only if not encrypted in stream. - # NOT USED NOW. - # Till https://blueprints.launchpad.net/percona-xtrabackup/+spec/add-support-for-rsync-url - # is implemented - #get_keys - if [[ $encrypt -eq 1 && $sencrypted -eq 0 ]];then - # Decrypt the files if any - find ${DATA} -type f -name '*.xbcrypt' -printf '%p\n' | while read line;do - input=$line - output=${input%.xbcrypt} - - if [[ -n $ekey ]];then - xbcrypt -d --encrypt-algo=$ealgo --encrypt-key=$ekey -i $input > $output - else - xbcrypt -d --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile -i $input > $output - fi - done - - if [[ $? = 0 ]];then - find ${DATA} -type f -name '*.xbcrypt' -delete - fi + if [[ $incremental -ne 1 ]];then + rm -f ${DATA}/ib_logfile* + else + rm -f ${BDATA}/ib_logfile* fi get_proc @@ -414,33 +626,47 @@ then # Rebuild indexes for compact backups if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then wsrep_log_info "Index compaction detected" - nthreads=$(my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -- '--rebuild-threads' | cut -d= -f2) - [[ -z $nthreads ]] && nthreads=$nproc - wsrep_log_info "Rebuilding with $nthreads threads" - rebuild="--rebuild-indexes --rebuild-threads=$nthreads" + rebuild=1 fi - if test -n "$(find ${DATA} -maxdepth 1 -name '*.qp' -print -quit)";then + if [[ $rebuild -eq 1 ]];then + nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) + wsrep_log_info "Rebuilding during prepare with $nthreads threads" + rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" + fi + + if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then wsrep_log_info "Compressed qpress files found" if [[ ! -x `which qpress` ]];then - wsrep_log_error "qpress not found in PATH" + wsrep_log_error "qpress not found in path: $PATH" exit 22 fi - set +e + if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then + count=$(find ${DATA} -type f -name '*.qp' | wc -l) + count=$(( count*2 )) + if pv --help | grep -q FORMAT;then + pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" + else + pvopts="-f -s $count -l -N Decompression" + fi + pcmd="pv $pvopts" + adjust_progress + dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" + else + dcmd="xargs -n 2 qpress -T${nproc}d" + fi wsrep_log_info "Removing existing ibdata1 file" rm -f ${DATA}/ibdata1 # Decompress the qpress files wsrep_log_info "Decompression with $nproc threads" - find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | xargs -P $nproc -n 2 qpress -d + timeit "Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" extcode=$? - set -e - if [[ $extcode -eq 0 ]];then wsrep_log_info "Removing qpress files after decompression" find ${DATA} -type f -name '*.qp' -delete @@ -453,10 +679,21 @@ then fi fi - wsrep_log_info "Preparing the backup at ${DATA}" + if [[ $incremental -eq 1 ]];then + # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. + INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \ + --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" + fi + + wsrep_log_info "Preparing the backup at ${DATA}" + timeit "Xtrabackup prepare stage" "$INNOAPPLY" + + if [[ $incremental -eq 1 ]];then + wsrep_log_info "Cleaning up ${DATA} after incremental SST" + [[ -d ${DATA} ]] && rm -rf ${DATA} + DATA=$BDATA + fi - ${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --apply-log $rebuild \ - ${DATA} 1>&2 2> ${DATA}/innobackup.prepare.log if [ $? -ne 0 ]; then wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" @@ -466,14 +703,13 @@ then wsrep_log_info "${IST_FILE} received from donor: Running IST" fi + if [[ ! -r ${MAGIC_FILE} ]];then + wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" + exit 2 + fi + cat "${MAGIC_FILE}" # output UUID:seqno - - #Cleanup not required here since EXIT trap should be called - #wsrep_cleanup_progress_file - -else - wsrep_log_error "Unrecognized role: ${WSREP_SST_OPT_ROLE}" - exit 22 # EINVAL + wsrep_log_info "Total time on joiner: $totime seconds" fi exit 0 diff --git a/sql/slave.cc b/sql/slave.cc index 7469f28457d..563caf287a7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3456,12 +3456,18 @@ pthread_handler_t handle_slave_sql(void *arg) my_off_t UNINIT_VAR(saved_log_pos); my_off_t UNINIT_VAR(saved_master_log_pos); my_off_t saved_skip= 0; +#ifdef WITH_WSREP + my_bool wsrep_node_dropped= FALSE; +#endif /* WITH_WSREP */ Relay_log_info* rli = &((Master_info*)arg)->rli; const char *errmsg; // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff my_thread_init(); DBUG_ENTER("handle_slave_sql"); +#ifdef WITH_WSREP + wsrep_restart_point: +#endif /* WITH_WSREP */ LINT_INIT(saved_master_log_pos); LINT_INIT(saved_log_pos); @@ -3727,6 +3733,12 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, Error running query, slave SQL thread aborted. Fix the problem, and restart \ the slave SQL thread with \"SLAVE START\". We stopped at log \ '%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff)); +#ifdef WITH_WSREP + if (WSREP_ON && last_errno == ER_UNKNOWN_COM_ERROR) + { + wsrep_node_dropped= TRUE; + } +#endif /* WITH_WSREP */ } goto err; } @@ -3791,6 +3803,27 @@ err_during_init: THD_CHECK_SENTRY(thd); delete thd; mysql_mutex_unlock(&LOCK_thread_count); +#ifdef WITH_WSREP + /* if slave stopped due to node going non primary, we set global flag to + trigger automatic restart of slave when node joins back to cluster + */ + if (wsrep_node_dropped && wsrep_restart_slave) + { + if (wsrep_ready) + { + WSREP_INFO("Slave error due to node temporarily non-primary" + "SQL slave will continue"); + wsrep_node_dropped= FALSE; + mysql_mutex_unlock(&rli->run_lock); + goto wsrep_restart_point; + } else { + WSREP_INFO("Slave error due to node going non-primary"); + WSREP_INFO("wsrep_restart_slave was set and therefore slave will be " + "automatically restarted when node joins back to cluster"); + wsrep_restart_slave_activated= TRUE; + } + } +#endif /* WITH_WSREP */ /* Note: the order of the broadcast and unlock calls below (first broadcast, then unlock) is important. Otherwise a killer_thread can execute between the calls and diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e840b5c7072..893d358d8a8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5181,6 +5181,7 @@ restart: thd->lex->sql_command== SQLCOM_LOAD || thd->lex->sql_command== SQLCOM_DELETE) && wsrep_replicate_myisam && + (*start) && (*start)->table && (*start)->table->file->ht->db_type == DB_TYPE_MYISAM) { WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 30833588e06..aba051d214d 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3918,6 +3918,10 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting( "transaction after every 10K rows inserted", GLOBAL_VAR(wsrep_load_data_splitting), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_restart_slave( + "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", + GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); #endif /* WITH_WSREP */ static Sys_var_charptr Sys_ignore_db_dirs( diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index 933ef3dc31f..af4ec84db85 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -320,3 +320,59 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) } } +void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache) +{ + char filename[PATH_MAX]= {0}; + int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", + wsrep_data_home_dir, thd->thread_id, + (long long)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; + } + cache->read_pos= cache->read_end; + } while ((cache->file >= 0) && (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); +} + diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index 6de73b2f5ee..76192f6e119 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -46,4 +46,7 @@ int wsrep_write_cache (wsrep_t* wsrep, /* 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); + #endif /* WSREP_BINLOG_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index c5627ff97fb..84034ec776e 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -505,11 +505,17 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) DBUG_RETURN(WSREP_TRX_CERT_FAIL); + case WSREP_SIZE_EXCEEDED: + WSREP_ERROR("transaction size exceeded"); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED); case WSREP_CONN_FAIL: WSREP_ERROR("connection failure"); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); DBUG_RETURN(WSREP_TRX_ERROR); default: WSREP_ERROR("unknown connection failure"); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); DBUG_RETURN(WSREP_TRX_ERROR); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 5867b063426..4fd07a9945c 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -26,6 +26,7 @@ #include #include #include "log_event.h" +#include Format_description_log_event *wsrep_format_desc = NULL; wsrep_t *wsrep = NULL; @@ -59,7 +60,10 @@ ulong wsrep_mysql_replication_bundle = 0; my_bool wsrep_desync = 0; // desynchronize the node from the // cluster my_bool wsrep_load_data_splitting = 1; // commit load data every 10K intervals - +my_bool wsrep_restart_slave = 0; // should mysql slave thread be + // restarted, if node joins back +my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave + // restart will be needed /* * End configuration options */ @@ -406,6 +410,25 @@ static void wsrep_synced_cb(void* app_ctx) // and wait for SE initialization wsrep_SE_init_wait(); } + if (wsrep_restart_slave_activated) + { + int rcode; + WSREP_INFO("MySQL slave restart"); + wsrep_restart_slave_activated= FALSE; + + mysql_mutex_lock(&LOCK_active_mi); + if ((rcode = start_slave_threads(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() @@ -627,6 +650,7 @@ int wsrep_init() { 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 { @@ -1159,7 +1183,7 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) } buff.append(STRING_WITH_LEN(" AS ")); //buff.append(views->source.str, views->source.length); - buff.append(thd->lex->create_view_select.str, + 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, @@ -1168,7 +1192,7 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) } static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, - const TABLE_LIST* table_list) + const TABLE_LIST* table_list) { wsrep_status_t ret(WSREP_WARNING); uchar* buf(0); @@ -1193,7 +1217,7 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, buf_err= wsrep_create_event_query(thd, &buf, &buf_len); break; default: - buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, + buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, &buf_len); break; } @@ -1243,7 +1267,7 @@ static void wsrep_TOI_end(THD *thd) { } } -static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) +static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) { wsrep_status_t ret(WSREP_WARNING); WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), @@ -1325,9 +1349,9 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, int ret= 0; mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) + if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", + WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", thd->thread_id, thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); return WSREP_TRX_FAIL; @@ -1346,7 +1370,7 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (wsrep_debug && thd->mdl_context.has_locks()) { - WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", + WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", thd->query(), thd->thread_id); } @@ -1438,7 +1462,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } - else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) + else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) { WSREP_DEBUG("DROP caused BF abort"); ticket->wsrep_report(wsrep_debug); @@ -1446,7 +1470,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; } - else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) + else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) { WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); ticket->wsrep_report(wsrep_debug); @@ -1454,7 +1478,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; } - else + else { WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); ticket->wsrep_report(wsrep_debug); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 5cf0d9dc0c5..ec2a38278ab 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -95,6 +95,8 @@ 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; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index 291cdbb7c75..6eefb961b62 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -75,15 +75,18 @@ void wsrep_notify_status (wsrep_member_status_t status, cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --index %d", view->my_idx); - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --members"); - - for (int i = 0; i < view->memb_num; i++) + if (view->memb_num) { - 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 (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); + } } } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index ec636a8b1ec..37c55707b28 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -934,8 +934,9 @@ wait_signal: else { 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 { diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 189d4bacc0e..c03763c7d45 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1207,6 +1207,7 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_bindir}/wsrep_sst_rsync %attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan %attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup +%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup-v2 %endif %attr(755, root, root) %{_sbindir}/mysqld diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh index bdbe3d12a39..c36a9ddc62a 100644 --- a/support-files/wsrep_notify.sh +++ b/support-files/wsrep_notify.sh @@ -87,6 +87,7 @@ do --members) MEMBERS=$2 shift + fi ;; esac shift diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index f713de66d57..c3304d7ed7c 100644 --- a/wsrep/wsrep_api.h +++ b/wsrep/wsrep_api.h @@ -137,7 +137,11 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); 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) diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index 3c7a7c2e354..3c7f97ede3f 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -388,4 +388,3 @@ int wsrep_dummy_loader(wsrep_t* w) return 0; } - From 11324465e099d73b668f558ec1ff360dfe006e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 18 Apr 2014 07:51:52 +0300 Subject: [PATCH 130/294] Merge lp:maria/5.5 up to mariadb-5.5.37 revision 4148. --- storage/innobase/fil/fil0fil.c | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 0367484ebf0..3b09222a530 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -4190,7 +4190,6 @@ fil_extend_space_to_desired_size( } mem_free(buf2); - fil_node_complete_io(node, fil_system, OS_FILE_WRITE); complete_io: From dee153c1b8c8949b460a39b8ea8f6edef4795bd2 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 18 Apr 2014 16:56:44 -0400 Subject: [PATCH 131/294] * Removed unnecessary duplicate script files. * Updated failing mtr tests. --- mysql-test/r/mysqld--help.result | 4 + mysql-test/suite/sys_vars/r/all_vars.result | 1 + scripts/wsrep_sst_common | 127 --- scripts/wsrep_sst_xtrabackup-v2 | 879 -------------------- support-files/wsrep_notify.sh | 1 - 5 files changed, 5 insertions(+), 1007 deletions(-) delete mode 100755 scripts/wsrep_sst_common delete mode 100755 scripts/wsrep_sst_xtrabackup-v2 diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index ff0967ed483..c4106d06553 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -911,6 +911,9 @@ The following options may be given as the first argument: --wsrep-recover Recover database state after crash and exit --wsrep-replicate-myisam To enable myisam replication + --wsrep-restart-slave + Should MySQL slave be restarted automatically, when node + joins back to cluster --wsrep-retry-autocommit=# Max number of times to retry a failed autocommit statement @@ -1204,6 +1207,7 @@ wsrep-provider none wsrep-provider-options wsrep-recover FALSE wsrep-replicate-myisam FALSE +wsrep-restart-slave FALSE wsrep-retry-autocommit 1 wsrep-slave-threads 1 wsrep-sst-auth (No default value) diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index adfd9f3bbe6..d7a72989d81 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -38,6 +38,7 @@ wsrep_provider wsrep_provider_options wsrep_recover wsrep_replicate_myisam +wsrep_restart_slave wsrep_retry_autocommit wsrep_slave_threads wsrep_sst_auth diff --git a/scripts/wsrep_sst_common b/scripts/wsrep_sst_common deleted file mode 100755 index f9a08c1c695..00000000000 --- a/scripts/wsrep_sst_common +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (C) 2012 Codership Oy -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# This is a common command line parser to be sourced by other SST scripts - -set -u - -WSREP_SST_OPT_BYPASS=0 -WSREP_SST_OPT_DATA="" - -while [ $# -gt 0 ]; do -case "$1" in - '--address') - readonly WSREP_SST_OPT_ADDR="$2" - shift - ;; - '--auth') - WSREP_SST_OPT_AUTH="$2" - shift - ;; - '--bypass') - WSREP_SST_OPT_BYPASS=1 - ;; - '--datadir') - readonly WSREP_SST_OPT_DATA="$2" - shift - ;; - '--defaults-file') - readonly WSREP_SST_OPT_CONF="$2" - shift - ;; - '--host') - readonly WSREP_SST_OPT_HOST="$2" - shift - ;; - '--local-port') - readonly WSREP_SST_OPT_LPORT="$2" - shift - ;; - '--parent') - readonly WSREP_SST_OPT_PARENT="$2" - shift - ;; - '--password') - readonly WSREP_SST_OPT_PSWD="$2" - shift - ;; - '--port') - readonly WSREP_SST_OPT_PORT="$2" - shift - ;; - '--role') - readonly WSREP_SST_OPT_ROLE="$2" - shift - ;; - '--socket') - readonly WSREP_SST_OPT_SOCKET="$2" - shift - ;; - '--user') - readonly WSREP_SST_OPT_USER="$2" - shift - ;; - '--gtid') - readonly WSREP_SST_OPT_GTID="$2" - shift - ;; - *) # must be command - # usage - # exit 1 - ;; -esac -shift -done -readonly WSREP_SST_OPT_BYPASS - -# For Bug:1200727 -if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then - if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then - WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) - fi -fi - -if [ -n "${WSREP_SST_OPT_DATA:-}" ] -then - SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" -else - SST_PROGRESS_FILE="" -fi - - -wsrep_log() -{ - # echo everything to stderr so that it gets into common error log - # deliberately made to look different from the rest of the log - local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)" - echo "WSREP_SST: $* ($tst)" >&2 -} - -wsrep_log_error() -{ - wsrep_log "[ERROR] $*" -} - -wsrep_log_info() -{ - wsrep_log "[INFO] $*" -} - -wsrep_cleanup_progress_file() -{ - [ -n "$SST_PROGRESS_FILE" ] && rm -f "$SST_PROGRESS_FILE" 2>/dev/null -} - diff --git a/scripts/wsrep_sst_xtrabackup-v2 b/scripts/wsrep_sst_xtrabackup-v2 deleted file mode 100755 index 59017fff8df..00000000000 --- a/scripts/wsrep_sst_xtrabackup-v2 +++ /dev/null @@ -1,879 +0,0 @@ -#!/bin/bash -ue -# Copyright (C) 2013 Percona Inc -# -# 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; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1301 USA. - -# Documentation: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html -# Make sure to read that before proceeding! - - - - -. $(dirname $0)/wsrep_sst_common - -ealgo="" -ekey="" -ekeyfile="" -encrypt=0 -nproc=1 -ecode=0 -XTRABACKUP_PID="" -SST_PORT="" -REMOTEIP="" -tcert="" -tpem="" -tkey="" -sockopt="" -progress="" -ttime=0 -totime=0 -lsn="" -incremental=0 -ecmd="" -rlimit="" -# Initially -stagemsg="${WSREP_SST_OPT_ROLE}" -cpat="" -speciald=0 -ib_home_dir="" -ib_log_dir="" - -sfmt="tar" -strmcmd="" -tfmt="" -tcmd="" -rebuild=0 -rebuildcmd="" -payload=0 -pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p' " -pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE " -STATDIR="" -uextra=0 -disver="" - -scomp="" -sdecomp="" - -if which pv &>/dev/null && pv --help | grep -q FORMAT;then - pvopts+=$pvformat -fi -pcmd="pv $pvopts" -declare -a RC - -INNOBACKUPEX_BIN=innobackupex -readonly AUTH=(${WSREP_SST_OPT_AUTH//:/ }) -DATA="${WSREP_SST_OPT_DATA}" -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" -MAGIC_FILE="${DATA}/${INFO_FILE}" - -# Setting the path for ss and ip -export PATH="/usr/sbin:/sbin:$PATH" - -timeit(){ - local stage=$1 - shift - local cmd="$@" - local x1 x2 took extcode - - if [[ $ttime -eq 1 ]];then - x1=$(date +%s) - wsrep_log_info "Evaluating $cmd" - eval "$cmd" - extcode=$? - x2=$(date +%s) - took=$(( x2-x1 )) - wsrep_log_info "NOTE: $stage took $took seconds" - totime=$(( totime+took )) - else - wsrep_log_info "Evaluating $cmd" - eval "$cmd" - extcode=$? - fi - return $extcode -} - -get_keys() -{ - # $encrypt -eq 1 is for internal purposes only - if [[ $encrypt -ge 2 || $encrypt -eq -1 ]];then - return - fi - - if [[ $encrypt -eq 0 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then - wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " - fi - return - fi - - if [[ $sfmt == 'tar' ]];then - wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" - encrypt=-1 - return - fi - - wsrep_log_info "Xtrabackup based encryption enabled in my.cnf - Supported only from Xtrabackup 2.1.4" - - if [[ -z $ealgo ]];then - wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" - exit 3 - fi - - if [[ -z $ekey && ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Either key or keyfile must be readable" - exit 3 - fi - - if [[ -z $ekey ]];then - ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" - else - ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" - fi - - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - ecmd+=" -d" - fi - - stagemsg+="-XB-Encrypted" -} - -get_transfer() -{ - if [[ -z $SST_PORT ]];then - TSST_PORT=4444 - else - TSST_PORT=$SST_PORT - fi - - if [[ $tfmt == 'nc' ]];then - if [[ ! -x `which nc` ]];then - wsrep_log_error "nc(netcat) not found in path: $PATH" - exit 2 - fi - wsrep_log_info "Using netcat as streamer" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - tcmd="nc -dl ${TSST_PORT}" - else - tcmd="nc ${REMOTEIP} ${TSST_PORT}" - fi - else - tfmt='socat' - wsrep_log_info "Using socat as streamer" - if [[ ! -x `which socat` ]];then - wsrep_log_error "socat not found in path: $PATH" - exit 2 - fi - - if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then - wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" - encrypt=-1 - fi - - if [[ $encrypt -eq 2 ]];then - wsrep_log_info "Using openssl based encryption with socat: with crt and pem" - if [[ -z $tpem || -z $tcert ]];then - wsrep_log_error "Both PEM and CRT files required" - exit 22 - fi - stagemsg+="-OpenSSL-Encrypted-2" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" - else - wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" - fi - elif [[ $encrypt -eq 3 ]];then - wsrep_log_info "Using openssl based encryption with socat: with key and crt" - if [[ -z $tpem || -z $tkey ]];then - wsrep_log_error "Both certificate and key files required" - exit 22 - fi - stagemsg+="-OpenSSL-Encrypted-3" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with certificate $tpem, key $tkey" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio" - else - wsrep_log_info "Encrypting with certificate $tpem, key $tkey" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}" - fi - - else - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" - else - tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" - fi - fi - fi - -} - -parse_cnf() -{ - local group=$1 - local var=$2 - reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) - if [[ -z $reval ]];then - [[ -n $3 ]] && reval=$3 - fi - echo $reval -} - -get_footprint() -{ - pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then - # QuickLZ has around 50% compression ratio - # When compression/compaction used, the progress is only an approximate. - payload=$(( payload*1/2 )) - fi - popd 1>/dev/null - pcmd+=" -s $payload" - adjust_progress -} - -adjust_progress() -{ - if [[ -n $progress && $progress != '1' ]];then - if [[ -e $progress ]];then - pcmd+=" 2>>$progress" - else - pcmd+=" 2>$progress" - fi - elif [[ -z $progress && -n $rlimit ]];then - # When rlimit is non-zero - pcmd="pv -q" - fi - - if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then - wsrep_log_info "Rate-limiting SST to $rlimit" - pcmd+=" -L \$rlimit" - fi -} - -read_cnf() -{ - sfmt=$(parse_cnf sst streamfmt "xbstream") - tfmt=$(parse_cnf sst transferfmt "socat") - tcert=$(parse_cnf sst tca "") - tpem=$(parse_cnf sst tcert "") - tkey=$(parse_cnf sst tkey "") - encrypt=$(parse_cnf sst encrypt 0) - sockopt=$(parse_cnf sst sockopt "") - progress=$(parse_cnf sst progress "") - rebuild=$(parse_cnf sst rebuild 0) - ttime=$(parse_cnf sst time 0) - cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') - incremental=$(parse_cnf sst incremental 0) - ealgo=$(parse_cnf xtrabackup encrypt "") - ekey=$(parse_cnf xtrabackup encrypt-key "") - ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") - scomp=$(parse_cnf sst compressor "") - sdecomp=$(parse_cnf sst decompressor "") - - - # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html - if [[ -z $ealgo ]];then - ealgo=$(parse_cnf sst encrypt-algo "") - ekey=$(parse_cnf sst encrypt-key "") - ekeyfile=$(parse_cnf sst encrypt-key-file "") - fi - rlimit=$(parse_cnf sst rlimit "") - uextra=$(parse_cnf sst use_extra 0) - speciald=$(parse_cnf sst sst-special-dirs 1) - iopts=$(parse_cnf sst inno-backup-opts "") - iapts=$(parse_cnf sst inno-apply-opts "") - impts=$(parse_cnf sst inno-move-opts "") -} - -get_stream() -{ - if [[ $sfmt == 'xbstream' ]];then - wsrep_log_info "Streaming with xbstream" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="xbstream -x" - else - strmcmd="xbstream -c \${INFO_FILE}" - fi - else - sfmt="tar" - wsrep_log_info "Streaming with tar" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="tar xfi - " - else - strmcmd="tar cf - \${INFO_FILE} " - fi - - fi -} - -get_proc() -{ - set +e - nproc=$(grep -c processor /proc/cpuinfo) - [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 - set -e -} - -sig_joiner_cleanup() -{ - wsrep_log_error "Removing $MAGIC_FILE file due to signal" - rm -f "$MAGIC_FILE" -} - -cleanup_joiner() -{ - # Since this is invoked just after exit NNN - local estatus=$? - if [[ $estatus -ne 0 ]];then - wsrep_log_error "Cleanup after exit with status:$estatus" - fi - if [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then - wsrep_log_info "Removing the sst_in_progress file" - wsrep_cleanup_progress_file - fi - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm $progress - fi - if [[ -n ${STATDIR:-} ]];then - [[ -d $STATDIR ]] && rm -rf $STATDIR - fi -} - -check_pid() -{ - local pid_file="$1" - [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 -} - -cleanup_donor() -{ - # Since this is invoked just after exit NNN - local estatus=$? - if [[ $estatus -ne 0 ]];then - wsrep_log_error "Cleanup after exit with status:$estatus" - fi - - if [[ -n $XTRABACKUP_PID ]];then - if check_pid $XTRABACKUP_PID - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - fi - - rm -f $XTRABACKUP_PID - fi - rm -f ${DATA}/${IST_FILE} - - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm $progress - fi -} - -kill_xtrabackup() -{ - local PID=$(cat $XTRABACKUP_PID) - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$XTRABACKUP_PID" -} - -setup_ports() -{ - if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') - REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') - else - SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') - fi -} - -# waits ~10 seconds for nc to open the port and then reports ready -# (regardless of timeout) -wait_for_listen() -{ - local PORT=$1 - local ADDR=$2 - local MODULE=$3 - for i in {1..50} - do - ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break - sleep 0.2 - done - if [[ $incremental -eq 1 ]];then - echo "ready ${ADDR}/${MODULE}/$lsn" - else - echo "ready ${ADDR}/${MODULE}" - fi -} - -check_extra() -{ - local use_socket=1 - if [[ $uextra -eq 1 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) - if [[ -n $eport ]];then - # Xtrabackup works only locally. - # Hence, setting host to 127.0.0.1 unconditionally. - wsrep_log_info "SST through extra_port $eport" - INNOEXTRA+=" --host=127.0.0.1 --port=$eport " - use_socket=0 - else - wsrep_log_error "Extra port $eport null, failing" - exit 1 - fi - else - wsrep_log_info "Thread pool not set, ignore the option use_extra" - fi - fi - if [[ $use_socket -eq 1 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then - INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" - fi -} - -recv_joiner() -{ - local dir=$1 - local msg=$2 - - pushd ${dir} 1>/dev/null - set +e - timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - popd 1>/dev/null - - - for ecode in "${RC[@]}";do - if [[ $ecode -ne 0 ]];then - wsrep_log_error "Error while getting data from donor node: " \ - "exit codes: ${RC[@]}" - exit 32 - fi - done - - if [ ! -r "${MAGIC_FILE}" ];then - # this message should cause joiner to abort - wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" - wsrep_log_info "Contents of datadir" - wsrep_log_info "$(ls -l ${dir}/*)" - exit 32 - fi -} - - -send_donor() -{ - local dir=$1 - local msg=$2 - - pushd ${dir} 1>/dev/null - set +e - timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - popd 1>/dev/null - - - for ecode in "${RC[@]}";do - if [[ $ecode -ne 0 ]];then - wsrep_log_error "Error while getting data from donor node: " \ - "exit codes: ${RC[@]}" - exit 32 - fi - done - -} - -if [[ ! -x `which innobackupex` ]];then - wsrep_log_error "innobackupex not in path: $PATH" - exit 2 -fi - -rm -f "${MAGIC_FILE}" - -if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then - wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" - exit 22 -fi - -read_cnf -setup_ports -get_stream -get_transfer - -if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then - disver="--no-version-check" -fi - - -INNOEXTRA="" -INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" -INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" -INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" - -if [ "$WSREP_SST_OPT_ROLE" = "donor" ] -then - trap cleanup_donor EXIT - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - - TMPDIR="${TMPDIR:-/tmp}" - - if [ "${AUTH[0]}" != "(null)" ]; then - INNOEXTRA+=" --user=${AUTH[0]}" - fi - - if [ ${#AUTH[*]} -eq 2 ]; then - INNOEXTRA+=" --password=${AUTH[1]}" - elif [ "${AUTH[0]}" != "(null)" ]; then - # Empty password, used for testing, debugging etc. - INNOEXTRA+=" --password=" - fi - - get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $ekey ]];then - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " - else - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " - fi - fi - - if [[ -n $lsn ]];then - INNOEXTRA+=" --incremental --incremental-lsn=$lsn " - fi - - check_extra - - wsrep_log_info "Streaming GTID file before SST" - - echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" - - ttcmd="$tcmd" - - if [[ $encrypt -eq 1 ]];then - if [[ -n $scomp ]];then - tcmd=" $ecmd | $scomp | $tcmd " - else - tcmd=" $ecmd | $tcmd " - fi - elif [[ -n $scomp ]];then - tcmd=" $scomp | $tcmd " - fi - - - send_donor $DATA "${stagemsg}-gtid" - - tcmd="$ttcmd" - if [[ -n $progress ]];then - get_footprint - tcmd="$pcmd | $tcmd" - elif [[ -n $rlimit ]];then - adjust_progress - tcmd="$pcmd | $tcmd" - fi - - wsrep_log_info "Sleeping before data transfer for SST" - sleep 10 - - wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" - - if [[ -n $scomp ]];then - tcmd="$scomp | $tcmd" - fi - - set +e - timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - - if [ ${RC[0]} -ne 0 ]; then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ - "Check ${DATA}/innobackup.backup.log" - exit 22 - elif [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then - wsrep_log_error "$tcmd finished with error: ${RC[1]}" - exit 22 - fi - - # innobackupex implicitly writes PID to fixed location in ${TMPDIR} - XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" - - - else # BYPASS FOR IST - - wsrep_log_info "Bypassing the SST for IST" - echo "continue" # now server can resume updating data - echo "${WSREP_SST_OPT_GTID}" > "${MAGIC_FILE}" - echo "1" > "${DATA}/${IST_FILE}" - get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $scomp ]];then - tcmd=" $ecmd | $scomp | $tcmd " - else - tcmd=" $ecmd | $tcmd " - fi - elif [[ -n $scomp ]];then - tcmd=" $scomp | $tcmd " - fi - strmcmd+=" \${IST_FILE}" - - send_donor $DATA "${stagemsg}-IST" - - fi - - echo "done ${WSREP_SST_OPT_GTID}" - wsrep_log_info "Total time on donor: $totime seconds" - -elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ] -then - [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" - [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE - - if [[ $speciald -eq 1 ]];then - wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter." - fi - - if [[ $speciald -eq 1 ]];then - ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "") - ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") - if [[ -z $ib_home_dir && -z $ib_log_dir ]];then - speciald=0 - fi - fi - - stagemsg="Joiner-Recv" - - if [[ ! -e ${DATA}/ibdata1 ]];then - incremental=0 - fi - - if [[ $incremental -eq 1 ]];then - wsrep_log_info "Incremental SST enabled: NOT SUPPORTED yet" - lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ') - wsrep_log_info "Recovered LSN: $lsn" - fi - - sencrypted=1 - nthreads=1 - - MODULE="xtrabackup_sst" - - rm -f "${DATA}/${IST_FILE}" - - # May need xtrabackup_checkpoints later on - rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile - - ADDR=${WSREP_SST_OPT_ADDR} - if [ -z "${SST_PORT}" ] - then - SST_PORT=4444 - ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" - fi - - wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & - - trap sig_joiner_cleanup HUP PIPE INT TERM - trap cleanup_joiner EXIT - - if [[ -n $progress ]];then - adjust_progress - tcmd+=" | $pcmd" - fi - - if [[ $incremental -eq 1 ]];then - BDATA=$DATA - DATA=$(mktemp -d) - MAGIC_FILE="${DATA}/${INFO_FILE}" - fi - - get_keys - if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then - if [[ -n $sdecomp ]];then - strmcmd=" $sdecomp | $ecmd | $strmcmd" - else - strmcmd=" $ecmd | $strmcmd" - fi - elif [[ -n $sdecomp ]];then - strmcmd=" $sdecomp | $strmcmd" - fi - - STATDIR=$(mktemp -d) - MAGIC_FILE="${STATDIR}/${INFO_FILE}" - recv_joiner $STATDIR "${stagemsg}-gtid" 1 - - if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null - then - wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." - exit 32 - fi - - if [ ! -r "${STATDIR}/${IST_FILE}" ] - then - wsrep_log_info "Proceeding with SST" - - if [[ $speciald -eq 1 && -d ${DATA}/.sst ]];then - wsrep_log_info "WARNING: Stale temporary SST directory: ${DATA}/.sst from previous SST" - fi - - if [[ $incremental -ne 1 ]];then - if [[ $speciald -eq 1 ]];then - wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" - find $ib_home_dir $ib_log_dir $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ - else - wsrep_log_info "Cleaning the existing datadir" - find $DATA -mindepth 1 -regex $cpat -prune -o -exec rm -rfv {} 1>&2 \+ - fi - tempdir=$(parse_cnf mysqld log-bin "") - if [[ -n ${tempdir:-} ]];then - binlog_dir=$(dirname $tempdir) - binlog_file=$(basename $tempdir) - if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then - pattern="$binlog_dir/$binlog_file\.[0-9]+$" - wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" - find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ - rm $binlog_dir/*.index || true - fi - fi - - else - wsrep_log_info "Removing existing ib_logfile files" - rm -f ${BDATA}/ib_logfile* - fi - - - if [[ $speciald -eq 1 ]];then - mkdir -p ${DATA}/.sst - TDATA=${DATA} - DATA="${DATA}/.sst" - fi - - - MAGIC_FILE="${DATA}/${INFO_FILE}" - recv_joiner $DATA "${stagemsg}-SST" 0 - - get_proc - - # Rebuild indexes for compact backups - if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then - wsrep_log_info "Index compaction detected" - rebuild=1 - fi - - if [[ $rebuild -eq 1 ]];then - nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) - wsrep_log_info "Rebuilding during prepare with $nthreads threads" - rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" - fi - - if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then - - wsrep_log_info "Compressed qpress files found" - - if [[ ! -x `which qpress` ]];then - wsrep_log_error "qpress not found in path: $PATH" - exit 22 - fi - - if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then - count=$(find ${DATA} -type f -name '*.qp' | wc -l) - count=$(( count*2 )) - if pv --help | grep -q FORMAT;then - pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" - else - pvopts="-f -s $count -l -N Decompression" - fi - pcmd="pv $pvopts" - adjust_progress - dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" - else - dcmd="xargs -n 2 qpress -T${nproc}d" - fi - - - # Decompress the qpress files - wsrep_log_info "Decompression with $nproc threads" - timeit "Joiner-Decompression" "find ${DATA} -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" - extcode=$? - - if [[ $extcode -eq 0 ]];then - wsrep_log_info "Removing qpress files after decompression" - find ${DATA} -type f -name '*.qp' -delete - if [[ $? -ne 0 ]];then - wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" - fi - else - wsrep_log_error "Decompression failed. Exit code: $extcode" - exit 22 - fi - fi - - if [[ $incremental -eq 1 ]];then - # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. - INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \ - --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" - fi - - wsrep_log_info "Preparing the backup at ${DATA}" - timeit "Xtrabackup prepare stage" "$INNOAPPLY" - - if [ $? -ne 0 ]; - then - wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log" - exit 22 - fi - - if [[ $speciald -eq 1 ]];then - MAGIC_FILE="${TDATA}/${INFO_FILE}" - set +e - rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log - set -e - wsrep_log_info "Moving the backup to ${TDATA}" - timeit "Xtrabackup move stage" "$INNOMOVE" - if [[ $? -eq 0 ]];then - wsrep_log_info "Move successful, removing ${DATA}" - rm -rf $DATA - DATA=${TDATA} - else - wsrep_log_error "Move failed, keeping ${DATA} for further diagnosis" - wsrep_log_error "Check ${DATA}/innobackup.move.log for details" - fi - fi - - if [[ $incremental -eq 1 ]];then - wsrep_log_info "Cleaning up ${DATA} after incremental SST" - [[ -d ${DATA} ]] && rm -rf ${DATA} - DATA=$BDATA - fi - - else - wsrep_log_info "${IST_FILE} received from donor: Running IST" - fi - - if [[ ! -r ${MAGIC_FILE} ]];then - wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" - exit 2 - fi - - cat "${MAGIC_FILE}" # output UUID:seqno - wsrep_log_info "Total time on joiner: $totime seconds" -fi - -exit 0 diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh index c36a9ddc62a..bdbe3d12a39 100644 --- a/support-files/wsrep_notify.sh +++ b/support-files/wsrep_notify.sh @@ -87,7 +87,6 @@ do --members) MEMBERS=$2 shift - fi ;; esac shift From b981c7a927f4a3721b4753d5fa73b966bf2eef96 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 18 Apr 2014 19:16:46 -0400 Subject: [PATCH 132/294] Updated WSREP_PATCH_REVNO. --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 95f3f4fcd8f..628cfd1b092 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "10") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "3961") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "3980") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. From 1950457c14646b108bec1fadb40b75440c3a3d41 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 21 Apr 2014 21:45:19 -0400 Subject: [PATCH 133/294] MDEV#6148 main.flush_read_lock fails due to conflicting read lock TOI was being attempted even when WSREP_ON was not enabled (off). So, with FTWRL in place TOI later gets aborted & thus the failure. Fixed by adding a check to skip TOI if wsrep is not enabled. --- sql/sql_alter.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 75d27016317..0b4636c1f0f 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -102,8 +102,9 @@ bool Alter_table_statement::execute(THD *thd) #ifdef WITH_WSREP TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); - if (!thd->is_current_stmt_binlog_format_row() || - !find_temporary_table(thd, first_table)) + if (WSREP(thd) && + (!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, first_table))) { if (wsrep_to_isolation_begin(thd, lex->name.str ? select_lex->db : NULL, From 2ab559023acc424a967037f50b7d149d821afb75 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 24 Apr 2014 22:52:07 -0400 Subject: [PATCH 134/294] Fixing file paths in @TOKUDB_DEB_FILES@. --- storage/tokudb/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index 6e6db9db3e2..54acfdce5a5 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -14,7 +14,7 @@ IF(NOT TOKUDB_OK OR WITHOUT_TOKUDB OR WITHOUT_TOKUDB_STORAGE_ENGINE) ENDIF() SET(TOKUDB_VERSION "7.1.5") -SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-server-5.5/README-TOKUDB\nusr/share/doc/mariadb-server-5.5/README.md" PARENT_SCOPE) +SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-galera-server-5.5/README-TOKUDB\nusr/share/doc/mariadb-galera-server-5.5/README.md" PARENT_SCOPE) SET(USE_BDB OFF CACHE BOOL "") SET(USE_VALGRIND OFF CACHE BOOL "") SET(BUILD_TESTING OFF CACHE BOOL "") From 98519db3416562928c62fc2c05355f1f4ffd9208 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 25 Apr 2014 10:58:51 -0400 Subject: [PATCH 135/294] MDEV#6171: Fix error message for split-brain Using my_message() (instead of my_error()) to send error message to the client. --- sql/sql_parse.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c6a81b878b3..e3db685b439 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -860,8 +860,9 @@ bool do_command(THD *thd) command != COM_TIME && command != COM_END ) { - my_error(ER_UNKNOWN_COM_ERROR, MYF(0), - "WSREP has not yet prepared node for application use"); + my_message(ER_UNKNOWN_COM_ERROR, + "WSREP has not yet prepared node for application use", + MYF(0)); thd->protocol->end_statement(); return_value= FALSE; goto out; @@ -2407,8 +2408,9 @@ mysql_execute_command(THD *thd) strncmp(thd->query(), mysqldump_magic_str, mysqldump_magic_str_len)) { #endif /* DIRTY_HACK */ - my_error(ER_UNKNOWN_COM_ERROR, MYF(0), - "WSREP has not yet prepared node for application use"); + my_message(ER_UNKNOWN_COM_ERROR, + "WSREP has not yet prepared node for application use", + MYF(0)); goto error; #if DIRTY_HACK } From f36e3d0dab29a9b19662f94b02a81da63a7fde1a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 25 Apr 2014 16:14:22 -0400 Subject: [PATCH 136/294] MDEV#6148 : Updating test result. --- .../r/auto_increment_increment_func.result | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result b/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result index a7ce4e99e20..df3ca1ab093 100644 --- a/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result +++ b/mysql-test/suite/sys_vars/r/auto_increment_increment_func.result @@ -142,8 +142,8 @@ id name 116 Record_10 117 Record_11 119 Record_12 -120 Record_13 -121 Record_14 +121 Record_13 +123 Record_14 ## Changing column's datatype to BigInt and verifying variable's behavior ## ALTER table t1 MODIFY id BIGINT NOT NULL auto_increment; INSERT into t1(name) values('Record_15'); @@ -159,10 +159,10 @@ id name 116 Record_10 117 Record_11 119 Record_12 -120 Record_13 -121 Record_14 -122 Record_15 -123 Record_16 +121 Record_13 +123 Record_14 +125 Record_15 +127 Record_16 '#--------------------FN_DYNVARS_001_07-------------------------#' ## Verifying behavior of variable with negative value ## SET @@auto_increment_increment = -10; @@ -181,12 +181,12 @@ id name 116 Record_10 117 Record_11 119 Record_12 -120 Record_13 -121 Record_14 -122 Record_15 -123 Record_16 -124 Record_17 -125 Record_18 +121 Record_13 +123 Record_14 +125 Record_15 +127 Record_16 +128 Record_17 +129 Record_18 ## Disconnecting test_con2 ## ## Dropping table t1 ## DROP table if exists t1; From 29466e2c85f2c1ab628237a3aca0bcf206d941ec Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 25 Apr 2014 18:23:14 -0400 Subject: [PATCH 137/294] * Adding wsrep_sst_xtrabackup-v2 to deb server files * Updated .bzrignore --- .bzrignore | 2 ++ debian/dist/Debian/mariadb-galera-server-5.5.files.in | 1 + debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in | 1 + 3 files changed, 4 insertions(+) diff --git a/.bzrignore b/.bzrignore index 3c86edbef52..f59296c1f36 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1095,9 +1095,11 @@ sql/share/slovak sql/share/spanish sql/share/swedish sql/share/ukrainian +scripts/wsrep_sst_common scripts/wsrep_sst_mysqldump scripts/wsrep_sst_rsync scripts/wsrep_sst_xtrabackup +scripts/wsrep_sst_xtrabackup-v2 CPackConfig.cmake CPackSourceConfig.cmake Docs/INFO_BIN diff --git a/debian/dist/Debian/mariadb-galera-server-5.5.files.in b/debian/dist/Debian/mariadb-galera-server-5.5.files.in index 063a2977b03..b7be2c77634 100644 --- a/debian/dist/Debian/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Debian/mariadb-galera-server-5.5.files.in @@ -43,6 +43,7 @@ usr/bin/wsrep_sst_common usr/bin/wsrep_sst_mysqldump usr/bin/wsrep_sst_rsync usr/bin/wsrep_sst_xtrabackup +usr/bin/wsrep_sst_xtrabackup-v2 usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN diff --git a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in index 3503bf6dd71..308710858d7 100644 --- a/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in +++ b/debian/dist/Ubuntu/mariadb-galera-server-5.5.files.in @@ -45,6 +45,7 @@ usr/bin/wsrep_sst_common usr/bin/wsrep_sst_mysqldump usr/bin/wsrep_sst_rsync usr/bin/wsrep_sst_xtrabackup +usr/bin/wsrep_sst_xtrabackup-v2 usr/share/doc/mariadb-galera-server-5.5/mysqld.sym.gz usr/share/doc/mariadb-galera-server-5.5/INFO_SRC usr/share/doc/mariadb-galera-server-5.5/INFO_BIN From 4515a6d31e954194482cda99204792dcf9ab75a3 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 28 Apr 2014 10:33:22 -0400 Subject: [PATCH 138/294] MDEV#6148 : Updating auto_increment_offset_func.result. --- .../r/auto_increment_offset_func.result | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result b/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result index 58ecf95dae3..d2b5b828c04 100644 --- a/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result +++ b/mysql-test/suite/sys_vars/r/auto_increment_offset_func.result @@ -144,8 +144,8 @@ id name 125 Record_12 134 Record_13 140 Record_14 -141 Record_15 -142 Record_16 +150 Record_15 +160 Record_16 ## Changing datatype of column id with primary key to BigInt ## ALTER table t1 modify id BIGINT NOT NULL auto_increment; INSERT into t1(name) values('Record_17'); @@ -166,10 +166,10 @@ id name 125 Record_12 134 Record_13 140 Record_14 -141 Record_15 -142 Record_16 -143 Record_17 -144 Record_18 +150 Record_15 +160 Record_16 +170 Record_17 +180 Record_18 '#--------------------FN_DYNVARS_002_07-------------------------#' ## Assigning -ve value to variable ## SET @@auto_increment_offset = -10; @@ -196,12 +196,12 @@ id name 125 Record_12 134 Record_13 140 Record_14 -141 Record_15 -142 Record_16 -143 Record_17 -144 Record_18 -145 Record_17 -146 Record_18 +150 Record_15 +160 Record_16 +170 Record_17 +180 Record_18 +181 Record_17 +191 Record_18 ## Assigning value that is out of range of variable ## SET @@auto_increment_offset = 65536; Warnings: @@ -229,16 +229,16 @@ id name 125 Record_12 134 Record_13 140 Record_14 -141 Record_15 -142 Record_16 -143 Record_17 -144 Record_18 -145 Record_17 -146 Record_18 -147 Record_17 -148 Record_18 -149 Record_19 -150 Record_20 +150 Record_15 +160 Record_16 +170 Record_17 +180 Record_18 +181 Record_17 +191 Record_18 +199 Record_17 +209 Record_18 +219 Record_19 +229 Record_20 ## No effect of auto_increment_offset since value of this variable is greater ## ## than auto_increment_increment ## ## Dropping table ## From 3061aa4ead8345cac36c2decb54fe617d6837f2b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 1 May 2014 19:19:48 -0400 Subject: [PATCH 139/294] MDEV-6196 MTR: Do not hardcode path for libgalera_smm.so Introduced an environment variable WSREP_PROVIDER to point to the galera library. Updated the tests. --- mysql-test/mysql-test-run.pl | 16 ++++++++++++++++ mysql-test/suite/galera/galera_2nodes.cnf | 4 ++-- mysql-test/suite/wsrep/t/binlog_format.opt | 2 +- mysql-test/suite/wsrep/t/pool_of_threads.opt | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 695363d524a..6da4cedc910 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2393,6 +2393,22 @@ sub environment_setup { $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log; } + # ---------------------------------------------------- + # Setup env for wsrep + # ---------------------------------------------------- + if (defined $ENV{'WSREP_PROVIDER'} ) + { + # Nothing needs to be done! WSREP_PROVIDER env is already set and will be + # used. + } else { + my $file_wsrep_provider= + mtr_file_exists("/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + } + + mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); + # ---------------------------------------------------- # mysql clients # ---------------------------------------------------- diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index 1ef673e9582..21a45dec5f3 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -3,12 +3,12 @@ [mysqld.1] binlog-format=row -wsrep_provider=/usr/lib/galera/libgalera_smm.so +wsrep_provider=@ENV.WSREP_PROVIDER wsrep_cluster_address='gcomm://' [mysqld.2] binlog-format=row -wsrep_provider=/usr/lib/galera/libgalera_smm.so +wsrep_provider=@ENV.WSREP_PROVIDER wsrep_cluster_address='gcomm://127.0.0.1:4567' wsrep_provider_options='gmcast.listen_addr=tcp://127.0.0.1:4568' diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt index 771d9b05e1e..83194184e17 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.opt +++ b/mysql-test/suite/wsrep/t/binlog_format.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/galera/libgalera_smm.so --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.opt b/mysql-test/suite/wsrep/t/pool_of_threads.opt index 92994ddfb68..fb23fb50a67 100644 --- a/mysql-test/suite/wsrep/t/pool_of_threads.opt +++ b/mysql-test/suite/wsrep/t/pool_of_threads.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=/usr/lib/galera/libgalera_smm.so --wsrep-cluster-address=gcomm:// --thread_handling=pool-of-threads +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --thread_handling=pool-of-threads From 68a0f28defc772398312445d16e09570900fe27d Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 3 May 2014 09:18:11 -0400 Subject: [PATCH 140/294] MDEV-6204: wsrep_sst_rsync timeout when lsof is not installed * Added a check for lsof * Added rsync & lsof to debian dependency list. * Merged r3982 from codership-mysql/wsrep-5.5. --- debian/dist/Debian/control | 2 +- debian/dist/Ubuntu/control | 2 +- scripts/wsrep_sst_rsync.sh | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 9a6f4b9f881..70c789ebe9a 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: MariaDB Developers XSBC-Original-Maintainer: Maria Developers Uploaders: MariaDB Developers -Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev +Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync, lsof Standards-Version: 3.8.3 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 178771319a2..27127535195 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: MariaDB Developers XSBC-Original-Maintainer: Maria Developers Uploaders: MariaDB Developers -Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev +Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync, lsof Standards-Version: 3.8.2 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 960eef2df4b..a7878ae22a5 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -25,6 +25,9 @@ OS=$(uname) . $(dirname $0)/wsrep_sst_common +# Setting the path for lsof on CentOS +export PATH="/usr/sbin:/sbin:$PATH" + cleanup_joiner() { wsrep_log_info "Joiner cleanup." @@ -52,6 +55,11 @@ check_pid_and_port() local rsync_pid=$2 local rsync_port=$3 + if ! which lsof > /dev/null; then + wsrep_log_error "lsof tool not found in PATH! Make sure you have it installed." + exit 2 # ENOENT + fi + local port_info=$(lsof -i :$rsync_port -Pn 2>/dev/null | \ grep "(LISTEN)") local is_rsync=$(echo $port_info | \ From 5ef55e2c1bd28f284706631334b8c3b158b86731 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 3 May 2014 12:58:40 -0400 Subject: [PATCH 141/294] Added galera, wsrep suites to the default mtr suite list. --- mysql-test/mysql-test-run.pl | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6da4cedc910..a7d6e839183 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -186,6 +186,8 @@ my @DEFAULT_SUITES= qw( sys_vars- unit- vcol- + galera- + wsrep- ); my $opt_suites; @@ -415,6 +417,7 @@ sub main { check_ndbcluster_support(); check_ssl_support(); check_debug_support(); + check_wsrep_support(); mtr_report("Collecting tests..."); my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases, \@opt_skip_test_list); @@ -2396,19 +2399,19 @@ sub environment_setup { # ---------------------------------------------------- # Setup env for wsrep # ---------------------------------------------------- - if (defined $ENV{'WSREP_PROVIDER'} ) - { - # Nothing needs to be done! WSREP_PROVIDER env is already set and will be - # used. - } else { - my $file_wsrep_provider= - mtr_file_exists("/usr/lib/galera/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so"); - $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + if (have_wsrep()) { + if (defined $ENV{'WSREP_PROVIDER'} ) { + # Nothing needs to be done! WSREP_PROVIDER env is already set and will be + # used. + } else { + my $file_wsrep_provider= + mtr_file_exists("/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + } + mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); } - mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); - # ---------------------------------------------------- # mysql clients # ---------------------------------------------------- @@ -3172,6 +3175,17 @@ sub ndbcluster_start ($) { return 0; } +sub have_wsrep() { + my $wsrep_on= $mysqld_variables{'wsrep-on'}; + return defined $wsrep_on +} + +sub check_wsrep_support() { + if (have_wsrep()) + { + mtr_report(" - binaries built with wsrep patch"); + } +} sub mysql_server_start($) { my ($mysqld, $tinfo) = @_; From 93a403bf1d8819a711d783a186bf226a01a6fcfd Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 3 May 2014 23:53:19 -0400 Subject: [PATCH 142/294] Fix for build failure when WITH_WSREP=OFF. --- sql/rpl_record.cc | 2 ++ storage/xtradb/trx/trx0sys.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 9c80f812999..27223f36988 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -320,6 +320,7 @@ unpack_row(Relay_log_info const *rli, (int) (pack_ptr - old_pack_ptr))); if (!pack_ptr) { +#if WITH_WSREP /* Debug message to troubleshoot bug https://mariadb.atlassian.net/browse/MDEV-4404 @@ -331,6 +332,7 @@ unpack_row(Relay_log_info const *rli, (ulong) old_pack_ptr, conv_table, conv_field, (table_found) ? "found" : "not found", (ulong)row_end ); +#endif rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, "Could not read field '%s' of table '%s.%s'", diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index 0730907bbe1..7d9397b8e2c 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -868,9 +868,6 @@ trx_sys_update_mysql_binlog_offset( mtr_t* mtr) /*!< in: mtr */ { const char* file_name; -#ifndef WITH_WSREP - trx_sysf_t* sys_header; -#endif /* !WITH_WSREP */ if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) { From 00b6fff2e7bedad1ecd270d9e86f991bed29482c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 8 May 2014 14:45:00 -0400 Subject: [PATCH 143/294] MDEV#6206: wsrep_slave_threads subtracts from max_connections Decoupled wsrep thread count from connection count. By doing so, the number of wsrep threads (applier/rollbacker) would no longer affect the threads_connected status variable and thus maximum allowable user connections limit would be @@max_connections. Also introduced a new status variable 'wsrep_thread_count' to hold the number of wsrep applier/rollbacker threads. Added a test case. --- mysql-test/include/mtr_check.sql | 1 + mysql-test/suite/wsrep/r/variables.result | 65 +++++++++++++++++++++++ mysql-test/suite/wsrep/t/variables.test | 44 +++++++++++++++ sql/mysqld.cc | 21 +++++--- 4 files changed, 124 insertions(+), 7 deletions(-) diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index 7f990431762..a4cc3f2fc96 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -32,6 +32,7 @@ BEGIN AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' + AND variable_name != 'WSREP_DATA_HOME_DIR' ORDER BY variable_name; -- Dump all databases, there should be none diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index 01b5abe5661..ffa908ad359 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -11,4 +11,69 @@ SET SESSION wsrep_replicate_myisam= ON; ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable and should be set with SET GLOBAL SET GLOBAL wsrep_replicate_myisam= ON; SET GLOBAL wsrep_replicate_myisam= OFF; + +# +# MDEV#6206: wsrep_slave_threads subtracts from max_connections +# +call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); +call mtr.add_suppression("WSREP: Failed to get provider options"); +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address + +SHOW STATUS LIKE 'threads_connected'; +Variable_name Value +Threads_connected 1 +SHOW STATUS LIKE 'wsrep_thread_count'; +Variable_name Value +wsrep_thread_count 0 + +SET GLOBAL wsrep_provider= '/usr/lib/galera/libgalera_smm.so'; +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +/usr/lib/galera/libgalera_smm.so +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +NULL +SHOW STATUS LIKE 'threads_connected'; +Variable_name Value +Threads_connected 1 +SHOW STATUS LIKE 'wsrep_thread_count'; +Variable_name Value +wsrep_thread_count 0 + +# Setting wsrep_cluster_address triggers the creation of +# applier/rollbacker threads. +SET GLOBAL wsrep_cluster_address= 'gcomm://'; +# Wait for applier threads to get created. +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +/usr/lib/galera/libgalera_smm.so +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +gcomm:// +SHOW STATUS LIKE 'threads_connected'; +Variable_name Value +Threads_connected 1 +SHOW STATUS LIKE 'wsrep_thread_count'; +Variable_name Value +wsrep_thread_count 2 + +SET @wsrep_slave_threads_saved= @@global.wsrep_slave_threads; +SET GLOBAL wsrep_slave_threads= 10; +# Wait for applier threads to get created. +SHOW STATUS LIKE 'threads_connected'; +Variable_name Value +Threads_connected 1 +SHOW STATUS LIKE 'wsrep_thread_count'; +Variable_name Value +wsrep_thread_count 11 +SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_cluster_address= ''; +SET GLOBAL wsrep_provider= 'none'; # End of test. diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 306cdf9b2c9..a584d0b39f0 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -16,4 +16,48 @@ SET GLOBAL wsrep_replicate_myisam= ON; # Reset it back. SET GLOBAL wsrep_replicate_myisam= OFF; +--echo +--echo # +--echo # MDEV#6206: wsrep_slave_threads subtracts from max_connections +--echo # +call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); +call mtr.add_suppression("WSREP: Failed to get provider options"); +SELECT @@global.wsrep_provider; +SELECT @@global.wsrep_slave_threads; +SELECT @@global.wsrep_cluster_address; +SHOW STATUS LIKE 'threads_connected'; +SHOW STATUS LIKE 'wsrep_thread_count'; +--echo + +eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; +SELECT @@global.wsrep_provider; +SELECT @@global.wsrep_cluster_address; +SHOW STATUS LIKE 'threads_connected'; +SHOW STATUS LIKE 'wsrep_thread_count'; +--echo + +--echo # Setting wsrep_cluster_address triggers the creation of +--echo # applier/rollbacker threads. +SET GLOBAL wsrep_cluster_address= 'gcomm://'; +--echo # Wait for applier threads to get created. +sleep 3; +SELECT @@global.wsrep_provider; +SELECT @@global.wsrep_cluster_address; +SHOW STATUS LIKE 'threads_connected'; +SHOW STATUS LIKE 'wsrep_thread_count'; +--echo + +SET @wsrep_slave_threads_saved= @@global.wsrep_slave_threads; +SET GLOBAL wsrep_slave_threads= 10; +--echo # Wait for applier threads to get created. +sleep 3; +SHOW STATUS LIKE 'threads_connected'; +SHOW STATUS LIKE 'wsrep_thread_count'; + +# reset (for mtr internal checks) +SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_cluster_address= ''; +SET GLOBAL wsrep_provider= 'none'; + --echo # End of test. + diff --git a/sql/mysqld.cc b/sql/mysqld.cc index af1a5a2e81e..33e5e47bff1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2604,9 +2604,19 @@ void thd_cleanup(THD *thd) void dec_connection_count(THD *thd) { - mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; - mysql_mutex_unlock(&LOCK_connection_count); +#ifdef WITH_WSREP + /* + Do not decrement when its wsrep system thread. wsrep_applier is set for + applier as well as rollbacker threads. + */ + if (!thd->wsrep_applier) +#endif /* WITH_WSREP */ + { + DBUG_ASSERT(*thd->scheduler->connection_count > 0); + mysql_mutex_lock(&LOCK_connection_count); + (*thd->scheduler->connection_count)--; + mysql_mutex_unlock(&LOCK_connection_count); + } } @@ -4879,10 +4889,6 @@ pthread_handler_t start_wsrep_THD(void *arg) thd->set_time(); thd->init_for_queries(); - mysql_mutex_lock(&LOCK_connection_count); - ++connection_count; - mysql_mutex_unlock(&LOCK_connection_count); - mysql_mutex_lock(&LOCK_thread_count); wsrep_running_threads++; mysql_cond_broadcast(&COND_thread_count); @@ -7938,6 +7944,7 @@ SHOW_VAR status_vars[]= { {"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_thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH}, {"wsrep", (char*) &wsrep_show_status, SHOW_FUNC}, #endif {NullS, NullS, SHOW_LONG} From 50d1e45cd49f39231ea9cc87f7c4a17f1617fc2f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 12 May 2014 12:45:02 -0400 Subject: [PATCH 144/294] MDEV#5925: New mariadb-galera-test packages Added logic for generation of 'galera' test packages. --- cmake/cpack_rpm.cmake | 5 +- debian/dist/Debian/control | 27 +++++-- debian/dist/Ubuntu/control | 27 +++++-- debian/mariadb-galera-test-5.5.dirs | 101 +++++++++++++++++++++++++++ debian/mariadb-galera-test-5.5.files | 15 ++++ debian/mariadb-galera-test-5.5.links | 2 + 6 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 debian/mariadb-galera-test-5.5.dirs create mode 100644 debian/mariadb-galera-test-5.5.files create mode 100644 debian/mariadb-galera-test-5.5.links diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 1d373106d8d..9738de452b1 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -23,8 +23,7 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared") SET(CPACK_COMPONENT_COMMON_GROUP "common") SET(CPACK_COMPONENT_COMPAT_GROUP "compat") SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts - SupportFiles Readme) - + SupportFiles Readme Test) SET(CPACK_RPM_PACKAGE_NAME "MariaDB-Galera") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") @@ -147,6 +146,8 @@ SETA(CPACK_RPM_test_PACKAGE_OBSOLETES "MySQL-OurDelta-test") SETA(CPACK_RPM_test_PACKAGE_PROVIDES "MySQL-test") +SET(CPACK_RPM_test_PACKAGE_CONFLICTS + "MariaDB-test") SETA(CPACK_RPM_server_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 70c789ebe9a..47656f24bdf 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -10,9 +10,28 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria +Package: mariadb-galera-test-5.5 +Section: database +Architecture: any +Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (>= ${source:Version}) +Suggests: patch +Conflicts: mariadb-test, mariadb-galera-test (<< ${source:Version}), + mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, + mariadb-test-5.5, + mariadb-server-5.5, mariadb-galera-server-5.5 (<< 5.5.33) +Replaces: mariadb-test (<< ${source:Version}), mariadb-galera-test (<< ${source:Version}), + mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 +Description: MariaDB database regression test suite + MariaDB is a fast, stable and true multi-user, multi-threaded SQL database + server. SQL (Structured Query Language) is the most popular database query + language in the world. The main goals of MariaDB are speed, robustness and + ease of use. + . + This package includes the regression test suite. + Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-test +Suggests: tinyca, mailx, mariadb-galera-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) @@ -64,11 +83,11 @@ Description: MariaDB database client (metapackage depending on the latest versio maintainers. Install this package if in doubt about which MariaDB version you want, as this is the one we consider to be in the best shape. -Package: mariadb-test +Package: mariadb-galera-test Section: database Architecture: all -Depends: mariadb-test-5.5 (= ${source:Version}) +Depends: mariadb-galera-test-5.5 (= ${source:Version}) Description: MariaDB database regression test suite (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB + mariadb-galera-test (currently mariadb-galera-test-5.5), as determined by the MariaDB maintainers. diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 27127535195..15a99a4a827 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -10,9 +10,28 @@ Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria +Package: mariadb-galera-test-5.5 +Section: database +Architecture: any +Depends: mariadb-galera-server-5.5 (= ${source:Version}), mariadb-client-5.5 (>= ${source:Version}) +Suggests: patch +Conflicts: mariadb-test, mariadb-galera-test (<< ${source:Version}), + mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3, + mariadb-test-5.5, + mariadb-server-5.5, mariadb-galera-server-5.5 (<< 5.5.33) +Replaces: mariadb-test (<< ${source:Version}), mariadb-galera-test (<< ${source:Version}), + mariadb-test-5.1, mariadb-test-5.2, mariadb-test-5.3 +Description: MariaDB database regression test suite + MariaDB is a fast, stable and true multi-user, multi-threaded SQL database + server. SQL (Structured Query Language) is the most popular database query + language in the world. The main goals of MariaDB are speed, robustness and + ease of use. + . + This package includes the regression test suite. + Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-test +Suggests: tinyca, mailx, mariadb-galera-test Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) @@ -64,11 +83,11 @@ Description: MariaDB database client (metapackage depending on the latest versio maintainers. Install this package if in doubt about which MariaDB version you want, as this is the one we consider to be in the best shape. -Package: mariadb-test +Package: mariadb-galera-test Section: database Architecture: all -Depends: mariadb-test-5.5 (= ${source:Version}) +Depends: mariadb-galera-test-5.5 (= ${source:Version}) Description: MariaDB database regression test suite (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-test (currently mariadb-test-5.5), as determined by the MariaDB + mariadb-galera-test (currently mariadb-galera-test-5.5), as determined by the MariaDB maintainers. diff --git a/debian/mariadb-galera-test-5.5.dirs b/debian/mariadb-galera-test-5.5.dirs new file mode 100644 index 00000000000..4e75b80c8b3 --- /dev/null +++ b/debian/mariadb-galera-test-5.5.dirs @@ -0,0 +1,101 @@ +usr/bin +usr/share/man/man1 +usr/share/mysql/mysql-test +usr/share/mysql/mysql-test/extra +usr/share/mysql/mysql-test/extra/binlog_tests +usr/share/mysql/mysql-test/extra/rpl_tests +usr/share/mysql/mysql-test/lib +usr/share/mysql/mysql-test/lib/My +usr/share/mysql/mysql-test/lib/My/SafeProcess +usr/share/mysql/mysql-test/lib/My/File +usr/share/mysql/mysql-test/lib/v1 +usr/share/mysql/mysql-test/lib/v1/My +usr/share/mysql/mysql-test/collections +usr/share/mysql/mysql-test/t +usr/share/mysql/mysql-test/r +usr/share/mysql/mysql-test/include +usr/share/mysql/mysql-test/suite +usr/share/mysql/mysql-test/suite/parts +usr/share/mysql/mysql-test/suite/parts/inc +usr/share/mysql/mysql-test/suite/parts/t +usr/share/mysql/mysql-test/suite/parts/r +usr/share/mysql/mysql-test/suite/rpl_ndb +usr/share/mysql/mysql-test/suite/rpl_ndb/t +usr/share/mysql/mysql-test/suite/rpl_ndb/r +usr/share/mysql/mysql-test/suite/bugs +usr/share/mysql/mysql-test/suite/bugs/t +usr/share/mysql/mysql-test/suite/bugs/r +usr/share/mysql/mysql-test/suite/bugs/data +usr/share/mysql/mysql-test/suite/rpl +usr/share/mysql/mysql-test/suite/rpl/t +usr/share/mysql/mysql-test/suite/rpl/r +usr/share/mysql/mysql-test/suite/rpl/include +usr/share/mysql/mysql-test/suite/innodb +usr/share/mysql/mysql-test/suite/innodb/t +usr/share/mysql/mysql-test/suite/innodb/r +usr/share/mysql/mysql-test/suite/innodb/include +usr/share/mysql/mysql-test/suite/manual +usr/share/mysql/mysql-test/suite/manual/t +usr/share/mysql/mysql-test/suite/manual/r +usr/share/mysql/mysql-test/suite/stress +usr/share/mysql/mysql-test/suite/stress/t +usr/share/mysql/mysql-test/suite/stress/r +usr/share/mysql/mysql-test/suite/stress/include +usr/share/mysql/mysql-test/suite/jp +usr/share/mysql/mysql-test/suite/jp/t +usr/share/mysql/mysql-test/suite/jp/r +usr/share/mysql/mysql-test/suite/jp/include +usr/share/mysql/mysql-test/suite/jp/std_data +usr/share/mysql/mysql-test/suite/ndb +usr/share/mysql/mysql-test/suite/ndb/t +usr/share/mysql/mysql-test/suite/ndb/r +usr/share/mysql/mysql-test/suite/maria +usr/share/mysql/mysql-test/suite/maria/t +usr/share/mysql/mysql-test/suite/maria/r +usr/share/mysql/mysql-test/suite/funcs_2 +usr/share/mysql/mysql-test/suite/funcs_2/lib +usr/share/mysql/mysql-test/suite/funcs_2/t +usr/share/mysql/mysql-test/suite/funcs_2/charset +usr/share/mysql/mysql-test/suite/funcs_2/r +usr/share/mysql/mysql-test/suite/funcs_2/include +usr/share/mysql/mysql-test/suite/funcs_2/data +usr/share/mysql/mysql-test/suite/binlog +usr/share/mysql/mysql-test/suite/binlog/t +usr/share/mysql/mysql-test/suite/binlog/r +usr/share/mysql/mysql-test/suite/binlog/std_data +usr/share/mysql/mysql-test/suite/ndb_team +usr/share/mysql/mysql-test/suite/ndb_team/t +usr/share/mysql/mysql-test/suite/ndb_team/r +usr/share/mysql/mysql-test/suite/federated +usr/share/mysql/mysql-test/suite/funcs_1 +usr/share/mysql/mysql-test/suite/funcs_1/cursors +usr/share/mysql/mysql-test/suite/funcs_1/bitdata +usr/share/mysql/mysql-test/suite/funcs_1/views +usr/share/mysql/mysql-test/suite/funcs_1/storedproc +usr/share/mysql/mysql-test/suite/funcs_1/triggers +usr/share/mysql/mysql-test/suite/funcs_1/lib +usr/share/mysql/mysql-test/suite/funcs_1/t +usr/share/mysql/mysql-test/suite/funcs_1/r +usr/share/mysql/mysql-test/suite/funcs_1/include +usr/share/mysql/mysql-test/suite/funcs_1/datadict +usr/share/mysql/mysql-test/suite/vcol +usr/share/mysql/mysql-test/suite/vcol/inc +usr/share/mysql/mysql-test/suite/vcol/t +usr/share/mysql/mysql-test/suite/vcol/r +usr/share/mysql/mysql-test/suite/oqgraph +usr/share/mysql/mysql-test/suite/oqgraph/t +usr/share/mysql/mysql-test/suite/oqgraph/r +usr/share/mysql/mysql-test/suite/oqgraph/include +usr/share/mysql/mysql-test/suite/wsrep +usr/share/mysql/mysql-test/suite/wsrep/t +usr/share/mysql/mysql-test/suite/wsrep/r +usr/share/mysql/mysql-test/suite/galera +usr/share/mysql/mysql-test/suite/galera/t +usr/share/mysql/mysql-test/suite/galera/r +usr/share/mysql/mysql-test/std_data +usr/share/mysql/mysql-test/std_data/ndb_backup50 +usr/share/mysql/mysql-test/std_data/parts +usr/share/mysql/mysql-test/std_data/ndb_backup51_data_le +usr/share/mysql/mysql-test/std_data/ndb_backup51_data_be +usr/share/mysql/mysql-test/std_data/ndb_backup51 +usr/share/mysql/mysql-test/std_data/funcs_1 diff --git a/debian/mariadb-galera-test-5.5.files b/debian/mariadb-galera-test-5.5.files new file mode 100644 index 00000000000..79eb9520607 --- /dev/null +++ b/debian/mariadb-galera-test-5.5.files @@ -0,0 +1,15 @@ +usr/lib/mysql/plugin/dialog_examples.so +usr/lib/mysql/plugin/auth_test_plugin.so +usr/lib/mysql/plugin/qa_auth_interface.so +usr/lib/mysql/plugin/qa_auth_server.so +usr/lib/mysql/plugin/qa_auth_client.so +usr/lib/mysql/plugin/auth_0x0100.so +usr/lib/mysql/plugin/mypluglib.so +usr/lib/mysql/plugin/daemon_example.ini +usr/lib/mysql/plugin/libdaemon_example.so +usr/lib/mysql/plugin/adt_null.so +usr/bin/mysql_client_test +usr/share/man/man1/mysql_client_test.1 +usr/bin/mysqltest +usr/share/man/man1/mysqltest.1 +usr/share/mysql/mysql-test diff --git a/debian/mariadb-galera-test-5.5.links b/debian/mariadb-galera-test-5.5.links new file mode 100644 index 00000000000..082680fe5ed --- /dev/null +++ b/debian/mariadb-galera-test-5.5.links @@ -0,0 +1,2 @@ +usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mysql-test-run +usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mtr From 0f10b12b1c819e0653970ee8990d663cd9246179 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 25 May 2014 00:07:25 -0400 Subject: [PATCH 145/294] MDEV#6211: MariaDB-Galera-server uses 'socat', but 'socat' is not in the dependency list Added socat, grep, gawk, iproute, coreutils, findutils to the dependency list. --- cmake/cpack_rpm.cmake | 7 ++----- debian/dist/Debian/control | 16 ++++++++++++---- debian/dist/Ubuntu/control | 14 +++++++++++--- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 9738de452b1..11f681d8e6e 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -126,7 +126,8 @@ SETA(CPACK_RPM_server_PACKAGE_PROVIDES "mysql-server") SETA(CPACK_RPM_server_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" - "galera") + "MariaDB-client" "galera" "lsof" "socat" "grep" "gawk" "iproute" "coreutils" + "findutils") SETA(CPACK_RPM_shared_PACKAGE_OBSOLETES "mysql-shared" @@ -149,10 +150,6 @@ SETA(CPACK_RPM_test_PACKAGE_PROVIDES SET(CPACK_RPM_test_PACKAGE_CONFLICTS "MariaDB-test") -SETA(CPACK_RPM_server_PACKAGE_REQUIRES - ${CPACK_RPM_PACKAGE_REQUIRES} - "MariaDB-client") - SET(CPACK_RPM_server_PRE_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-prein.sh) SET(CPACK_RPM_server_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-preun.sh) SET(CPACK_RPM_server_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-postin.sh) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 47656f24bdf..14f497e6e86 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -4,8 +4,13 @@ Priority: optional Maintainer: MariaDB Developers XSBC-Original-Maintainer: Maria Developers Uploaders: MariaDB Developers -Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync, lsof -Standards-Version: 3.8.3 +Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), + libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), + zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, + libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, + texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, + hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync +Standards-Version: 3.8.2 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria @@ -31,10 +36,13 @@ Description: MariaDB database regression test suite Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-galera-test +Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), + ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), + libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + lsof, socat, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 15a99a4a827..14f497e6e86 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -4,7 +4,12 @@ Priority: optional Maintainer: MariaDB Developers XSBC-Original-Maintainer: Maria Developers Uploaders: MariaDB Developers -Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync, lsof +Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), + libncurses5-dev (>= 5.0-6), perl (>= 5.6.0), libwrap0-dev (>= 7.6-8.3), + zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, + libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, + texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, + hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync Standards-Version: 3.8.2 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files @@ -31,10 +36,13 @@ Description: MariaDB database regression test suite Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-galera-test +Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf -Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2) +Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), + ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), + libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + lsof, socat, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, From 86e73576dd2ccf7385ac0b5b7b3bbf6d656e71f4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 25 May 2014 00:23:17 -0400 Subject: [PATCH 146/294] Setting the "Standards-Version" in Debian control file back to 3.8.3. --- debian/dist/Debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 14f497e6e86..b539dde1579 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -10,7 +10,7 @@ Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync -Standards-Version: 3.8.2 +Standards-Version: 3.8.3 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files Vcs-Bzr: bzr://lp:maria From 7487f6b397c97bc27cbb6315746006f3df0e291d Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 May 2014 09:07:19 -0400 Subject: [PATCH 147/294] Removing rsync from the debian build dependency list. --- debian/dist/Debian/control | 2 +- debian/dist/Ubuntu/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index b539dde1579..05788d01a8e 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -9,7 +9,7 @@ Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, - hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync + hardening-wrapper, ${CMAKE_DEP}libaio-dev Standards-Version: 3.8.3 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 14f497e6e86..c26cccbd17e 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -9,7 +9,7 @@ Build-Depends: libtool (>= 1.4.2-7), procps | hurd, debhelper, file (>= 3.28), zlib1g-dev (>= 1:1.1.3-5), ${LIBREADLINE_DEV}, libevent-dev, libssl-dev, libpam0g-dev, psmisc, po-debconf, chrpath, automake1.9, doxygen, texlive-latex-base, ghostscript | gs-gpl, dpatch, gawk, bison, lsb-release, - hardening-wrapper, ${CMAKE_DEP}libaio-dev, rsync + hardening-wrapper, ${CMAKE_DEP}libaio-dev Standards-Version: 3.8.2 Homepage: http://mariadb.org/ Vcs-Browser: http://bazaar.launchpad.net/~maria-captains/maria/5.5/files From c73cd2a5959198348cc73730fbbe846f85c60c1b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 May 2014 11:04:42 -0400 Subject: [PATCH 148/294] s/#if/#ifdef --- sql/rpl_record.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 27223f36988..b3b3e836638 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -307,11 +307,11 @@ unpack_row(Relay_log_info const *rli, uint16 const metadata= tabledef->field_metadata(i); #ifndef DBUG_OFF uchar const *const old_pack_ptr= pack_ptr; -#else -#if WITH_WSREP +#else +#ifdef WITH_WSREP uchar const *const old_pack_ptr= pack_ptr; -#endif -#endif +#endif /* WITH_WSREP */ +#endif /* !DBUG_OFF */ pack_ptr= f->unpack(f->ptr, pack_ptr, row_end, metadata); DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;" " pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d", @@ -320,7 +320,7 @@ unpack_row(Relay_log_info const *rli, (int) (pack_ptr - old_pack_ptr))); if (!pack_ptr) { -#if WITH_WSREP +#ifdef WITH_WSREP /* Debug message to troubleshoot bug https://mariadb.atlassian.net/browse/MDEV-4404 @@ -332,7 +332,7 @@ unpack_row(Relay_log_info const *rli, (ulong) old_pack_ptr, conv_table, conv_field, (table_found) ? "found" : "not found", (ulong)row_end ); -#endif +#endif /* WITH_WSREP */ rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, "Could not read field '%s' of table '%s.%s'", From 26fa9e8294db1d922dea2e5aa25f548b210d6378 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 29 May 2014 21:03:10 -0400 Subject: [PATCH 149/294] Added rsync to galera server's debian/rpm dependency list. --- cmake/cpack_rpm.cmake | 4 ++-- debian/dist/Debian/control | 2 +- debian/dist/Ubuntu/control | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 11f681d8e6e..8ee87840798 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -126,8 +126,8 @@ SETA(CPACK_RPM_server_PACKAGE_PROVIDES "mysql-server") SETA(CPACK_RPM_server_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" - "MariaDB-client" "galera" "lsof" "socat" "grep" "gawk" "iproute" "coreutils" - "findutils") + "MariaDB-client" "galera" "rsync" "lsof" "socat" "grep" "gawk" "iproute" + "coreutils" "findutils") SETA(CPACK_RPM_shared_PACKAGE_OBSOLETES "mysql-shared" diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 05788d01a8e..e82da9ed4ca 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -42,7 +42,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), - lsof, socat, grep, gawk, iproute, coreutils, findutils + rsync, lsof, socat, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index c26cccbd17e..e461ea4d8e5 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -42,7 +42,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), - lsof, socat, grep, gawk, iproute, coreutils, findutils + rsync, lsof, socat, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, From 1ebc055f1bf7308de96aa81eba71b58d0af42a4b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 5 Jun 2014 23:40:32 -0400 Subject: [PATCH 150/294] Modified mtr script to skip inclusion of 'galera' test suites if galera library is not specified or found. --- mysql-test/mysql-test-run.pl | 42 ++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a7d6e839183..12af2efdaad 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -135,6 +135,7 @@ my $opt_start; my $opt_start_dirty; my $opt_start_exit; my $start_only; +my $file_wsrep_provider; END { if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) @@ -186,8 +187,6 @@ my @DEFAULT_SUITES= qw( sys_vars- unit- vcol- - galera- - wsrep- ); my $opt_suites; @@ -2401,17 +2400,19 @@ sub environment_setup { # ---------------------------------------------------- if (have_wsrep()) { if (defined $ENV{'WSREP_PROVIDER'} ) { - # Nothing needs to be done! WSREP_PROVIDER env is already set and will be - # used. + # Nothing needs to be done! WSREP_PROVIDER env is already set & checked; + # will be used. } else { - my $file_wsrep_provider= - mtr_file_exists("/usr/lib/galera/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so"); $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; } - mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); + + if ($ENV{'WSREP_PROVIDER'} ne "") { + mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); + } else { + mtr_verbose("WSREP_PROVIDER isn't available"); + } } - + # ---------------------------------------------------- # mysql clients # ---------------------------------------------------- @@ -3180,10 +3181,33 @@ sub have_wsrep() { return defined $wsrep_on } +sub check_wsrep_provider_env { + if (defined $ENV{'WSREP_PROVIDER'}) { + if (mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") { + mtr_error("WSREP_PROVIDER env set to an invalid path"); + return 0; # error + } + # Ok, WSREP_PROVIDER set to a valid path. + return 1; + } + # Ok, WSREP_PROVIDER not defined. + return 2; +} + sub check_wsrep_support() { if (have_wsrep()) { mtr_report(" - binaries built with wsrep patch"); + + $file_wsrep_provider= + mtr_file_exists("/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"); + + if ((check_wsrep_provider_env() == 1) || ($file_wsrep_provider ne "")) { + # Add galera test suites + mtr_report(" - adding wsrep, galera to default test suites"); + push @DEFAULT_SUITES, qw(wsrep galera); + } } } From d3b2e780d6ddee9a4f434ba9928f77127bbbeeb1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 6 Jun 2014 13:49:10 -0400 Subject: [PATCH 151/294] Updated default load option groups. --- scripts/wsrep_sst_rsync.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index a7878ae22a5..bd8f03846e9 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -23,11 +23,11 @@ RSYNC_CONF= OS=$(uname) [ "$OS" == "Darwin" ] && export -n LD_LIBRARY_PATH -. $(dirname $0)/wsrep_sst_common - # Setting the path for lsof on CentOS export PATH="/usr/sbin:/sbin:$PATH" +. $(dirname $0)/wsrep_sst_common + cleanup_joiner() { wsrep_log_info "Joiner cleanup." @@ -83,7 +83,7 @@ WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} if [ -z "$WSREP_LOG_DIR" ]; then SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)" WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \ - "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 \ + "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 mariadb mariadb-5.5 \ | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ | cut -b 29- ) fi From 90ead99572c8168583cb0943792d964cc2a6abd2 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Jun 2014 16:33:57 -0400 Subject: [PATCH 152/294] bzr merge -r3980..3984 codership/5.5 --- scripts/wsrep_sst_common.sh | 10 +++++----- scripts/wsrep_sst_mysqldump.sh | 13 +++++++++---- sql/wsrep_sst.cc | 9 +++++---- storage/innobase/row/row0ins.c | 8 ++++---- storage/xtradb/row/row0ins.c | 8 ++++---- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index f9a08c1c695..b6c10ba4e7d 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -20,6 +20,7 @@ set -u WSREP_SST_OPT_BYPASS=0 WSREP_SST_OPT_DATA="" +WSREP_SST_OPT_AUTH="" while [ $# -gt 0 ]; do case "$1" in @@ -55,7 +56,7 @@ case "$1" in shift ;; '--password') - readonly WSREP_SST_OPT_PSWD="$2" + WSREP_SST_OPT_PSWD="$2" shift ;; '--port') @@ -71,7 +72,7 @@ case "$1" in shift ;; '--user') - readonly WSREP_SST_OPT_USER="$2" + WSREP_SST_OPT_USER="$2" shift ;; '--gtid') @@ -88,8 +89,8 @@ done readonly WSREP_SST_OPT_BYPASS # For Bug:1200727 -if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then - if [ -z $WSREP_SST_OPT_AUTH -o $WSREP_SST_OPT_AUTH = "(null)" ];then +if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then + if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) fi fi @@ -124,4 +125,3 @@ wsrep_cleanup_progress_file() { [ -n "$SST_PROGRESS_FILE" ] && rm -f "$SST_PROGRESS_FILE" 2>/dev/null } - diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index cf4f55df98e..3db1d73bb9c 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -1,15 +1,15 @@ -#!/bin/sh -e +#!/bin/bash -e # Copyright (C) 2009 Codership Oy -# +# # 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; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston @@ -61,6 +61,11 @@ then exit $EINVAL fi +# For Bug:1293798 +if [ -z "$WSREP_SST_OPT_PSWD" -a -n "$WSREP_SST_OPT_AUTH" ]; then + WSREP_SST_OPT_USER=$(echo $WSREP_SST_OPT_AUTH | cut -d: -f1) + WSREP_SST_OPT_PSWD=$(echo $WSREP_SST_OPT_AUTH | cut -d: -f2) +fi AUTH="-u$WSREP_SST_OPT_USER" if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 37c55707b28..1b57b63131c 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -110,7 +110,7 @@ bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) return 0; } -bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, +bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, enum_var_type type) { return 0; @@ -135,7 +135,7 @@ static bool sst_auth_real_set (const char* value) { my_free ((void*)wsrep_sst_auth); wsrep_sst_auth = my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); - //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, + //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, // sizeof(wsrep_sst_auth) - 1); } else @@ -717,10 +717,11 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " WSREP_SST_OPT_GTID" '%s:%lld'" "%s", user, pswd, host, port, mysqld_port, mysqld_unix_port, - mysql_real_data_home, uuid_str, + mysql_real_data_home, wsrep_defaults_file, uuid_str, (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); WSREP_DEBUG("Running: '%s'", cmd_str); @@ -754,7 +755,7 @@ static int run_sql_command(THD *thd, const char *query) int const err= thd->stmt_da->sql_errno(); WSREP_WARN ("error executing '%s': %d (%s)%s", query, err, thd->stmt_da->message(), - err == ER_UNKNOWN_SYSTEM_VARIABLE ? + err == ER_UNKNOWN_SYSTEM_VARIABLE ? ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); thd->clear_error(); return -1; diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index c6525ebcc93..3419297f059 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1696,6 +1696,10 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) return(DB_SUCCESS); +#endif /* WITH_WSREP */ rec_offs_init(offsets_); n_unique = dict_index_get_n_unique(index); @@ -1760,10 +1764,6 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { -#ifdef WITH_WSREP - /* appliers don't need dupkey checks */ - if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) -#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 36cbed9eea5..a1ee411b8cd 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1705,6 +1705,10 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) return(DB_SUCCESS); +#endif /* WITH_WSREP */ rec_offs_init(offsets_); n_unique = dict_index_get_n_unique(index); @@ -1769,10 +1773,6 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { -#ifdef WITH_WSREP - /* appliers don't need dupkey checks */ - if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) -#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } From c29cbac2eb06ab4a2bf1aeda65c15fce40a84345 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Jun 2014 17:00:32 -0400 Subject: [PATCH 153/294] bzr merge -r3985..3997 codership/5.5 --- .bzrignore | 1 + cmake/wsrep.cmake | 2 +- scripts/wsrep_sst_common.sh | 26 ++++++++++- scripts/wsrep_sst_rsync.sh | 6 ++- scripts/wsrep_sst_xtrabackup-v2.sh | 70 +++++++++++++++++++++++------- scripts/wsrep_sst_xtrabackup.sh | 2 +- sql/event_data_objects.cc | 13 ++++++ sql/events.cc | 41 +++++++++++++++++ sql/mysqld.cc | 3 +- sql/sql_yacc.yy | 12 +++-- sql/wsrep_mysqld.cc | 18 +++++++- sql/wsrep_mysqld.h | 1 + sql/wsrep_thd.cc | 15 +++++-- storage/innobase/lock/lock0lock.c | 10 +++++ storage/innobase/row/row0ins.c | 11 +++-- storage/xtradb/lock/lock0lock.c | 10 +++++ storage/xtradb/row/row0ins.c | 11 +++-- support-files/mysql.spec.sh | 2 +- wsrep/wsrep_dummy.c | 21 ++++++++- 19 files changed, 236 insertions(+), 39 deletions(-) diff --git a/.bzrignore b/.bzrignore index 125c1bf7d34..0c300408180 100644 --- a/.bzrignore +++ b/.bzrignore @@ -12,6 +12,7 @@ *.dll *.dsp *.dylib +*.diff *.exe *.exp *.gcda diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 628cfd1b092..dde6c0b4d2d 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "10") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "3980") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "3997") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index b6c10ba4e7d..d9aa24169ce 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1,4 +1,4 @@ -# Copyright (C) 2012 Codership Oy +# Copyright (C) 2012-2014 Codership Oy # # 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 @@ -125,3 +125,27 @@ wsrep_cleanup_progress_file() { [ -n "$SST_PROGRESS_FILE" ] && rm -f "$SST_PROGRESS_FILE" 2>/dev/null } + +wsrep_check_program() +{ + local prog=$1 + + if ! which $prog >/dev/null + then + echo "'$prog' not found in PATH" + return 2 # no such file or directory + fi +} + +wsrep_check_programs() +{ + local ret=0 + + while [ $# -gt 0 ] + do + wsrep_check_program $1 || ret=$? + shift + done + + return $ret +} diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index bd8f03846e9..464b2b1ef3e 100755 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -1,6 +1,6 @@ #!/bin/bash -ue -# Copyright (C) 2010 Codership Oy +# Copyright (C) 2010-2014 Codership Oy # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,6 +28,8 @@ export PATH="/usr/sbin:/sbin:$PATH" . $(dirname $0)/wsrep_sst_common +wsrep_check_programs rsync + cleanup_joiner() { wsrep_log_info "Joiner cleanup." @@ -202,6 +204,8 @@ then elif [ "$WSREP_SST_OPT_ROLE" = "joiner" ] then + wsrep_check_programs lsof + touch $SST_PROGRESS_FILE MYSQLD_PID=$WSREP_SST_OPT_PARENT diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 59017fff8df..865547ad9d8 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -63,6 +63,10 @@ STATDIR="" uextra=0 disver="" +tmpopts="" +itmpdir="" +xtmpdir="" + scomp="" sdecomp="" @@ -236,7 +240,7 @@ parse_cnf() get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | xargs -0 du --block-size=1 -c | awk 'END { print $1 }') if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. @@ -299,6 +303,7 @@ read_cnf() iopts=$(parse_cnf sst inno-backup-opts "") iapts=$(parse_cnf sst inno-apply-opts "") impts=$(parse_cnf sst inno-move-opts "") + stimeout=$(parse_cnf sst sst-initial-timeout 100) } get_stream() @@ -370,20 +375,29 @@ cleanup_donor() wsrep_log_error "Cleanup after exit with status:$estatus" fi - if [[ -n $XTRABACKUP_PID ]];then + if [[ -n ${XTRABACKUP_PID:-} ]];then if check_pid $XTRABACKUP_PID then wsrep_log_error "xtrabackup process is still running. Killing... " kill_xtrabackup fi - rm -f $XTRABACKUP_PID fi - rm -f ${DATA}/${IST_FILE} + rm -f ${DATA}/${IST_FILE} || true if [[ -n $progress && -p $progress ]];then wsrep_log_info "Cleaning up fifo file $progress" - rm $progress + rm -f $progress || true + fi + + wsrep_log_info "Cleaning up temporary directories" + + if [[ -n $xtmpdir ]];then + [[ -d $xtmpdir ]] && rm -rf $xtmpdir || true + fi + + if [[ -n $itmpdir ]];then + [[ -d $itmpdir ]] && rm -rf $itmpdir || true fi } @@ -391,7 +405,8 @@ kill_xtrabackup() { local PID=$(cat $XTRABACKUP_PID) [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$XTRABACKUP_PID" + wsrep_log_info "Removing xtrabackup pid file $XTRABACKUP_PID" + rm -f "$XTRABACKUP_PID" || true } setup_ports() @@ -453,13 +468,30 @@ recv_joiner() { local dir=$1 local msg=$2 + local tmt=$3 + local ltcmd pushd ${dir} 1>/dev/null set +e - timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + + if [[ $tmt -gt 0 && -x `which timeout` ]];then + if timeout --help | grep -q -- '-k';then + ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" + else + ltcmd="timeout $tmt $tcmd" + fi + timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + else + timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + fi + set -e popd 1>/dev/null + if [[ ${RC[0]} -eq 124 ]];then + wsrep_log_error "Possible timeout in receving first data from donor in gtid stage" + exit 32 + fi for ecode in "${RC[@]}";do if [[ $ecode -ne 0 ]];then @@ -501,7 +533,7 @@ send_donor() } -if [[ ! -x `which innobackupex` ]];then +if [[ ! -x `which $INNOBACKUPEX_BIN` ]];then wsrep_log_error "innobackupex not in path: $PATH" exit 2 fi @@ -526,7 +558,7 @@ fi INNOEXTRA="" INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" -INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" +INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then @@ -535,7 +567,14 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then - TMPDIR="${TMPDIR:-/tmp}" + if [[ -z $(parse_cnf mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then + xtmpdir=$(mktemp -d) + tmpopts=" --tmpdir=$xtmpdir " + wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" + fi + + itmpdir=$(mktemp -d) + wsrep_log_info "Using $itmpdir as innobackupex temporary directory" if [ "${AUTH[0]}" != "(null)" ]; then INNOEXTRA+=" --user=${AUTH[0]}" @@ -613,8 +652,8 @@ then exit 22 fi - # innobackupex implicitly writes PID to fixed location in ${TMPDIR} - XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" + # innobackupex implicitly writes PID to fixed location in $xtmpdir + XTRABACKUP_PID="$xtmpdir/xtrabackup_pid" else # BYPASS FOR IST @@ -717,7 +756,7 @@ then STATDIR=$(mktemp -d) MAGIC_FILE="${STATDIR}/${INFO_FILE}" - recv_joiner $STATDIR "${stagemsg}-gtid" 1 + recv_joiner $STATDIR "${stagemsg}-gtid" $stimeout if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null then @@ -767,7 +806,7 @@ then MAGIC_FILE="${DATA}/${INFO_FILE}" - recv_joiner $DATA "${stagemsg}-SST" 0 + recv_joiner $DATA "${stagemsg}-SST" 0 get_proc @@ -867,11 +906,10 @@ then wsrep_log_info "${IST_FILE} received from donor: Running IST" fi - if [[ ! -r ${MAGIC_FILE} ]];then + if [[ ! -r ${MAGIC_FILE} ]];then wsrep_log_error "SST magic file ${MAGIC_FILE} not found/readable" exit 2 fi - cat "${MAGIC_FILE}" # output UUID:seqno wsrep_log_info "Total time on joiner: $totime seconds" fi diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 01c9c3f3049..6b33eabee23 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -205,7 +205,7 @@ parse_cnf() get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(du --block-size=1 -c **/*.ibd **/*.MYI **/*.MYI ibdata1 | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | xargs -0 du --block-size=1 -c | awk 'END { print $1 }') if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index dfd35583581..dbf35bd94b7 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1467,8 +1467,21 @@ end: saved_master_access= thd->security_ctx->master_access; thd->security_ctx->master_access |= SUPER_ACL; +#ifdef WITH_WSREP + // sql_print_information("sizeof(LEX) = %d", sizeof(struct LEX)); + // sizeof(LEX) = 4512, so it's relatively safe to allocate it on stack. + LEX lex; + lex.sql_command = SQLCOM_DROP_EVENT; + thd->lex = &lex; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); +#endif + ret= Events::drop_event(thd, dbname, name, FALSE); +#ifdef WITH_WSREP + WSREP_TO_ISOLATION_END; + error: +#endif thd->security_ctx->master_access= saved_master_access; } } diff --git a/sql/events.cc b/sql/events.cc index e016ccd2b84..9e15a5f47bd 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1104,6 +1104,20 @@ Events::load_events_from_db(THD *thd) delete et; goto end; } +#ifdef WITH_WSREP + // when SST from master node who initials event, the event status is ENABLED + // this is problematic because there are two nodes with same events and both enabled. + if (et->originator != thd->server_id) + { + store_record(table, record[1]); + table->field[ET_FIELD_STATUS]-> + store((longlong) Event_parse_data::SLAVESIDE_DISABLED, + TRUE); + (void) table->file->ha_update_row(table->record[1], table->record[0]); + delete et; + continue; + } +#endif drop_on_completion= (et->on_completion == Event_parse_data::ON_COMPLETION_DROP); @@ -1158,6 +1172,33 @@ int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len) } return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); } +static int +wsrep_alter_query_string(THD *thd, String *buf) +{ + /* Append the "ALTER" part of the query */ + if (buf->append(STRING_WITH_LEN("ALTER "))) + return 1; + /* Append definer */ + append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); + /* Append the left part of thd->query after event name part */ + if (buf->append(thd->lex->stmt_definition_begin, + thd->lex->stmt_definition_end - + thd->lex->stmt_definition_begin)) + return 1; + + return 0; +} +int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len) +{ + String log_query; + + if (wsrep_alter_query_string(thd, &log_query)) + { + WSREP_WARN("events alter string failed: %s", thd->query()); + return 1; + } + return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); +} #endif /* WITH_WSREP */ /** @} (End of group Event_Scheduler) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 33e5e47bff1..6d9c9eb0b7a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2761,7 +2761,8 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) /* Mark that current_thd is not valid anymore */ my_pthread_setspecific_ptr(THR_THD, 0); #ifdef WITH_WSREP - if (put_in_cache && !thd->wsrep_applier) + const bool wsrep_applier(thd->wsrep_applier); + if (put_in_cache && !wsrep_applier) #else if (put_in_cache) #endif /* WITH_WSREP */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0a116b41308..5a9c71acc52 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6550,7 +6550,7 @@ alter: } view_tail {} - | ALTER definer_opt EVENT_SYM sp_name + | ALTER definer_opt remember_name EVENT_SYM sp_name { /* It is safe to use Lex->spname because @@ -6562,9 +6562,12 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(thd))) MYSQL_YYABORT; - Lex->event_parse_data->identifier= $4; + Lex->event_parse_data->identifier= $5; Lex->sql_command= SQLCOM_ALTER_EVENT; +#ifdef WITH_WSREP + Lex->stmt_definition_begin= $3; +#endif } ev_alter_on_schedule_completion opt_ev_rename_to @@ -6572,7 +6575,7 @@ alter: opt_ev_comment opt_ev_sql_stmt { - if (!($6 || $7 || $8 || $9 || $10)) + if (!($7 || $8 || $9 || $10 || $11)) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -6582,6 +6585,9 @@ alter: can overwrite it */ Lex->sql_command= SQLCOM_ALTER_EVENT; +#ifdef WITH_WSREP + Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr(); +#endif } | ALTER TABLESPACE alter_tablespace_info { diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 4fd07a9945c..1d869ab84c5 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -509,7 +509,20 @@ int wsrep_init() wsrep_ready_set(TRUE); wsrep_inited= 1; global_system_variables.wsrep_on = 0; - return 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 { @@ -1216,6 +1229,9 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, case SQLCOM_CREATE_EVENT: buf_err= wsrep_create_event_query(thd, &buf, &buf_len); break; + case SQLCOM_ALTER_EVENT: + buf_err= wsrep_alter_event_query(thd, &buf, &buf_len); + break; default: buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf, &buf_len); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index ec2a38278ab..7939bf55684 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -298,6 +298,7 @@ int wsrep_to_buf_helper( int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len); int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len); const wsrep_uuid_t* wsrep_cluster_uuid(); struct xid_t; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 3fed6db6d0d..132cfc7c5d2 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -23,11 +23,20 @@ #include "sql_base.h" // close_thread_tables() #include "mysqld.h" // start_wsrep_THD(); -static long long wsrep_bf_aborts_counter = 0; + +#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 int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff) { - wsrep_local_bf_aborts = my_atomic_load64(&wsrep_bf_aborts_counter); + wsrep_local_bf_aborts = WSREP_ATOMIC_LOAD_LONG(&wsrep_bf_aborts_counter); var->type = SHOW_LONGLONG; var->value = (char*)&wsrep_local_bf_aborts; return 0; @@ -39,7 +48,7 @@ void wsrep_client_rollback(THD *thd) WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", thd->thread_id, thd->query()); - my_atomic_add64(&wsrep_bf_aborts_counter, 1); + WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1); thd->wsrep_conflict_state= ABORTING; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 98cb239befc..48bb3183f9f 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1820,7 +1820,12 @@ lock_rec_create( automatically of the gap type */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { +#ifdef WITH_WSREP + ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || + wsrep_thd_is_BF(trx->mysql_thd, FALSE)); +#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); +#endif /* WITH_WSREP */ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } @@ -2104,7 +2109,12 @@ lock_rec_add_to_queue( struct for a gap type lock */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { +#ifdef WITH_WSREP + ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || + wsrep_thd_is_BF(trx->mysql_thd, FALSE)); +#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); +#endif /* WITH_WSREP */ /* There should never be LOCK_REC_NOT_GAP on a supremum record, but let us play safe */ diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 3419297f059..d250a8b47b8 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1696,10 +1696,6 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; -#ifdef WITH_WSREP - /* appliers don't need dupkey checks */ - if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) return(DB_SUCCESS); -#endif /* WITH_WSREP */ rec_offs_init(offsets_); n_unique = dict_index_get_n_unique(index); @@ -1764,6 +1760,13 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) { + if (!(lock_type & LOCK_REC_NOT_GAP)) { + lock_type |= LOCK_REC_NOT_GAP; + } + } +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index d9a5768d94c..e17398fe0e3 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -1821,7 +1821,12 @@ lock_rec_create( automatically of the gap type */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { +#ifdef WITH_WSREP + ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || + wsrep_thd_is_BF(trx->mysql_thd, FALSE)); +#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); +#endif /* WITH_WSREP */ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } @@ -2111,7 +2116,12 @@ lock_rec_add_to_queue( struct for a gap type lock */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { +#ifdef WITH_WSREP + ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || + wsrep_thd_is_BF(trx->mysql_thd, FALSE)); +#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); +#endif /* WITH_WSREP */ /* There should never be LOCK_REC_NOT_GAP on a supremum record, but let us play safe */ diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index a1ee411b8cd..3f38a080c3b 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1705,10 +1705,6 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; -#ifdef WITH_WSREP - /* appliers don't need dupkey checks */ - if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) return(DB_SUCCESS); -#endif /* WITH_WSREP */ rec_offs_init(offsets_); n_unique = dict_index_get_n_unique(index); @@ -1773,6 +1769,13 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) { + if (!(lock_type & LOCK_REC_NOT_GAP)) { + lock_type |= LOCK_REC_NOT_GAP; + } + } +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index c03763c7d45..1764e7d518f 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -304,7 +304,7 @@ Version: %{mysql_version} Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases %if %{defined with_wsrep} -Requires: %{distro_requires} rsync +Requires: %{distro_requires} rsync lsof %else Requires: %{distro_requires} %endif diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index 3c7f97ede3f..fb5881410ff 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -20,11 +20,13 @@ #include #include +#include /*! 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 */ @@ -43,6 +45,10 @@ static void dummy_free(wsrep_t *w) { WSREP_DBUG_ENTER(w); free(w->ctx); + if (WSREP_DUMMY(w)->options) { + free(WSREP_DUMMY(w)->options); + WSREP_DUMMY(w)->options = NULL; + } w->ctx = NULL; } @@ -51,6 +57,9 @@ static wsrep_status_t dummy_init (wsrep_t* w, { 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; } @@ -61,16 +70,23 @@ static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused))) static wsrep_status_t dummy_options_set( wsrep_t* w, - const char* conf __attribute__((unused))) + 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) { WSREP_DBUG_ENTER(w); - return NULL; + return WSREP_DUMMY(w)->options; } static wsrep_status_t dummy_connect( @@ -385,6 +401,7 @@ int wsrep_dummy_loader(wsrep_t* w) // initialize private context WSREP_DUMMY(w)->log_fn = NULL; + WSREP_DUMMY(w)->options = NULL; return 0; } From 1410785e8ab283f2592867985b6560329e874f63 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Jun 2014 17:35:44 -0400 Subject: [PATCH 154/294] Fix for a segfault. --- wsrep/wsrep_dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index fb5881410ff..bab5329dc02 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -44,11 +44,11 @@ typedef struct wsrep_dummy static void dummy_free(wsrep_t *w) { WSREP_DBUG_ENTER(w); - free(w->ctx); if (WSREP_DUMMY(w)->options) { free(WSREP_DUMMY(w)->options); WSREP_DUMMY(w)->options = NULL; } + free(w->ctx); w->ctx = NULL; } From 93cc06b20cd83f6f84ac152d66214f48462ee1df Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 10 Jun 2014 18:31:07 -0400 Subject: [PATCH 155/294] Fixed a warning in mtr script. Updated wsrep.variables test. --- mysql-test/mysql-test-run.pl | 2 +- mysql-test/suite/wsrep/r/variables.result | 12 ++++++------ mysql-test/suite/wsrep/t/variables.test | 14 +++++++++++++- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 12af2efdaad..4522911eec9 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2406,7 +2406,7 @@ sub environment_setup { $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; } - if ($ENV{'WSREP_PROVIDER'} ne "") { + if ((defined $ENV{'WSREP_PROVIDER'}) && ($ENV{'WSREP_PROVIDER'} ne "")) { mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); } else { mtr_verbose("WSREP_PROVIDER isn't available"); diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index ffa908ad359..bfa371da3a7 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -19,13 +19,13 @@ call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_sla call mtr.add_suppression("WSREP: Failed to get provider options"); SELECT @@global.wsrep_provider; @@global.wsrep_provider -none +libgalera_smm.so SELECT @@global.wsrep_slave_threads; @@global.wsrep_slave_threads 1 SELECT @@global.wsrep_cluster_address; @@global.wsrep_cluster_address - +NULL SHOW STATUS LIKE 'threads_connected'; Variable_name Value Threads_connected 1 @@ -33,10 +33,9 @@ SHOW STATUS LIKE 'wsrep_thread_count'; Variable_name Value wsrep_thread_count 0 -SET GLOBAL wsrep_provider= '/usr/lib/galera/libgalera_smm.so'; SELECT @@global.wsrep_provider; @@global.wsrep_provider -/usr/lib/galera/libgalera_smm.so +libgalera_smm.so SELECT @@global.wsrep_cluster_address; @@global.wsrep_cluster_address NULL @@ -53,7 +52,7 @@ SET GLOBAL wsrep_cluster_address= 'gcomm://'; # Wait for applier threads to get created. SELECT @@global.wsrep_provider; @@global.wsrep_provider -/usr/lib/galera/libgalera_smm.so +libgalera_smm.so SELECT @@global.wsrep_cluster_address; @@global.wsrep_cluster_address gcomm:// @@ -74,6 +73,7 @@ SHOW STATUS LIKE 'wsrep_thread_count'; Variable_name Value wsrep_thread_count 11 SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_provider= none; SET GLOBAL wsrep_cluster_address= ''; -SET GLOBAL wsrep_provider= 'none'; +SET GLOBAL wsrep_provider_options= ''; # End of test. diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index a584d0b39f0..59d2aeccafd 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -5,6 +5,10 @@ --echo # --echo # Testing wsrep_replicate_myisam variable. +--disable_query_log +eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; +--enable_query_log + --error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@session.wsrep_replicate_myisam; SELECT @@global.wsrep_replicate_myisam; @@ -22,6 +26,7 @@ SET GLOBAL wsrep_replicate_myisam= OFF; --echo # call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); call mtr.add_suppression("WSREP: Failed to get provider options"); +--replace_regex /.*libgalera_smm.*/libgalera_smm.so/ SELECT @@global.wsrep_provider; SELECT @@global.wsrep_slave_threads; SELECT @@global.wsrep_cluster_address; @@ -29,7 +34,11 @@ SHOW STATUS LIKE 'threads_connected'; SHOW STATUS LIKE 'wsrep_thread_count'; --echo +--disable_query_log eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; +--enable_query_log + +--replace_regex /.*libgalera_smm.*/libgalera_smm.so/ SELECT @@global.wsrep_provider; SELECT @@global.wsrep_cluster_address; SHOW STATUS LIKE 'threads_connected'; @@ -41,6 +50,8 @@ SHOW STATUS LIKE 'wsrep_thread_count'; SET GLOBAL wsrep_cluster_address= 'gcomm://'; --echo # Wait for applier threads to get created. sleep 3; + +--replace_regex /.*libgalera_smm.*/libgalera_smm.so/ SELECT @@global.wsrep_provider; SELECT @@global.wsrep_cluster_address; SHOW STATUS LIKE 'threads_connected'; @@ -56,8 +67,9 @@ SHOW STATUS LIKE 'wsrep_thread_count'; # reset (for mtr internal checks) SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_provider= none; SET GLOBAL wsrep_cluster_address= ''; -SET GLOBAL wsrep_provider= 'none'; +SET GLOBAL wsrep_provider_options= ''; --echo # End of test. From 85032e36c66820c851b63b5189bc397404af51c7 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 11 Jun 2014 17:13:03 -0400 Subject: [PATCH 156/294] Modified patch for lp:1310875. --- sql/mysqld.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6d9c9eb0b7a..c008be9d5d3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2757,11 +2757,15 @@ static bool cache_thread() bool one_thread_per_connection_end(THD *thd, bool put_in_cache) { DBUG_ENTER("one_thread_per_connection_end"); +#ifdef WITH_WSREP + const bool wsrep_applier(thd->wsrep_applier); +#endif /* WITH_WSREP */ + unlink_thd(thd); /* Mark that current_thd is not valid anymore */ my_pthread_setspecific_ptr(THR_THD, 0); + #ifdef WITH_WSREP - const bool wsrep_applier(thd->wsrep_applier); if (put_in_cache && !wsrep_applier) #else if (put_in_cache) From c7ad886a7039306aeb591e542e827a68c3302e29 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 15 Jun 2014 13:53:43 -0400 Subject: [PATCH 157/294] MDEV#6296: runtime adjustment of wsrep_slave_threads creates threads but never removes them When wsrep_slave_threads is changed at runtime, the old "change" value is not taken into account and thus successive SETs can make wsrep_slave_threads value inconsistent with the actual number of applier threads present. --- sql/wsrep_var.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 319c5fca979..8aa2c9f321b 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -453,7 +453,7 @@ void wsrep_node_address_init (const char* value) bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) { mysql_mutex_lock(&LOCK_wsrep_slave_threads); - wsrep_slave_count_change = var->value->val_int() - wsrep_slave_threads; + wsrep_slave_count_change += (var->value->val_int() - wsrep_slave_threads); mysql_mutex_unlock(&LOCK_wsrep_slave_threads); return 0; From b5a2600e4ba6f4027561bb0a41bac11b1239a856 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 23 Jun 2014 09:37:46 -0400 Subject: [PATCH 158/294] Empty revision to trigger build on buildbot. From b7a5b71fb3c56f3b7ba706935fec5bb30c04f082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 30 Jun 2014 14:02:54 +0300 Subject: [PATCH 159/294] MDEV-6225: Idle replication slave keeps crashing. Analysis: Based on crashed the buffer pool instance identifier is not correct on block to be freed. Add LRU list mutex holding on functions calling free and add additional safety checks. --- scripts/mysql_config.pl | 4 +- storage/xtradb/btr/btr0cur.c | 4 +- storage/xtradb/buf/buf0buf.c | 4 +- storage/xtradb/buf/buf0lru.c | 60 ++++++++++++++++++++++++----- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/include/buf0buf.ic | 6 +-- storage/xtradb/include/buf0lru.h | 1 + 7 files changed, 61 insertions(+), 20 deletions(-) diff --git a/scripts/mysql_config.pl b/scripts/mysql_config.pl index 20ed9e023eb..5490853c091 100644 --- a/scripts/mysql_config.pl +++ b/scripts/mysql_config.pl @@ -53,7 +53,7 @@ my $cwd = cwd(); my $basedir; my $socket = '/tmp/mysql.sock'; -my $version = '5.5.37'; +my $version = '5.5.38'; sub which { @@ -204,7 +204,7 @@ $flags->{embedded_libs} = [@ldflags,@lib_e_opts,'','','','','']; $flags->{include} = ["-I$pkgincludedir"]; -$flags->{cflags} = [@{$flags->{include}},split(" ",'-Wall -DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048 -DWITH_INNODB_DISALLOW_WRITES -fPIC -O2 -g -DNDEBUG -DDBUG_OFF')]; +$flags->{cflags} = [@{$flags->{include}},split(" ",'-Wall -DWITH_WSREP -DWSREP_PROC_INFO -DMYSQL_MAX_VARIABLE_VALUE_LEN=2048 -DWITH_INNODB_DISALLOW_WRITES -O2 -g -DNDEBUG -DDBUG_OFF')]; # ---------------------------------------------------------------------- # Remove some options that a client doesn't have to care about diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index 3c56d29bdd0..e4c774d8b07 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -4428,7 +4428,7 @@ btr_blob_free( && buf_block_get_space(block) == space && buf_block_get_page_no(block) == page_no) { - if (!buf_LRU_free_block(&block->page, all, &have_LRU_mutex) + if (!buf_LRU_free_block(&block->page, (void *)&block->mutex, all, &have_LRU_mutex) && all && block->page.zip.data /* Now, buf_LRU_free_block() may release mutex temporarily */ && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE @@ -4437,7 +4437,7 @@ btr_blob_free( /* Attempt to deallocate the uncompressed page if the whole block cannot be deallocted. */ - buf_LRU_free_block(&block->page, FALSE, &have_LRU_mutex); + buf_LRU_free_block(&block->page, (void *)&block->mutex, FALSE, &have_LRU_mutex); } } diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index 38652a62034..2ec49594775 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -2069,7 +2069,7 @@ err_exit: } /* Discard the uncompressed page frame if possible. */ - if (buf_LRU_free_block(bpage, FALSE, &have_LRU_mutex)) { + if (buf_LRU_free_block(bpage, (void *)block_mutex, FALSE, &have_LRU_mutex)) { if (have_LRU_mutex) { mutex_exit(&buf_pool->LRU_list_mutex); have_LRU_mutex = FALSE; @@ -2843,7 +2843,7 @@ wait_until_unfixed: insert buffer (change buffer) as much as possible. */ ulint page_no = buf_block_get_page_no(block); - if (buf_LRU_free_block(&block->page, TRUE, &have_LRU_mutex)) { + if (buf_LRU_free_block(&block->page, (void *)block_mutex, TRUE, &have_LRU_mutex)) { mutex_exit(block_mutex); if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { /* Set the watch, as it would have diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index cfb45232084..a1fdf0a951c 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -957,6 +957,7 @@ buf_LRU_free_from_unzip_LRU_list( { buf_block_t* block; ulint distance; + ibool taken_LRU_mutex = FALSE; //ut_ad(buf_pool_mutex_own(buf_pool)); @@ -976,6 +977,12 @@ buf_LRU_free_from_unzip_LRU_list( distance = 100 + (n_iterations * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5; + if (!*have_LRU_mutex) { + mutex_enter(&buf_pool->LRU_list_mutex); + taken_LRU_mutex = TRUE; + *have_LRU_mutex = TRUE; + } + restart: for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0); @@ -990,18 +997,30 @@ restart: goto restart; } + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); + ut_a(block->page.buf_pool_index < srv_buf_pool_instances); ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_ad(block->in_unzip_LRU_list); ut_ad(block->page.in_LRU_list); - freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex); + freed = buf_LRU_free_block(&block->page, (void *)&block->mutex, FALSE, have_LRU_mutex); mutex_exit(&block->mutex); if (freed) { + + if (taken_LRU_mutex && *have_LRU_mutex) { + mutex_exit(&buf_pool->LRU_list_mutex); + *have_LRU_mutex = FALSE; + } return(TRUE); } } + if (taken_LRU_mutex && *have_LRU_mutex) { + mutex_exit(&buf_pool->LRU_list_mutex); + *have_LRU_mutex = FALSE; + } + return(FALSE); } @@ -1024,11 +1043,18 @@ buf_LRU_free_from_common_LRU_list( { buf_page_t* bpage; ulint distance; + ibool taken_LRU_mutex = FALSE; //ut_ad(buf_pool_mutex_own(buf_pool)); distance = 100 + (n_iterations * buf_pool->curr_size) / 10; + if (!*have_LRU_mutex) { + mutex_enter(&buf_pool->LRU_list_mutex); + taken_LRU_mutex = TRUE; + *have_LRU_mutex = TRUE; + } + restart: for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0); @@ -1048,11 +1074,13 @@ restart: goto restart; } + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); + ut_a(bpage->buf_pool_index < srv_buf_pool_instances); accessed = buf_page_is_accessed(bpage); - freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex); + freed = buf_LRU_free_block(bpage, (void *)block_mutex, TRUE, have_LRU_mutex); mutex_exit(block_mutex); if (freed) { @@ -1062,10 +1090,21 @@ restart: if (!accessed) { ++buf_pool->stat.n_ra_pages_evicted; } + + if (taken_LRU_mutex && *have_LRU_mutex) { + mutex_exit(&buf_pool->LRU_list_mutex); + *have_LRU_mutex = FALSE; + } + return(TRUE); } } + if (taken_LRU_mutex && *have_LRU_mutex) { + mutex_exit(&buf_pool->LRU_list_mutex); + *have_LRU_mutex = FALSE; + } + return(FALSE); } @@ -1846,16 +1885,17 @@ ibool buf_LRU_free_block( /*===============*/ buf_page_t* bpage, /*!< in: block to be freed */ + void* block_mutex, /*!< in: block mutex or NULL */ ibool zip, /*!< in: TRUE if should remove also the compressed page of an uncompressed page */ ibool* have_LRU_mutex) { buf_page_t* b = NULL; buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - mutex_t* block_mutex = buf_page_get_mutex(bpage); + //mutex_t* block_mutex = buf_page_get_mutex(bpage); //ut_ad(buf_pool_mutex_own(buf_pool)); - ut_ad(mutex_own(block_mutex)); + ut_ad(mutex_own((mutex_t*)block_mutex)); ut_ad(buf_page_in_file(bpage)); //ut_ad(bpage->in_LRU_list); ut_ad(!bpage->in_flush_list == !bpage->oldest_modification); @@ -1912,14 +1952,14 @@ alloc: #endif /* UNIV_DEBUG */ /* not to break latch order, must re-enter block_mutex */ - mutex_exit(block_mutex); + mutex_exit((mutex_t*)block_mutex); if (!*have_LRU_mutex) { mutex_enter(&buf_pool->LRU_list_mutex); /* optimistic */ *have_LRU_mutex = TRUE; } rw_lock_x_lock(&buf_pool->page_hash_latch); - mutex_enter(block_mutex); + mutex_enter((mutex_t*)block_mutex); /* recheck states of block */ if (!bpage->in_LRU_list || block_mutex != buf_page_get_mutex(bpage) @@ -2071,7 +2111,7 @@ not_freed: *have_LRU_mutex = FALSE; } rw_lock_x_unlock(&buf_pool->page_hash_latch); - mutex_exit(block_mutex); + mutex_exit((mutex_t*)block_mutex); /* Remove possible adaptive hash index on the page. The page was declared uninitialized by @@ -2107,7 +2147,7 @@ not_freed: mutex_enter(&buf_pool->LRU_list_mutex); *have_LRU_mutex = TRUE; } - mutex_enter(block_mutex); + mutex_enter((mutex_t*)block_mutex); if (b) { mutex_enter(&buf_pool->zip_mutex); @@ -2126,8 +2166,8 @@ not_freed: /* The block_mutex should have been released by buf_LRU_block_remove_hashed_page() when it returns BUF_BLOCK_ZIP_FREE. */ - ut_ad(block_mutex == &buf_pool->zip_mutex); - mutex_enter(block_mutex); + ut_ad((mutex_t*)block_mutex == &buf_pool->zip_mutex); + mutex_enter((mutex_t*)block_mutex); if (*have_LRU_mutex) { mutex_exit(&buf_pool->LRU_list_mutex); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 93338795eb5..dcb56cc4df8 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -13715,7 +13715,7 @@ innodb_buffer_pool_evict_update( mutex_enter(&block->mutex); buf_LRU_free_block(&block->page, - FALSE, &have_LRU_mutex); + (void *)&block->mutex,FALSE, &have_LRU_mutex); mutex_exit(&block->mutex); block = prev_block; } diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic index 18c46b6412e..7fd32e4e995 100644 --- a/storage/xtradb/include/buf0buf.ic +++ b/storage/xtradb/include/buf0buf.ic @@ -60,7 +60,7 @@ buf_pool_index( { ulint i = buf_pool - buf_pool_ptr; ut_ad(i < MAX_BUFFER_POOLS); - ut_ad(i < srv_buf_pool_instances); + ut_a(i < srv_buf_pool_instances); return(i); } @@ -75,7 +75,7 @@ buf_pool_from_bpage( { ulint i; i = bpage->buf_pool_index; - ut_ad(i < srv_buf_pool_instances); + ut_a(i < srv_buf_pool_instances); return(&buf_pool_ptr[i]); } @@ -1097,7 +1097,7 @@ buf_pool_from_array( buffer pool instance from */ { ut_ad(index < MAX_BUFFER_POOLS); - ut_ad(index < srv_buf_pool_instances); + ut_a(index < srv_buf_pool_instances); return(&buf_pool_ptr[index]); } diff --git a/storage/xtradb/include/buf0lru.h b/storage/xtradb/include/buf0lru.h index 4b415214fa5..00988f0957a 100644 --- a/storage/xtradb/include/buf0lru.h +++ b/storage/xtradb/include/buf0lru.h @@ -99,6 +99,7 @@ ibool buf_LRU_free_block( /*===============*/ buf_page_t* bpage, /*!< in: block to be freed */ + void* block_mutex, /*!< in: block mutex or NULL */ ibool zip, /*!< in: TRUE if should remove also the compressed page of an uncompressed page */ ibool* have_LRU_mutex) From 04db5aeb097a9733ba31015f09198aea04067ee4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 30 Jun 2014 09:04:46 -0400 Subject: [PATCH 160/294] Bumping server version. (5.5.39-galera) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a519214c0c5..67a35621511 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=38 +MYSQL_VERSION_PATCH=39 MYSQL_VERSION_EXTRA= From 40bfd20180a392f0c2e56cc99fff9ab3bf3ef87f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 9 Jul 2014 11:04:28 -0400 Subject: [PATCH 161/294] MDEV#6411 - Setting set @@global_wsrep_sst_auth=NULL causes crash Fixed by properly handling the NULL values. --- mysql-test/suite/wsrep/r/variables.result | 18 ++++++++ mysql-test/suite/wsrep/t/variables.test | 18 ++++++++ sql/mysqld.cc | 4 +- sql/wsrep_mysqld.cc | 7 +++- sql/wsrep_mysqld.h | 2 +- sql/wsrep_sst.cc | 51 ++++++++++++++--------- sql/wsrep_sst.h | 1 + sql/wsrep_var.cc | 2 +- 8 files changed, 79 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index bfa371da3a7..bbd969c735a 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -11,6 +11,7 @@ SET SESSION wsrep_replicate_myisam= ON; ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable and should be set with SET GLOBAL SET GLOBAL wsrep_replicate_myisam= ON; SET GLOBAL wsrep_replicate_myisam= OFF; +SET GLOBAL wsrep_provider=none; # # MDEV#6206: wsrep_slave_threads subtracts from max_connections @@ -76,4 +77,21 @@ SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; SET GLOBAL wsrep_provider= none; SET GLOBAL wsrep_cluster_address= ''; SET GLOBAL wsrep_provider_options= ''; +# +# MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash +# +SET @wsrep_sst_auth_saved= @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth= 'user:pass'; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +******** +SET @@global.wsrep_sst_auth= ''; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth + +SET @@global.wsrep_sst_auth= NULL; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +NULL +SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; # End of test. diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 59d2aeccafd..a79a99bfecc 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -19,6 +19,7 @@ SET GLOBAL wsrep_replicate_myisam= ON; # Reset it back. SET GLOBAL wsrep_replicate_myisam= OFF; +SET GLOBAL wsrep_provider=none; --echo --echo # @@ -26,6 +27,11 @@ SET GLOBAL wsrep_replicate_myisam= OFF; --echo # call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); call mtr.add_suppression("WSREP: Failed to get provider options"); + +--disable_query_log +eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; +--enable_query_log + --replace_regex /.*libgalera_smm.*/libgalera_smm.so/ SELECT @@global.wsrep_provider; SELECT @@global.wsrep_slave_threads; @@ -71,5 +77,17 @@ SET GLOBAL wsrep_provider= none; SET GLOBAL wsrep_cluster_address= ''; SET GLOBAL wsrep_provider_options= ''; +--echo # +--echo # MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash +--echo # +SET @wsrep_sst_auth_saved= @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth= 'user:pass'; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth= ''; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth= NULL; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; + --echo # End of test. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c008be9d5d3..888900565db 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1759,7 +1759,7 @@ static void __cdecl kill_server(int sig_ptr) close_connections(); #ifdef WITH_WSREP if (wsrep_inited == 1) - wsrep_deinit(); + wsrep_deinit(true); #endif if (sig != MYSQL_KILL_SIGNAL && sig != 0) @@ -1871,7 +1871,7 @@ extern "C" void unireg_abort(int exit_code) /* In bootstrap mode we deinitialize wsrep here. */ if (opt_bootstrap && wsrep_inited) - wsrep_deinit(); + wsrep_deinit(true); } #endif // WITH_WSREP diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 1d869ab84c5..a0ea67c51ab 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -696,7 +696,7 @@ void wsrep_init_startup (bool first) } -void wsrep_deinit() +void wsrep_deinit(bool free_options) { DBUG_ASSERT(wsrep_inited == 1); wsrep_unload(wsrep); @@ -708,6 +708,11 @@ void wsrep_deinit() delete wsrep_format_desc; wsrep_format_desc= NULL; wsrep_inited= 0; + + if (free_options) + { + wsrep_sst_auth_free(); + } } void wsrep_recover() diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 7939bf55684..8e5b14f37a0 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -124,7 +124,7 @@ void wsrep_free_status(THD *thd); void wsrep_filter_new_cluster (int* argc, char* argv[]); int wsrep_init(); -void wsrep_deinit(); +void wsrep_deinit(bool free_options); void wsrep_recover(); bool wsrep_before_SE(); // initialize wsrep before storage // engines (true) or after (false) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 1b57b63131c..be9efa86873 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -120,31 +120,44 @@ bool wsrep_sst_auth_check (sys_var *self, THD* thd, set_var* var) { return 0; } + static bool sst_auth_real_set (const char* value) { - const char* v = strdup (value); + const char* v= NULL; - if (v) + if (value) + { + v= my_strdup(value, MYF(0)); + } + else // its NULL + { + wsrep_sst_auth_free(); + return 0; + } + + if (v) + { + // set sst_auth_real + if (sst_auth_real) { my_free((void *) sst_auth_real); } + sst_auth_real = v; + + // mask wsrep_sst_auth + if (strlen(sst_auth_real)) { - if (sst_auth_real) free (const_cast(sst_auth_real)); - sst_auth_real = v; - - if (strlen(sst_auth_real)) - { - if (wsrep_sst_auth) - { - my_free ((void*)wsrep_sst_auth); - wsrep_sst_auth = my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); - //strncpy (wsrep_sst_auth, WSREP_SST_AUTH_MASK, - // sizeof(wsrep_sst_auth) - 1); - } - else - wsrep_sst_auth = my_strdup (WSREP_SST_AUTH_MASK, MYF(0)); - } - return 0; + if (wsrep_sst_auth) { my_free((void*) wsrep_sst_auth); } + wsrep_sst_auth= my_strdup(WSREP_SST_AUTH_MASK, MYF(0)); } + return 0; + } + return 1; +} - return 1; +void wsrep_sst_auth_free() +{ + if (wsrep_sst_auth) { my_free((void *) wsrep_sst_auth); } + if (sst_auth_real) { my_free((void *) sst_auth_real); } + wsrep_sst_auth= NULL; + sst_auth_real= NULL; } bool wsrep_sst_auth_update (sys_var *self, THD* thd, enum_var_type type) diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index b7f0e26f226..dc7789f5a4e 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -31,6 +31,7 @@ extern void wsrep_sst_grab(); extern bool wsrep_sst_wait(); /*! Signals wsrep that initialization is complete, writesets can be applied */ extern void wsrep_sst_continue(); +extern void wsrep_sst_auth_free(); extern void wsrep_SE_init_grab(); /*! grab init critical section */ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 8aa2c9f321b..54d0b1cdfe6 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -239,7 +239,7 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) mysql_mutex_lock(&LOCK_global_system_variables); if (wsrep_inited == 1) - wsrep_deinit(); + wsrep_deinit(false); char* tmp= strdup(wsrep_provider); // wsrep_init() rewrites provider //when fails From d2cd778a27f77fcf38585e7a029e005082ea50af Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 10 Jul 2014 12:51:34 -0400 Subject: [PATCH 162/294] MDEV-5786: mysql_upgrade on galera replicates "alter table" on system tables With wsrep patch, binary logging is implicitly enabled. This fix makes sure that it is turned off for --skip-write-binlog by swithcing off wsrep_on. --- client/mysql_upgrade.c | 5 +++++ client/mysqlcheck.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 5fb3b1317d9..760461b5d11 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -523,7 +523,12 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, int ret; File fd; char query_file_path[FN_REFLEN]; +#ifdef WITH_WSREP + /* Note: wsrep_on=ON implicitly enables binary logging. */ + const uchar sql_log_bin[]= "SET SQL_LOG_BIN=0, WSREP_ON=OFF;"; +#else const uchar sql_log_bin[]= "SET SQL_LOG_BIN=0;"; +#endif /* WITH_WSREP */ DBUG_ENTER("run_query"); DBUG_PRINT("enter", ("query: %s", query)); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 11a88c834b8..a4b5d856d44 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -729,9 +729,15 @@ static int use_db(char *database) DBUG_RETURN(0); } /* use_db */ +/* Do not send commands to replication slaves. */ static int disable_binlog() { +#ifdef WITH_WSREP + /* Additionally turn off @@wsrep_on to disable implicit binary logging. */ + const char *stmt= "SET SQL_LOG_BIN=0, WSREP_ON=OFF"; +#else const char *stmt= "SET SQL_LOG_BIN=0"; +#endif /* WITH_WSREP */ return run_query(stmt); } From 3ce3647055c0749b6a2029b85f179146b5e8b2be Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 12 Jul 2014 18:20:45 -0400 Subject: [PATCH 163/294] MDEV#6399 - Make galera test suite run with --parallel Galera tests used default base/SST ports which led to failures due to port conflicts when run in parallel. Fixed by setting them to ones generated by mtr framework. --- mysql-test/lib/My/ConfigFactory.pm | 3 +++ mysql-test/mysql-test-run.pl | 1 + mysql-test/suite/galera/galera_2nodes.cnf | 7 +++++-- mysql-test/suite/wsrep/my.cnf | 8 ++++++++ mysql-test/suite/wsrep/t/binlog_format.opt | 2 +- mysql-test/suite/wsrep/t/pool_of_threads.opt | 2 +- mysql-test/suite/wsrep/t/variables.test | 6 ++++++ 7 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/wsrep/my.cnf diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index e79d97e045e..367f69ca86d 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -238,6 +238,9 @@ my @mysqld_rules= { 'pid-file' => \&fix_pidfile }, { '#host' => \&fix_host }, { 'port' => \&fix_port }, + # galera base_port and port used during SST + { '#galera_port' => \&fix_port }, + { '#sst_port' => \&fix_port }, { 'socket' => \&fix_socket }, { '#log-error' => \&fix_log_error }, { 'general-log' => 1 }, diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4522911eec9..c0b4598663d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4859,6 +4859,7 @@ sub extract_warning_lines ($$) { # Galera-related warnings. qr|WSREP:.*down context.*|, qr|WSREP: Failed to send state UUID:.*|, + qr|WSREP: wsrep_sst_receive_address.*|, ); my $matched_lines= []; diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index 21a45dec5f3..5a08125089a 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -5,12 +5,15 @@ binlog-format=row wsrep_provider=@ENV.WSREP_PROVIDER 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' [mysqld.2] binlog-format=row wsrep_provider=@ENV.WSREP_PROVIDER -wsrep_cluster_address='gcomm://127.0.0.1:4567' -wsrep_provider_options='gmcast.listen_addr=tcp://127.0.0.1:4568' +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' [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/wsrep/my.cnf b/mysql-test/suite/wsrep/my.cnf new file mode 100644 index 00000000000..fc314fbfb40 --- /dev/null +++ b/mysql-test/suite/wsrep/my.cnf @@ -0,0 +1,8 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld.1] + +[ENV] +GALERA_BASE_PORT=@mysqld.1.#galera_port + diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt index 83194184e17..1b8937b91f3 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.opt +++ b/mysql-test/suite/wsrep/t/binlog_format.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --log-bin +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --wsrep-on=1 --log-bin diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.opt b/mysql-test/suite/wsrep/t/pool_of_threads.opt index fb23fb50a67..5ee38531a4a 100644 --- a/mysql-test/suite/wsrep/t/pool_of_threads.opt +++ b/mysql-test/suite/wsrep/t/pool_of_threads.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --thread_handling=pool-of-threads +--binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --thread_handling=pool-of-threads diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index a79a99bfecc..f71735f64c4 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -1,5 +1,11 @@ --source include/have_wsrep.inc +# Set galera's base_port so that test can run in parallel with other galera +# tests. +--disable_query_log +eval SET GLOBAL wsrep_provider_options='base_port=$GALERA_BASE_PORT'; +--enable_query_log + --echo --echo # MDEV#5534: mysql_tzinfo_to_sql generates wrong query --echo # From 9c3f623777237d2a5f6104baf3dc657ef03a747c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 15 Jul 2014 00:54:29 -0400 Subject: [PATCH 164/294] MDEV-4728: MariaDB can't start while bootup Introduced safety checks to ensure mysqld_safe terminates if mktemp fails to create a valid file. --- scripts/mysqld_safe.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 09ac77785af..d4f936f33f5 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -229,8 +229,19 @@ wsrep_recover_position() { local wr_logfile=$(mktemp $DATADIR/wsrep_recovery.XXXXXX) - [ "$euid" = "0" ] && chown $user $wr_logfile - chmod 600 $wr_logfile + # safety checks + if [ -z $wr_logfile ]; then + log_error "WSREP: mktemp failed" + return 1 + fi + + if [ -f $wr_logfile ]; then + [ "$euid" = "0" ] && chown $user $wr_logfile + chmod 600 $wr_logfile + else + log_error "WSREP: mktemp failed" + return 1 + fi local wr_pidfile="$DATADIR/"`@HOSTNAME@`"-recover.pid" From 0dadd017501e379546ffe3edae7728b931007be0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 17 Jul 2014 16:22:01 -0400 Subject: [PATCH 165/294] MDEV-3896: More user-friendly cnf files in MariaDB-Galera rpm/deb packages * Added "galera" as default option group. * Updated deb/rpm server config files to include mandatory and optional settings (as comments) required to configure Galera cluster. --- debian/additions/my.cnf | 16 +++++++++++++++- include/mysqld_default_groups.h | 3 +++ support-files/rpm/server.cnf | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index a27f8543f0b..962a65c89ae 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -151,7 +151,21 @@ innodb_flush_method = O_DIRECT # ssl-cert=/etc/mysql/server-cert.pem # ssl-key=/etc/mysql/server-key.pem - +# +# * Galera-related settings +# +[galera] +# Mandatory settings +#wsrep_provider= +#wsrep_cluster_address= +#wsrep_slave_threads=1 +#binlog_format=row +#default_storage_engine=InnoDB +#innodb_autoinc_lock_mode=2 +#query_cache_size=0 +# +# Optional setting +#innodb_flush_log_at_trx_commit=2 [mysqldump] quick diff --git a/include/mysqld_default_groups.h b/include/mysqld_default_groups.h index a2e94ddd854..30dfdae1338 100644 --- a/include/mysqld_default_groups.h +++ b/include/mysqld_default_groups.h @@ -5,4 +5,7 @@ const char *load_default_groups[]= { "mysqld", "server", MYSQL_BASE_VERSION, "mariadb", MARIADB_BASE_VERSION, "client-server", +#ifdef WITH_WSREP +"galera", +#endif 0, 0}; diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index 2025a8b811a..56b4eaf4202 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -11,6 +11,22 @@ # this is only for the mysqld standalone daemon [mysqld] +# +# * Galera-related settings +# +[galera] +# Mandatory settings +#wsrep_provider= +#wsrep_cluster_address= +#wsrep_slave_threads=1 +#binlog_format=row +#default_storage_engine=InnoDB +#innodb_autoinc_lock_mode=2 +#query_cache_size=0 +# +# Optional setting +#innodb_flush_log_at_trx_commit=2 + # this is only for embedded server [embedded] From 7b69cab89163a8d6e1a7a5cdcb66a66366136d7c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 22 Jul 2014 09:27:35 -0400 Subject: [PATCH 166/294] MDEV-4647: Crash on setting wsep system variables to default The variables' ON_CHECK functions relied on set_var's "value" member, which is NULL for SET ... =default. Fixed by using save_result instead. Also, for many wsrep variables, pointers to their respective global variables were used to provide default values. The patch fixes this by using appropriate macros and string literals. --- sql/sys_vars.cc | 28 +++++---- sql/wsrep_sst.cc | 75 +++++++++++------------- sql/wsrep_sst.h | 28 ++++++++- sql/wsrep_var.cc | 144 +++++++++++++++++++++-------------------------- sql/wsrep_var.h | 4 +- 5 files changed, 140 insertions(+), 139 deletions(-) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index aba051d214d..3abfec66364 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3691,8 +3691,7 @@ static Sys_var_tz Sys_time_zone( static Sys_var_charptr Sys_wsrep_provider( "wsrep_provider", "Path to replication provider library", PREALLOCATED GLOBAL_VAR(wsrep_provider), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER), - IN_FS_CHARSET, DEFAULT(wsrep_provider), - // IN_FS_CHARSET, DEFAULT(wsrep_provider_default), + IN_FS_CHARSET, DEFAULT(WSREP_NONE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_provider_check), ON_UPDATE(wsrep_provider_update)); @@ -3700,8 +3699,7 @@ static Sys_var_charptr Sys_wsrep_provider_options( "wsrep_provider_options", "provider specific options", PREALLOCATED GLOBAL_VAR(wsrep_provider_options), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER_OPTIONS), - IN_FS_CHARSET, DEFAULT(wsrep_provider_options), - NO_MUTEX_GUARD, NOT_IN_BINLOG, + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_provider_options_check), ON_UPDATE(wsrep_provider_options_update)); @@ -3714,7 +3712,7 @@ static Sys_var_charptr Sys_wsrep_data_home_dir( static Sys_var_charptr Sys_wsrep_cluster_name( "wsrep_cluster_name", "Name for the cluster", PREALLOCATED GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_cluster_name), + IN_FS_CHARSET, DEFAULT(WSREP_CLUSTER_NAME), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_cluster_name_check), ON_UPDATE(wsrep_cluster_name_update)); @@ -3724,7 +3722,7 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( "wsrep_cluster_address", "Address to initially connect to cluster", PREALLOCATED GLOBAL_VAR(wsrep_cluster_address), CMD_LINE(REQUIRED_ARG, OPT_WSREP_CLUSTER_ADDRESS), - IN_FS_CHARSET, DEFAULT(wsrep_cluster_address), + IN_FS_CHARSET, DEFAULT(""), &PLock_wsrep_slave_threads, NOT_IN_BINLOG, ON_CHECK(wsrep_cluster_address_check), ON_UPDATE(wsrep_cluster_address_update)); @@ -3732,21 +3730,21 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_node_name), - NO_MUTEX_GUARD, NOT_IN_BINLOG); + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + wsrep_node_name_check, wsrep_node_name_update); static Sys_var_charptr Sys_wsrep_node_address ( "wsrep_node_address", "Node address", PREALLOCATED GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_node_address), + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(wsrep_node_address_check), + ON_CHECK(wsrep_node_address_check), ON_UPDATE(wsrep_node_address_update)); static Sys_var_charptr Sys_wsrep_node_incoming_address( "wsrep_node_incoming_address", "Client connection address", PREALLOCATED GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), + IN_FS_CHARSET, DEFAULT(WSREP_NODE_INCOMING_AUTO), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_ulong Sys_wsrep_slave_threads( @@ -3794,7 +3792,7 @@ static Sys_var_mybool Sys_wsrep_drupal_282555_workaround( static Sys_var_charptr sys_wsrep_sst_method( "wsrep_sst_method", "State snapshot transfer method", GLOBAL_VAR(wsrep_sst_method),CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_sst_method), NO_MUTEX_GUARD, NOT_IN_BINLOG, + IN_FS_CHARSET, DEFAULT(WSREP_SST_DEFAULT), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_sst_method_check), ON_UPDATE(wsrep_sst_method_update)); @@ -3802,7 +3800,7 @@ static Sys_var_charptr Sys_wsrep_sst_receive_address( "wsrep_sst_receive_address", "Address where node is waiting for " "SST contact", GLOBAL_VAR(wsrep_sst_receive_address),CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(wsrep_sst_receive_address), NO_MUTEX_GUARD, + IN_FS_CHARSET, DEFAULT(WSREP_SST_ADDRESS_AUTO), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_sst_receive_address_check), ON_UPDATE(wsrep_sst_receive_address_update)); @@ -3810,7 +3808,7 @@ static Sys_var_charptr Sys_wsrep_sst_receive_address( static Sys_var_charptr Sys_wsrep_sst_auth( "wsrep_sst_auth", "Authentication for SST connection", PREALLOCATED GLOBAL_VAR(wsrep_sst_auth), CMD_LINE(REQUIRED_ARG, OPT_WSREP_SST_AUTH), - IN_FS_CHARSET, DEFAULT(wsrep_sst_auth), NO_MUTEX_GUARD, + IN_FS_CHARSET, DEFAULT(NULL), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_sst_auth_check), ON_UPDATE(wsrep_sst_auth_update)); @@ -3839,7 +3837,7 @@ static Sys_var_charptr Sys_wsrep_start_position ( "wsrep_start_position", "global transaction position to start from ", PREALLOCATED GLOBAL_VAR(wsrep_start_position), CMD_LINE(REQUIRED_ARG, OPT_WSREP_START_POSITION), - IN_FS_CHARSET, DEFAULT(wsrep_start_position), + IN_FS_CHARSET, DEFAULT(WSREP_START_POSITION_ZERO), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_start_position_check), ON_UPDATE(wsrep_start_position_update)); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index be9efa86873..d2263e3e171 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -31,32 +31,6 @@ extern const char wsrep_defaults_file[]; -#define WSREP_SST_OPT_ROLE "--role" -#define WSREP_SST_OPT_ADDR "--address" -#define WSREP_SST_OPT_AUTH "--auth" -#define WSREP_SST_OPT_DATA "--datadir" -#define WSREP_SST_OPT_CONF "--defaults-file" -#define WSREP_SST_OPT_PARENT "--parent" - -// mysqldump-specific options -#define WSREP_SST_OPT_USER "--user" -#define WSREP_SST_OPT_PSWD "--password" -#define WSREP_SST_OPT_HOST "--host" -#define WSREP_SST_OPT_PORT "--port" -#define WSREP_SST_OPT_LPORT "--local-port" - -// donor-specific -#define WSREP_SST_OPT_SOCKET "--socket" -#define WSREP_SST_OPT_GTID "--gtid" -#define WSREP_SST_OPT_BYPASS "--bypass" - -#define WSREP_SST_MYSQLDUMP "mysqldump" -#define WSREP_SST_RSYNC "rsync" -#define WSREP_SST_SKIP "skip" -#define WSREP_SST_DEFAULT WSREP_SST_RSYNC -#define WSREP_SST_ADDRESS_AUTO "AUTO" -#define WSREP_SST_AUTH_MASK "********" - const char* wsrep_sst_method = WSREP_SST_DEFAULT; const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; const char* wsrep_sst_donor = ""; @@ -68,17 +42,16 @@ my_bool wsrep_sst_donor_rejects_queries = FALSE; bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* c_str = NULL; - - if ((res = var->value->val_str(&str)) && - (c_str = res->c_ptr()) && - strlen(c_str) > 0) - return 0; - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_method", c_str ? c_str : "NULL"); + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length == 0 )) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); return 1; + } + + return 0; } bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) @@ -86,6 +59,7 @@ bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) return 0; } +// TODO: Improve address verification. static bool sst_receive_address_check (const char* str) { if (!strncasecmp(str, "127.0.0.1", strlen("127.0.0.1")) || @@ -99,15 +73,30 @@ static bool sst_receive_address_check (const char* str) bool wsrep_sst_receive_address_check (sys_var *self, THD* thd, set_var* var) { - const char* c_str = var->value->str_value.c_ptr(); + char addr_buf[FN_REFLEN]; - if (sst_receive_address_check (c_str)) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "wsrep_sst_receive_address", c_str ? c_str : "NULL"); - return 1; - } + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + { + goto err; + } - return 0; + memcpy(addr_buf, var->save_result.string_value.str, + var->save_result.string_value.length); + addr_buf[var->save_result.string_value.length]= 0; + + if (sst_receive_address_check(addr_buf)) + { + goto err; + } + + return 0; + +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); + return 1; } bool wsrep_sst_receive_address_update (sys_var *self, THD* thd, diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index dc7789f5a4e..ad02aa55114 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -16,7 +16,33 @@ #ifndef WSREP_SST_H #define WSREP_SST_H -#include // my_bool +#include // my_bool + +#define WSREP_SST_OPT_ROLE "--role" +#define WSREP_SST_OPT_ADDR "--address" +#define WSREP_SST_OPT_AUTH "--auth" +#define WSREP_SST_OPT_DATA "--datadir" +#define WSREP_SST_OPT_CONF "--defaults-file" +#define WSREP_SST_OPT_PARENT "--parent" + +// mysqldump-specific options +#define WSREP_SST_OPT_USER "--user" +#define WSREP_SST_OPT_PSWD "--password" +#define WSREP_SST_OPT_HOST "--host" +#define WSREP_SST_OPT_PORT "--port" +#define WSREP_SST_OPT_LPORT "--local-port" + +// donor-specific +#define WSREP_SST_OPT_SOCKET "--socket" +#define WSREP_SST_OPT_GTID "--gtid" +#define WSREP_SST_OPT_BYPASS "--bypass" + +#define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_RSYNC "rsync" +#define WSREP_SST_SKIP "skip" +#define WSREP_SST_DEFAULT WSREP_SST_RSYNC +#define WSREP_SST_ADDRESS_AUTO "AUTO" +#define WSREP_SST_AUTH_MASK "********" /* system variables */ extern const char* wsrep_sst_method; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 54d0b1cdfe6..a633b72bc0d 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -26,9 +26,6 @@ #include #include -#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" -#define WSREP_CLUSTER_NAME "my_wsrep_cluster" - const char* wsrep_provider = 0; const char* wsrep_provider_options = 0; const char* wsrep_cluster_address = 0; @@ -98,22 +95,22 @@ static int wsrep_start_position_verify (const char* start_str) bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* start_str = NULL; + char start_pos_buf[FN_REFLEN]; - if (!(res = var->value->val_str(&str))) goto err; + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + goto err; - start_str = res->c_ptr(); + memcpy(start_pos_buf, var->save_result.string_value.str, + var->save_result.string_value.length); + start_pos_buf[var->save_result.string_value.length]= 0; - if (!start_str) goto err; - - if (!wsrep_start_position_verify(start_str)) return 0; + if (!wsrep_start_position_verify(start_pos_buf)) return 0; err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - start_str ? start_str : "NULL"); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); return 1; } @@ -199,22 +196,22 @@ static int wsrep_provider_verify (const char* provider_str) bool wsrep_provider_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* provider_str = NULL; + char wsrep_provider_buf[FN_REFLEN]; - if (!(res = var->value->val_str(&str))) goto err; + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + goto err; - provider_str = res->c_ptr(); + memcpy(wsrep_provider_buf, var->save_result.string_value.str, + var->save_result.string_value.length); + wsrep_provider_buf[var->save_result.string_value.length]= 0; - if (!provider_str) goto err; - - if (!wsrep_provider_verify(provider_str)) return 0; + if (!wsrep_provider_verify(wsrep_provider_buf)) return 0; err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - provider_str ? provider_str : "NULL"); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); return 1; } @@ -309,21 +306,23 @@ static int wsrep_cluster_address_verify (const char* cluster_address_str) bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* cluster_address_str = NULL; + char addr_buf[FN_REFLEN]; - if (!(res = var->value->val_str(&str))) goto err; + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + goto err; - cluster_address_str = res->c_ptr(); + memcpy(addr_buf, var->save_result.string_value.str, + var->save_result.string_value.length); + addr_buf[var->save_result.string_value.length]= 0; - if (!wsrep_cluster_address_verify(cluster_address_str)) return 0; + if (!wsrep_cluster_address_verify(addr_buf)) return 0; err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - cluster_address_str ? cluster_address_str : "NULL"); - return 1 ; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); + return 1; } bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) @@ -363,25 +362,18 @@ void wsrep_cluster_address_init (const char* value) wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; } +/* wsrep_cluster_name cannot be NULL or an empty string. */ bool wsrep_cluster_name_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* cluster_name_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - cluster_name_str = res->c_ptr(); - - if (!cluster_name_str || strlen(cluster_name_str) == 0) goto err; - + if (!var->save_result.string_value.str || + (var->save_result.string_value.length == 0)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + (var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL")); + return 1; + } return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - cluster_name_str ? cluster_name_str : "NULL"); - return 1; } bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type) @@ -391,23 +383,15 @@ bool wsrep_cluster_name_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_node_name_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* node_name_str = NULL; - - if (!(res = var->value->val_str(&str))) goto err; - - node_name_str = res->c_ptr(); - - if (!node_name_str || strlen(node_name_str) == 0) goto err; - + // TODO: for now 'allow' 0-length string to be valid (default) + if (!var->save_result.string_value.str) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + (var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL")); + return 1; + } return 0; - - err: - - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - node_name_str ? node_name_str : "NULL"); - return 1; } bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type) @@ -418,22 +402,23 @@ bool wsrep_node_name_update (sys_var *self, THD* thd, enum_var_type type) // TODO: do something more elaborate, like checking connectivity bool wsrep_node_address_check (sys_var *self, THD* thd, set_var* var) { - char buff[FN_REFLEN]; - String str(buff, sizeof(buff), system_charset_info), *res; - const char* node_address_str = NULL; + char addr_buf[FN_REFLEN]; - if (!(res = var->value->val_str(&str))) goto err; + if ((! var->save_result.string_value.str) || + (var->save_result.string_value.length > (FN_REFLEN - 1))) // safety + goto err; - node_address_str = res->c_ptr(); - - if (!node_address_str || strlen(node_address_str) == 0) goto err; + memcpy(addr_buf, var->save_result.string_value.str, + var->save_result.string_value.length); + addr_buf[var->save_result.string_value.length]= 0; + // TODO: for now 'allow' 0-length string to be valid (default) return 0; - err: - +err: my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, - node_address_str ? node_address_str : "NULL"); + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); return 1; } @@ -453,7 +438,8 @@ void wsrep_node_address_init (const char* value) bool wsrep_slave_threads_check (sys_var *self, THD* thd, set_var* var) { mysql_mutex_lock(&LOCK_wsrep_slave_threads); - wsrep_slave_count_change += (var->value->val_int() - wsrep_slave_threads); + wsrep_slave_count_change += (var->save_result.ulonglong_value - + wsrep_slave_threads); mysql_mutex_unlock(&LOCK_wsrep_slave_threads); return 0; @@ -471,7 +457,7 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) { - bool new_wsrep_desync = var->value->val_bool(); + bool new_wsrep_desync= (bool) var->save_result.ulonglong_value; if (wsrep_desync == new_wsrep_desync) { if (new_wsrep_desync) { push_warning (thd, MYSQL_ERROR::WARN_LEVEL_WARN, diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index b69f670a14b..2a5e94b6724 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -16,7 +16,9 @@ #ifndef WSREP_VAR_H #define WSREP_VAR_H -#define WSREP_NODE_INCOMING_AUTO "AUTO" +#define WSREP_CLUSTER_NAME "my_wsrep_cluster" +#define WSREP_NODE_INCOMING_AUTO "AUTO" +#define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" // MySQL variables funcs From 79750be18783efb7594a8dd011086c9d3a680983 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 22 Jul 2014 09:41:10 -0400 Subject: [PATCH 167/294] MDEV-6377 : Test cases for wsrep system variables. --- mysql-test/suite/sys_vars/r/all_vars.result | 36 ----------- .../wsrep_auto_increment_control_basic.result | 45 +++++++++++++ .../r/wsrep_causal_reads_basic.result | 50 +++++++++++++++ .../r/wsrep_certify_nonpk_basic.result | 45 +++++++++++++ .../r/wsrep_cluster_address_basic.result | 54 ++++++++++++++++ .../r/wsrep_cluster_name_basic.result | 43 +++++++++++++ .../r/wsrep_convert_lock_to_trx_basic.result | 45 +++++++++++++ .../r/wsrep_data_home_dir_basic.result | 48 ++++++++++++++ .../sys_vars/r/wsrep_dbug_option_basic.result | 47 ++++++++++++++ .../suite/sys_vars/r/wsrep_debug_basic.result | 45 +++++++++++++ .../sys_vars/r/wsrep_desync_basic.result | 52 +++++++++++++++ ...srep_drupal_282555_workaround_basic.result | 45 +++++++++++++ .../r/wsrep_forced_binlog_format_basic.result | 51 +++++++++++++++ .../r/wsrep_load_data_splitting_basic.result | 45 +++++++++++++ .../r/wsrep_log_conflicts_basic.result | 45 +++++++++++++ .../sys_vars/r/wsrep_max_ws_rows_basic.result | 53 +++++++++++++++ .../sys_vars/r/wsrep_max_ws_size_basic.result | 58 +++++++++++++++++ ...srep_mysql_replication_bundle_basic.result | 52 +++++++++++++++ .../r/wsrep_node_address_basic.result | 49 ++++++++++++++ .../wsrep_node_incoming_address_basic.result | 56 ++++++++++++++++ .../sys_vars/r/wsrep_node_name_basic.result | 48 ++++++++++++++ .../sys_vars/r/wsrep_notify_cmd_basic.result | 47 ++++++++++++++ .../suite/sys_vars/r/wsrep_on_basic.result | 50 +++++++++++++++ .../sys_vars/r/wsrep_osu_method_basic.result | 60 +++++++++++++++++ .../sys_vars/r/wsrep_provider_basic.result | 40 ++++++++++++ .../r/wsrep_provider_options_basic.result | 48 ++++++++++++++ .../sys_vars/r/wsrep_recover_basic.result | 22 +++++++ .../r/wsrep_replicate_myisam_basic.result | 31 +++++++++ .../r/wsrep_restart_slave_basic.result | 31 +++++++++ .../r/wsrep_retry_autocommit_basic.result | 63 ++++++++++++++++++ .../r/wsrep_slave_threads_basic.result | 49 ++++++++++++++ .../sys_vars/r/wsrep_sst_auth_basic.result | 52 +++++++++++++++ .../sys_vars/r/wsrep_sst_donor_basic.result | 50 +++++++++++++++ ...rep_sst_donor_rejects_queries_basic.result | 45 +++++++++++++ .../sys_vars/r/wsrep_sst_method_basic.result | 54 ++++++++++++++++ .../r/wsrep_sst_receive_address_basic.result | 64 +++++++++++++++++++ .../r/wsrep_start_position_basic.result | 57 +++++++++++++++++ .../t/wsrep_auto_increment_control_basic.test | 42 ++++++++++++ .../sys_vars/t/wsrep_causal_reads_basic.test | 45 +++++++++++++ .../sys_vars/t/wsrep_certify_nonpk_basic.test | 42 ++++++++++++ .../t/wsrep_cluster_address_basic.test | 48 ++++++++++++++ .../sys_vars/t/wsrep_cluster_name_basic.test | 40 ++++++++++++ .../t/wsrep_convert_lock_to_trx_basic.test | 42 ++++++++++++ .../sys_vars/t/wsrep_data_home_dir_basic.test | 41 ++++++++++++ .../sys_vars/t/wsrep_dbug_option_basic.test | 42 ++++++++++++ .../suite/sys_vars/t/wsrep_debug_basic.test | 42 ++++++++++++ .../suite/sys_vars/t/wsrep_desync_basic.test | 49 ++++++++++++++ .../wsrep_drupal_282555_workaround_basic.test | 42 ++++++++++++ .../t/wsrep_forced_binlog_format_basic.test | 46 +++++++++++++ .../t/wsrep_load_data_splitting_basic.test | 42 ++++++++++++ .../sys_vars/t/wsrep_log_conflicts_basic.test | 42 ++++++++++++ .../sys_vars/t/wsrep_max_ws_rows_basic.test | 45 +++++++++++++ .../sys_vars/t/wsrep_max_ws_size_basic.test | 45 +++++++++++++ .../wsrep_mysql_replication_bundle_basic.test | 45 +++++++++++++ .../sys_vars/t/wsrep_node_address_basic.test | 45 +++++++++++++ .../t/wsrep_node_incoming_address_basic.test | 47 ++++++++++++++ .../sys_vars/t/wsrep_node_name_basic.test | 44 +++++++++++++ .../sys_vars/t/wsrep_notify_cmd_basic.test | 43 +++++++++++++ .../suite/sys_vars/t/wsrep_on_basic.test | 45 +++++++++++++ .../sys_vars/t/wsrep_osu_method_basic.test | 50 +++++++++++++++ .../sys_vars/t/wsrep_provider_basic.test | 39 +++++++++++ .../t/wsrep_provider_options_basic.test | 44 +++++++++++++ .../suite/sys_vars/t/wsrep_recover_basic.test | 26 ++++++++ .../t/wsrep_replicate_myisam_basic.test | 36 +++++++++++ .../sys_vars/t/wsrep_restart_slave_basic.test | 36 +++++++++++ .../t/wsrep_retry_autocommit_basic.test | 52 +++++++++++++++ .../sys_vars/t/wsrep_slave_threads_basic.test | 43 +++++++++++++ .../sys_vars/t/wsrep_sst_auth_basic.test | 45 +++++++++++++ .../sys_vars/t/wsrep_sst_donor_basic.test | 43 +++++++++++++ ...wsrep_sst_donor_rejects_queries_basic.test | 42 ++++++++++++ .../sys_vars/t/wsrep_sst_method_basic.test | 47 ++++++++++++++ .../t/wsrep_sst_receive_address_basic.test | 53 +++++++++++++++ .../t/wsrep_start_position_basic.test | 56 ++++++++++++++++ 73 files changed, 3315 insertions(+), 36 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/wsrep_auto_increment_control_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_causal_reads_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_certify_nonpk_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_cluster_address_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_cluster_name_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_convert_lock_to_trx_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_dbug_option_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_debug_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_desync_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_drupal_282555_workaround_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_forced_binlog_format_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_log_conflicts_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_max_ws_rows_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_max_ws_size_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_mysql_replication_bundle_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_node_address_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_node_incoming_address_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_notify_cmd_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_on_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_provider_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_recover_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_replicate_myisam_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_restart_slave_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_retry_autocommit_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sst_auth_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sst_donor_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sst_donor_rejects_queries_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_start_position_basic.result create mode 100644 mysql-test/suite/sys_vars/t/wsrep_auto_increment_control_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_causal_reads_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_certify_nonpk_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_cluster_address_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_cluster_name_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_convert_lock_to_trx_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_dbug_option_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_debug_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_desync_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_drupal_282555_workaround_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_forced_binlog_format_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_load_data_splitting_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_log_conflicts_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_max_ws_rows_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_max_ws_size_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_mysql_replication_bundle_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_node_address_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_node_incoming_address_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_notify_cmd_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_on_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_provider_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_recover_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_replicate_myisam_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_restart_slave_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_retry_autocommit_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sst_auth_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sst_donor_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sst_donor_rejects_queries_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_start_position_basic.test diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index d7a72989d81..aa40005f5e2 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -11,41 +11,5 @@ select distinct variable_name as `there should be *no* variables listed below:` left join t1 on variable_name=test_name where test_name is null; there should be *no* variables listed below: innodb_disallow_writes -wsrep_auto_increment_control -wsrep_causal_reads -wsrep_certify_nonpk -wsrep_cluster_address -wsrep_cluster_name -wsrep_convert_lock_to_trx -wsrep_data_home_dir -wsrep_dbug_option -wsrep_debug -wsrep_desync -wsrep_drupal_282555_workaround -wsrep_forced_binlog_format -wsrep_load_data_splitting -wsrep_log_conflicts -wsrep_max_ws_rows -wsrep_max_ws_size -wsrep_mysql_replication_bundle -wsrep_node_address -wsrep_node_incoming_address -wsrep_node_name -wsrep_notify_cmd -wsrep_on -wsrep_osu_method -wsrep_provider -wsrep_provider_options -wsrep_recover -wsrep_replicate_myisam -wsrep_restart_slave -wsrep_retry_autocommit -wsrep_slave_threads -wsrep_sst_auth -wsrep_sst_donor -wsrep_sst_donor_rejects_queries -wsrep_sst_method -wsrep_sst_receive_address -wsrep_start_position drop table t1; drop table t2; diff --git a/mysql-test/suite/sys_vars/r/wsrep_auto_increment_control_basic.result b/mysql-test/suite/sys_vars/r/wsrep_auto_increment_control_basic.result new file mode 100644 index 00000000000..2608e58b986 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_auto_increment_control_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_auto_increment_control +# +# save the initial value +SET @wsrep_auto_increment_control_global_saved = @@global.wsrep_auto_increment_control; +# default +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +1 + +# scope +SELECT @@session.wsrep_auto_increment_control; +ERROR HY000: Variable 'wsrep_auto_increment_control' is a GLOBAL variable +SET @@global.wsrep_auto_increment_control=OFF; +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +0 +SET @@global.wsrep_auto_increment_control=ON; +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +1 + +# valid values +SET @@global.wsrep_auto_increment_control='OFF'; +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +0 +SET @@global.wsrep_auto_increment_control=ON; +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +1 +SET @@global.wsrep_auto_increment_control=default; +SELECT @@global.wsrep_auto_increment_control; +@@global.wsrep_auto_increment_control +1 + +# invalid values +SET @@global.wsrep_auto_increment_control=NULL; +ERROR 42000: Variable 'wsrep_auto_increment_control' can't be set to the value of 'NULL' +SET @@global.wsrep_auto_increment_control='junk'; +ERROR 42000: Variable 'wsrep_auto_increment_control' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_auto_increment_control = @wsrep_auto_increment_control_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_causal_reads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_causal_reads_basic.result new file mode 100644 index 00000000000..501117dda9f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_causal_reads_basic.result @@ -0,0 +1,50 @@ +# +# wsrep_causal_reads +# +# save the initial values +SET @wsrep_causal_reads_global_saved = @@global.wsrep_causal_reads; +SET @wsrep_causal_reads_session_saved = @@session.wsrep_causal_reads; +# default +SELECT @@global.wsrep_causal_reads; +@@global.wsrep_causal_reads +0 +SELECT @@session.wsrep_causal_reads; +@@session.wsrep_causal_reads +0 + +# scope and valid values +SET @@global.wsrep_causal_reads=OFF; +SELECT @@global.wsrep_causal_reads; +@@global.wsrep_causal_reads +0 +SET @@global.wsrep_causal_reads=ON; +SELECT @@global.wsrep_causal_reads; +@@global.wsrep_causal_reads +1 +SET @@session.wsrep_causal_reads=OFF; +SELECT @@session.wsrep_causal_reads; +@@session.wsrep_causal_reads +0 +SET @@session.wsrep_causal_reads=ON; +SELECT @@session.wsrep_causal_reads; +@@session.wsrep_causal_reads +1 +SET @@session.wsrep_causal_reads=default; +SELECT @@session.wsrep_causal_reads; +@@session.wsrep_causal_reads +1 + +# invalid values +SET @@global.wsrep_causal_reads=NULL; +ERROR 42000: Variable 'wsrep_causal_reads' can't be set to the value of 'NULL' +SET @@global.wsrep_causal_reads='junk'; +ERROR 42000: Variable 'wsrep_causal_reads' can't be set to the value of 'junk' +SET @@session.wsrep_causal_reads=NULL; +ERROR 42000: Variable 'wsrep_causal_reads' can't be set to the value of 'NULL' +SET @@session.wsrep_causal_reads='junk'; +ERROR 42000: Variable 'wsrep_causal_reads' can't be set to the value of 'junk' + +# restore the initial values +SET @@global.wsrep_causal_reads = @wsrep_causal_reads_global_saved; +SET @@session.wsrep_causal_reads = @wsrep_causal_reads_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_certify_nonpk_basic.result b/mysql-test/suite/sys_vars/r/wsrep_certify_nonpk_basic.result new file mode 100644 index 00000000000..7200d14f75f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_certify_nonpk_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_certify_nonpk +# +# save the initial value +SET @wsrep_certify_nonpk_global_saved = @@global.wsrep_certify_nonpk; +# default +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +1 + +# scope +SELECT @@session.wsrep_certify_nonpk; +ERROR HY000: Variable 'wsrep_certify_nonPK' is a GLOBAL variable +SET @@global.wsrep_certify_nonpk=OFF; +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +0 +SET @@global.wsrep_certify_nonpk=ON; +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +1 + +# valid values +SET @@global.wsrep_certify_nonpk='OFF'; +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +0 +SET @@global.wsrep_certify_nonpk=ON; +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +1 +SET @@global.wsrep_certify_nonpk=default; +SELECT @@global.wsrep_certify_nonpk; +@@global.wsrep_certify_nonpk +1 + +# invalid values +SET @@global.wsrep_certify_nonpk=NULL; +ERROR 42000: Variable 'wsrep_certify_nonPK' can't be set to the value of 'NULL' +SET @@global.wsrep_certify_nonpk='junk'; +ERROR 42000: Variable 'wsrep_certify_nonPK' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_certify_nonpk = @wsrep_certify_nonpk_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_cluster_address_basic.result b/mysql-test/suite/sys_vars/r/wsrep_cluster_address_basic.result new file mode 100644 index 00000000000..8497e220523 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_cluster_address_basic.result @@ -0,0 +1,54 @@ +# +# wsrep_cluster_address +# +call mtr.add_suppression("safe_mutex: Found wrong usage of mutex.*"); +# save the initial value +SET @wsrep_cluster_address_global_saved = @@global.wsrep_cluster_address; +# default +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address + + +# scope +SELECT @@session.wsrep_cluster_address; +ERROR HY000: Variable 'wsrep_cluster_address' is a GLOBAL variable +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address + + +# valid values +SET @@global.wsrep_cluster_address='127.0.0.1'; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +127.0.0.1 +SET @@global.wsrep_cluster_address=AUTO; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +AUTO +SET @@global.wsrep_cluster_address=default; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address + + +# invalid values +SET @@global.wsrep_node_address=NULL; +ERROR 42000: Variable 'wsrep_node_address' can't be set to the value of 'NULL' +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address + +SET @@global.wsrep_cluster_address=ON; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +ON +SET @@global.wsrep_cluster_address='OFF'; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +OFF +SET @@global.wsrep_cluster_address='junk'; +SELECT @@global.wsrep_cluster_address; +@@global.wsrep_cluster_address +junk + +# restore the initial value +SET @@global.wsrep_cluster_address = @wsrep_cluster_address_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_cluster_name_basic.result b/mysql-test/suite/sys_vars/r/wsrep_cluster_name_basic.result new file mode 100644 index 00000000000..29a2d966489 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_cluster_name_basic.result @@ -0,0 +1,43 @@ +# +# wsrep_cluster_name +# +# save the initial value +SET @wsrep_cluster_name_global_saved = @@global.wsrep_cluster_name; +# default +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +my_wsrep_cluster + +# scope +SELECT @@session.wsrep_cluster_name; +ERROR HY000: Variable 'wsrep_cluster_name' is a GLOBAL variable +SET @@global.wsrep_cluster_name='my_galera_cluster'; +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +my_galera_cluster + +# valid values +SET @@global.wsrep_cluster_name='my_quoted_galera_cluster'; +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +my_quoted_galera_cluster +SET @@global.wsrep_cluster_name=my_unquoted_cluster; +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +my_unquoted_cluster +SET @@global.wsrep_cluster_name=OFF; +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +OFF +SET @@global.wsrep_cluster_name=default; +SELECT @@global.wsrep_cluster_name; +@@global.wsrep_cluster_name +my_wsrep_cluster + +# invalid values +SET @@global.wsrep_cluster_name=NULL; +ERROR 42000: Variable 'wsrep_cluster_name' can't be set to the value of 'NULL' + +# restore the initial value +SET @@global.wsrep_cluster_name = @wsrep_cluster_name_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_convert_lock_to_trx_basic.result b/mysql-test/suite/sys_vars/r/wsrep_convert_lock_to_trx_basic.result new file mode 100644 index 00000000000..80210c4c4b6 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_convert_lock_to_trx_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_convert_lock_to_trx +# +# save the initial value +SET @wsrep_convert_lock_to_trx_global_saved = @@global.wsrep_convert_lock_to_trx; +# default +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +0 + +# scope +SELECT @@session.wsrep_convert_lock_to_trx; +ERROR HY000: Variable 'wsrep_convert_LOCK_to_trx' is a GLOBAL variable +SET @@global.wsrep_convert_lock_to_trx=OFF; +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +0 +SET @@global.wsrep_convert_lock_to_trx=ON; +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +1 + +# valid values +SET @@global.wsrep_convert_lock_to_trx='OFF'; +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +0 +SET @@global.wsrep_convert_lock_to_trx=ON; +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +1 +SET @@global.wsrep_convert_lock_to_trx=default; +SELECT @@global.wsrep_convert_lock_to_trx; +@@global.wsrep_convert_lock_to_trx +0 + +# invalid values +SET @@global.wsrep_convert_lock_to_trx=NULL; +ERROR 42000: Variable 'wsrep_convert_LOCK_to_trx' can't be set to the value of 'NULL' +SET @@global.wsrep_convert_lock_to_trx='junk'; +ERROR 42000: Variable 'wsrep_convert_LOCK_to_trx' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_convert_lock_to_trx = @wsrep_convert_lock_to_trx_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result b/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result new file mode 100644 index 00000000000..044ef8bf3bc --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result @@ -0,0 +1,48 @@ +# +# wsrep_data_home_dir (readonly) +# +# default +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + + +# scope +SELECT @@session.wsrep_data_home_dir; +ERROR HY000: Variable 'wsrep_data_home_dir' is a GLOBAL variable +SET @@global.wsrep_data_home_dir='/tmp/data'; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + + +# valid values +SET @@global.wsrep_data_home_dir='/tmp/data'; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + +SET @@global.wsrep_data_home_dir=junk-dir; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + +SET @@global.wsrep_data_home_dir=junk/dir; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + +SET @@global.wsrep_data_home_dir=OFF; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + +SET @@global.wsrep_data_home_dir=default; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +SELECT @@global.wsrep_data_home_dir; +@@global.wsrep_data_home_dir + + +# invalid values +SET @@global.wsrep_data_home_dir=NULL; +ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_dbug_option_basic.result b/mysql-test/suite/sys_vars/r/wsrep_dbug_option_basic.result new file mode 100644 index 00000000000..2092d54681e --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_dbug_option_basic.result @@ -0,0 +1,47 @@ +# +# wsrep_dbug_option +# +# save the initial value +SET @wsrep_dbug_option_global_saved = @@global.wsrep_dbug_option; +# default +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option + + +# scope +SELECT @@session.wsrep_dbug_option; +ERROR HY000: Variable 'wsrep_dbug_option' is a GLOBAL variable +SET @@global.wsrep_dbug_option='test-dbug-string'; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option +test-dbug-string + +# valid values +SET @@global.wsrep_dbug_option='quoted-dbug-string'; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option +quoted-dbug-string +SET @@global.wsrep_dbug_option=unquoted_dbug_string; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option +unquoted_dbug_string +SET @@global.wsrep_dbug_option=OFF; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option +OFF +SET @@global.wsrep_dbug_option=NULL; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option +NULL +SET @@global.wsrep_dbug_option=default; +SELECT @@global.wsrep_dbug_option; +@@global.wsrep_dbug_option + + +# invalid values +SET @@global.wsrep_dbug_option=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_dbug_option' + +# restore the initial value +SET @@global.wsrep_dbug_option = @wsrep_dbug_option_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result b/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result new file mode 100644 index 00000000000..96c262c110c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_debug +# +# save the initial value +SET @wsrep_debug_global_saved = @@global.wsrep_debug; +# default +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +0 + +# scope +SELECT @@session.wsrep_debug; +ERROR HY000: Variable 'wsrep_debug' is a GLOBAL variable +SET @@global.wsrep_debug=OFF; +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +0 +SET @@global.wsrep_debug=ON; +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +1 + +# valid values +SET @@global.wsrep_debug='OFF'; +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +0 +SET @@global.wsrep_debug=ON; +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +1 +SET @@global.wsrep_debug=default; +SELECT @@global.wsrep_debug; +@@global.wsrep_debug +0 + +# invalid values +SET @@global.wsrep_debug=NULL; +ERROR 42000: Variable 'wsrep_debug' can't be set to the value of 'NULL' +SET @@global.wsrep_debug='junk'; +ERROR 42000: Variable 'wsrep_debug' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_debug = @wsrep_debug_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_desync_basic.result b/mysql-test/suite/sys_vars/r/wsrep_desync_basic.result new file mode 100644 index 00000000000..69599c4b47a --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_desync_basic.result @@ -0,0 +1,52 @@ +# +# wsrep_desync +# +call mtr.add_suppression("WSREP: SET desync failed 9 for SET @@global.wsrep_desync=ON"); +# save the initial value +SET @wsrep_desync_global_saved = @@global.wsrep_desync; +# default +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +0 + +# scope +SELECT @@session.wsrep_desync; +ERROR HY000: Variable 'wsrep_desync' is a GLOBAL variable +SET @@global.wsrep_desync=OFF; +Warnings: +Warning 1231 'wsrep_desync' is already OFF. +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +0 +SET @@global.wsrep_desync=ON; +ERROR HY000: Operation 'desync' failed for SET @@global.wsrep_desync=ON +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +1 + +# valid values +SET @@global.wsrep_desync='OFF'; +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +0 +SET @@global.wsrep_desync=ON; +ERROR HY000: Operation 'desync' failed for SET @@global.wsrep_desync=ON +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +1 +SET @@global.wsrep_desync=default; +SELECT @@global.wsrep_desync; +@@global.wsrep_desync +0 + +# invalid values +SET @@global.wsrep_desync=NULL; +ERROR 42000: Variable 'wsrep_desync' can't be set to the value of 'NULL' +SET @@global.wsrep_desync='junk'; +ERROR 42000: Variable 'wsrep_desync' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_desync = @wsrep_desync_global_saved; +Warnings: +Warning 1231 'wsrep_desync' is already OFF. +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_drupal_282555_workaround_basic.result b/mysql-test/suite/sys_vars/r/wsrep_drupal_282555_workaround_basic.result new file mode 100644 index 00000000000..52bfc01e810 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_drupal_282555_workaround_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_drupal_282555_workaround +# +# save the initial value +SET @wsrep_drupal_282555_workaround_global_saved = @@global.wsrep_drupal_282555_workaround; +# default +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +0 + +# scope +SELECT @@session.wsrep_drupal_282555_workaround; +ERROR HY000: Variable 'wsrep_drupal_282555_workaround' is a GLOBAL variable +SET @@global.wsrep_drupal_282555_workaround=OFF; +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +0 +SET @@global.wsrep_drupal_282555_workaround=ON; +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +1 + +# valid values +SET @@global.wsrep_drupal_282555_workaround='OFF'; +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +0 +SET @@global.wsrep_drupal_282555_workaround=ON; +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +1 +SET @@global.wsrep_drupal_282555_workaround=default; +SELECT @@global.wsrep_drupal_282555_workaround; +@@global.wsrep_drupal_282555_workaround +0 + +# invalid values +SET @@global.wsrep_drupal_282555_workaround=NULL; +ERROR 42000: Variable 'wsrep_drupal_282555_workaround' can't be set to the value of 'NULL' +SET @@global.wsrep_drupal_282555_workaround='junk'; +ERROR 42000: Variable 'wsrep_drupal_282555_workaround' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_drupal_282555_workaround = @wsrep_drupal_282555_workaround_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_forced_binlog_format_basic.result b/mysql-test/suite/sys_vars/r/wsrep_forced_binlog_format_basic.result new file mode 100644 index 00000000000..3cf5ffcaf4e --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_forced_binlog_format_basic.result @@ -0,0 +1,51 @@ +# +# wsrep_forced_binlog_format +# +# save the initial value +SET @wsrep_forced_binlog_format_global_saved = @@global.wsrep_forced_binlog_format; +# default +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +NONE + +# scope +SELECT @@session.wsrep_forced_binlog_format; +ERROR HY000: Variable 'wsrep_forced_binlog_format' is a GLOBAL variable +SET @@global.wsrep_forced_binlog_format=STATEMENT; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +STATEMENT + +# valid values +SET @@global.wsrep_forced_binlog_format=STATEMENT; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +STATEMENT +SET @@global.wsrep_forced_binlog_format=ROW; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +ROW +SET @@global.wsrep_forced_binlog_format=MIXED; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +MIXED +SET @@global.wsrep_forced_binlog_format=NONE; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +NONE +SET @@global.wsrep_forced_binlog_format=default; +SELECT @@global.wsrep_forced_binlog_format; +@@global.wsrep_forced_binlog_format +NONE + +# invalid values +SET @@global.wsrep_forced_binlog_format=NULL; +ERROR 42000: Variable 'wsrep_forced_binlog_format' can't be set to the value of 'NULL' +SET @@global.wsrep_forced_binlog_format='junk'; +ERROR 42000: Variable 'wsrep_forced_binlog_format' can't be set to the value of 'junk' +SET @@global.wsrep_forced_binlog_format=ON; +ERROR 42000: Variable 'wsrep_forced_binlog_format' can't be set to the value of 'ON' + +# restore the initial value +SET @@global.wsrep_forced_binlog_format = @wsrep_forced_binlog_format_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result new file mode 100644 index 00000000000..687934a7705 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_load_data_splitting +# +# save the initial value +SET @wsrep_load_data_splitting_global_saved = @@global.wsrep_load_data_splitting; +# default +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +1 + +# scope +SELECT @@session.wsrep_load_data_splitting; +ERROR HY000: Variable 'wsrep_load_data_splitting' is a GLOBAL variable +SET @@global.wsrep_load_data_splitting=OFF; +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +0 +SET @@global.wsrep_load_data_splitting=ON; +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +1 + +# valid values +SET @@global.wsrep_load_data_splitting='OFF'; +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +0 +SET @@global.wsrep_load_data_splitting=ON; +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +1 +SET @@global.wsrep_load_data_splitting=default; +SELECT @@global.wsrep_load_data_splitting; +@@global.wsrep_load_data_splitting +1 + +# invalid values +SET @@global.wsrep_load_data_splitting=NULL; +ERROR 42000: Variable 'wsrep_load_data_splitting' can't be set to the value of 'NULL' +SET @@global.wsrep_load_data_splitting='junk'; +ERROR 42000: Variable 'wsrep_load_data_splitting' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_load_data_splitting = @wsrep_load_data_splitting_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_log_conflicts_basic.result b/mysql-test/suite/sys_vars/r/wsrep_log_conflicts_basic.result new file mode 100644 index 00000000000..4d577daa904 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_log_conflicts_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_log_conflicts +# +# save the initial value +SET @wsrep_log_conflicts_global_saved = @@global.wsrep_log_conflicts; +# default +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +0 + +# scope +SELECT @@session.wsrep_log_conflicts; +ERROR HY000: Variable 'wsrep_log_conflicts' is a GLOBAL variable +SET @@global.wsrep_log_conflicts=OFF; +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +0 +SET @@global.wsrep_log_conflicts=ON; +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +1 + +# valid values +SET @@global.wsrep_log_conflicts='OFF'; +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +0 +SET @@global.wsrep_log_conflicts=ON; +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +1 +SET @@global.wsrep_log_conflicts=default; +SELECT @@global.wsrep_log_conflicts; +@@global.wsrep_log_conflicts +0 + +# invalid values +SET @@global.wsrep_log_conflicts=NULL; +ERROR 42000: Variable 'wsrep_log_conflicts' can't be set to the value of 'NULL' +SET @@global.wsrep_log_conflicts='junk'; +ERROR 42000: Variable 'wsrep_log_conflicts' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_log_conflicts = @wsrep_log_conflicts_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_max_ws_rows_basic.result b/mysql-test/suite/sys_vars/r/wsrep_max_ws_rows_basic.result new file mode 100644 index 00000000000..15438a2afd5 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_max_ws_rows_basic.result @@ -0,0 +1,53 @@ +# +# wsrep_max_ws_rows +# +# save the initial value +SET @wsrep_max_ws_rows_global_saved = @@global.wsrep_max_ws_rows; +# default +SELECT @@global.wsrep_max_ws_rows; +@@global.wsrep_max_ws_rows +131072 + +# scope +SELECT @@session.wsrep_max_ws_rows; +ERROR HY000: Variable 'wsrep_max_ws_rows' is a GLOBAL variable +SET @@global.wsrep_max_ws_rows=1; +SELECT @@global.wsrep_max_ws_rows; +@@global.wsrep_max_ws_rows +1 + +# valid values +SET @@global.wsrep_max_ws_rows=131072; +SELECT @@global.wsrep_max_ws_rows; +@@global.wsrep_max_ws_rows +131072 +SET @@global.wsrep_max_ws_rows=131073; +SELECT @@global.wsrep_max_ws_rows; +@@global.wsrep_max_ws_rows +131073 +SET @@global.wsrep_max_ws_rows=0; +Warnings: +Warning 1292 Truncated incorrect wsrep_max_ws_rows value: '0' +SELECT @@global.wsrep_max_ws_rows; +@@global.wsrep_max_ws_rows +1 +SET @@global.wsrep_max_ws_rows=default; +SELECT @global.wsrep_max_ws_rows; +@global.wsrep_max_ws_rows +NULL + +# invalid values +SET @@global.wsrep_max_ws_rows=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_max_ws_rows' +SET @@global.wsrep_max_ws_rows='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_max_ws_rows' +SET @@global.wsrep_max_ws_rows=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_max_ws_rows value: '-1' +SELECT @global.wsrep_max_ws_rows; +@global.wsrep_max_ws_rows +NULL + +# restore the initial value +SET @@global.wsrep_max_ws_rows = @wsrep_max_ws_rows_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_max_ws_size_basic.result b/mysql-test/suite/sys_vars/r/wsrep_max_ws_size_basic.result new file mode 100644 index 00000000000..26d8d823a5c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_max_ws_size_basic.result @@ -0,0 +1,58 @@ +# +# wsrep_max_ws_size +# +# save the initial value +SET @wsrep_max_ws_size_global_saved = @@global.wsrep_max_ws_size; +# default +SELECT @@global.wsrep_max_ws_size; +@@global.wsrep_max_ws_size +1073741824 + +# scope +SELECT @@session.wsrep_max_ws_size; +ERROR HY000: Variable 'wsrep_max_ws_size' is a GLOBAL variable +SET @@global.wsrep_max_ws_size=1; +Warnings: +Warning 1292 Truncated incorrect wsrep_max_ws_size value: '1' +SELECT @@global.wsrep_max_ws_size; +@@global.wsrep_max_ws_size +1024 + +# valid values +SET @@global.wsrep_max_ws_size=1073741824; +SELECT @@global.wsrep_max_ws_size; +@@global.wsrep_max_ws_size +1073741824 +SET @@global.wsrep_max_ws_size=1073741825; +SELECT @@global.wsrep_max_ws_size; +@@global.wsrep_max_ws_size +1073741825 +SET @@global.wsrep_max_ws_size=0; +Warnings: +Warning 1292 Truncated incorrect wsrep_max_ws_size value: '0' +SELECT @@global.wsrep_max_ws_size; +@@global.wsrep_max_ws_size +1024 +SET @@global.wsrep_max_ws_size=default; +SELECT @global.wsrep_max_ws_size; +@global.wsrep_max_ws_size +NULL + +# invalid values +SET @@global.wsrep_max_ws_size=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_max_ws_size' +SET @@global.wsrep_max_ws_size='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_max_ws_size' +SELECT @global.wsrep_max_ws_size; +@global.wsrep_max_ws_size +NULL +SET @@global.wsrep_max_ws_size=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_max_ws_size value: '-1' +SELECT @global.wsrep_max_ws_size; +@global.wsrep_max_ws_size +NULL + +# restore the initial value +SET @@global.wsrep_max_ws_size = @wsrep_max_ws_size_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_mysql_replication_bundle_basic.result b/mysql-test/suite/sys_vars/r/wsrep_mysql_replication_bundle_basic.result new file mode 100644 index 00000000000..1d69d800703 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_mysql_replication_bundle_basic.result @@ -0,0 +1,52 @@ +# +# wsrep_mysql_replication_bundle +# +# save the initial value +SET @wsrep_mysql_replication_bundle_global_saved = @@global.wsrep_mysql_replication_bundle; +# default +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +0 + +# scope +SELECT @@session.wsrep_mysql_replication_bundle; +ERROR HY000: Variable 'wsrep_mysql_replication_bundle' is a GLOBAL variable +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +0 + +# valid values +SET @@global.wsrep_mysql_replication_bundle=0; +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +0 +SET @@global.wsrep_mysql_replication_bundle=1000; +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +1000 +SET @@global.wsrep_mysql_replication_bundle=default; +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +0 + +# invalid values +SET @@global.wsrep_mysql_replication_bundle=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_mysql_replication_bundle' +SET @@global.wsrep_mysql_replication_bundle='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_mysql_replication_bundle' +SET @@global.wsrep_mysql_replication_bundle=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_mysql_replication_bundle value: '-1' +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +0 +SET @@global.wsrep_mysql_replication_bundle=1001; +Warnings: +Warning 1292 Truncated incorrect wsrep_mysql_replication_bundle value: '1001' +SELECT @@global.wsrep_mysql_replication_bundle; +@@global.wsrep_mysql_replication_bundle +1000 + +# restore the initial value +SET @@global.wsrep_mysql_replication_bundle = @wsrep_mysql_replication_bundle_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_node_address_basic.result b/mysql-test/suite/sys_vars/r/wsrep_node_address_basic.result new file mode 100644 index 00000000000..e9a93d2fcd6 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_node_address_basic.result @@ -0,0 +1,49 @@ +# +# wsrep_node_address +# +# save the initial value +SET @wsrep_node_address_global_saved = @@global.wsrep_node_address; +# default +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address + + +# scope +SELECT @@session.wsrep_node_address; +ERROR HY000: Variable 'wsrep_node_address' is a GLOBAL variable +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address + + +# valid values +SET @@global.wsrep_node_address='127.0.0.1'; +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address +127.0.0.1 +SET @@global.wsrep_node_address=default; +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address + + +# invalid values +SET @@global.wsrep_node_address=NULL; +ERROR 42000: Variable 'wsrep_node_address' can't be set to the value of 'NULL' +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address + +SET @@global.wsrep_node_address=ON; +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address +ON +SET @@global.wsrep_node_address='OFF'; +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address +OFF +SET @@global.wsrep_node_address='junk'; +SELECT @@global.wsrep_node_address; +@@global.wsrep_node_address +junk + +# restore the initial value +SET @@global.wsrep_node_address = @wsrep_node_address_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_node_incoming_address_basic.result b/mysql-test/suite/sys_vars/r/wsrep_node_incoming_address_basic.result new file mode 100644 index 00000000000..2340c61db28 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_node_incoming_address_basic.result @@ -0,0 +1,56 @@ +# +# wsrep_node_incoming_address +# +# save the initial value +SET @wsrep_node_incoming_address_global_saved = @@global.wsrep_node_incoming_address; +# default +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +AUTO + +# scope +SELECT @@session.wsrep_node_incoming_address; +ERROR HY000: Variable 'wsrep_node_incoming_address' is a GLOBAL variable +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +AUTO + +# valid values +SET @@global.wsrep_node_incoming_address='127.0.0.1:4444'; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +127.0.0.1:4444 +SET @@global.wsrep_node_incoming_address='127.0.0.1'; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +127.0.0.1 +SET @@global.wsrep_node_incoming_address=AUTO; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +AUTO +SET @@global.wsrep_node_incoming_address=default; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +AUTO + +# invalid values +SET @@global.wsrep_node_incoming_address=ON; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +ON +SET @@global.wsrep_node_incoming_address='OFF'; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +OFF +SET @@global.wsrep_node_incoming_address=NULL; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +NULL +SET @@global.wsrep_node_incoming_address='junk'; +SELECT @@global.wsrep_node_incoming_address; +@@global.wsrep_node_incoming_address +junk + +# restore the initial value +SET @@global.wsrep_node_incoming_address = @wsrep_node_incoming_address_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result b/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result new file mode 100644 index 00000000000..9657e6bf428 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result @@ -0,0 +1,48 @@ +# +# wsrep_node_name +# +call mtr.add_suppression("WSREP: Failed to get provider options"); +# save the initial value +SET @wsrep_node_name_global_saved = @@global.wsrep_node_name; +# default +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name + + +# scope +SELECT @@session.wsrep_node_name; +ERROR HY000: Variable 'wsrep_node_name' is a GLOBAL variable +SET @@global.wsrep_node_name='node_name'; +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name +node_name + +# valid values +SET @@global.wsrep_node_name='my_node'; +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name +my_node +SET @@global.wsrep_node_name='hyphenated-node-name'; +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name +hyphenated-node-name +SET @@global.wsrep_node_name=default; +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name + + +# invalid values +SET @@global.wsrep_node_name=NULL; +ERROR 42000: Variable 'wsrep_node_name' can't be set to the value of 'NULL' +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name + +SET @@global.wsrep_node_name=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_node_name' +SELECT @@global.wsrep_node_name; +@@global.wsrep_node_name + + +# restore the initial value +SET @@global.wsrep_node_name = @wsrep_node_name_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_notify_cmd_basic.result b/mysql-test/suite/sys_vars/r/wsrep_notify_cmd_basic.result new file mode 100644 index 00000000000..056ff8c817b --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_notify_cmd_basic.result @@ -0,0 +1,47 @@ +# +# wsrep_notify_cmd +# +call mtr.add_suppression("WSREP: Failed to get provider options"); +# save the initial value +SET @wsrep_notify_cmd_global_saved = @@global.wsrep_notify_cmd; +# default +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd + + +# scope +SELECT @@session.wsrep_notify_cmd; +ERROR HY000: Variable 'wsrep_notify_cmd' is a GLOBAL variable +SET @@global.wsrep_notify_cmd='notify_cmd'; +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd +notify_cmd + +# valid values +SET @@global.wsrep_notify_cmd='command'; +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd +command +SET @@global.wsrep_notify_cmd='hyphenated-command'; +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd +hyphenated-command +SET @@global.wsrep_notify_cmd=default; +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd + +SET @@global.wsrep_notify_cmd=NULL; +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd +NULL + +# invalid values +SET @@global.wsrep_notify_cmd=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_notify_cmd' +SELECT @@global.wsrep_notify_cmd; +@@global.wsrep_notify_cmd +NULL + +# restore the initial value +SET @@global.wsrep_notify_cmd = @wsrep_notify_cmd_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_on_basic.result b/mysql-test/suite/sys_vars/r/wsrep_on_basic.result new file mode 100644 index 00000000000..735e2d77180 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_on_basic.result @@ -0,0 +1,50 @@ +# +# wsrep_on +# +# save the initial values +SET @wsrep_on_global_saved = @@global.wsrep_on; +SET @wsrep_on_session_saved = @@session.wsrep_on; +# default +SELECT @@global.wsrep_on; +@@global.wsrep_on +0 +SELECT @@session.wsrep_on; +@@session.wsrep_on +0 + +# scope and valid values +SET @@global.wsrep_on=OFF; +SELECT @@global.wsrep_on; +@@global.wsrep_on +0 +SET @@global.wsrep_on=ON; +SELECT @@global.wsrep_on; +@@global.wsrep_on +1 +SET @@session.wsrep_on=OFF; +SELECT @@session.wsrep_on; +@@session.wsrep_on +0 +SET @@session.wsrep_on=ON; +SELECT @@session.wsrep_on; +@@session.wsrep_on +1 +SET @@session.wsrep_on=default; +SELECT @@session.wsrep_on; +@@session.wsrep_on +1 + +# invalid values +SET @@global.wsrep_on=NULL; +ERROR 42000: Variable 'wsrep_on' can't be set to the value of 'NULL' +SET @@global.wsrep_on='junk'; +ERROR 42000: Variable 'wsrep_on' can't be set to the value of 'junk' +SET @@session.wsrep_on=NULL; +ERROR 42000: Variable 'wsrep_on' can't be set to the value of 'NULL' +SET @@session.wsrep_on='junk'; +ERROR 42000: Variable 'wsrep_on' can't be set to the value of 'junk' + +# restore the initial values +SET @@global.wsrep_on = @wsrep_on_global_saved; +SET @@session.wsrep_on = @wsrep_on_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result b/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result new file mode 100644 index 00000000000..95b59e62adc --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result @@ -0,0 +1,60 @@ +# +# wsrep_osu_method +# +# save the initial value +SET @wsrep_osu_method_global_saved = @@global.wsrep_osu_method; +# default +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +TOI + +# scope +SELECT @@session.wsrep_osu_method; +ERROR HY000: Variable 'wsrep_OSU_method' is a GLOBAL variable +SET @@global.wsrep_osu_method=TOI; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +TOI + +# valid values +SET @@global.wsrep_osu_method=TOI; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +TOI +SET @@global.wsrep_osu_method=RSU; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU +SET @@global.wsrep_osu_method="RSU"; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU +SET @@global.wsrep_osu_method=default; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +TOI +SET @@global.wsrep_osu_method=1; +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU + +# invalid values +SET @@global.wsrep_osu_method=4; +ERROR 42000: Variable 'wsrep_OSU_method' can't be set to the value of '4' +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU +SET @@global.wsrep_osu_method=NULL; +ERROR 42000: Variable 'wsrep_OSU_method' can't be set to the value of 'NULL' +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU +SET @@global.wsrep_osu_method='junk'; +ERROR 42000: Variable 'wsrep_OSU_method' can't be set to the value of 'junk' +SELECT @@global.wsrep_osu_method; +@@global.wsrep_osu_method +RSU + +# restore the initial value +SET @@global.wsrep_osu_method = @wsrep_osu_method_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_provider_basic.result b/mysql-test/suite/sys_vars/r/wsrep_provider_basic.result new file mode 100644 index 00000000000..3e4ac8ca883 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_provider_basic.result @@ -0,0 +1,40 @@ +# +# wsrep_provider +# +# save the initial value +SET @wsrep_provider_global_saved = @@global.wsrep_provider; +# default +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none + +# scope +SELECT @@session.wsrep_provider; +ERROR HY000: Variable 'wsrep_provider' is a GLOBAL variable +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none + +# valid values +SET @@global.wsrep_provider=default; +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none + +# invalid values +SET @@global.wsrep_provider='/invalid/libgalera_smm.so'; +ERROR 42000: Variable 'wsrep_provider' can't be set to the value of '/invalid/libgalera_smm.so' +SET @@global.wsrep_provider=NULL; +ERROR 42000: Variable 'wsrep_provider' can't be set to the value of 'NULL' +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none +SET @@global.wsrep_provider=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_provider' +SELECT @@global.wsrep_provider; +@@global.wsrep_provider +none + +# restore the initial value +SET @@global.wsrep_provider = @wsrep_provider_global_saved; +# End of test 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 new file mode 100644 index 00000000000..ed6b125e064 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result @@ -0,0 +1,48 @@ +# +# wsrep_provider_options +# +call mtr.add_suppression("WSREP: Failed to get provider options"); +# save the initial value +SET @wsrep_provider_options_global_saved = @@global.wsrep_provider_options; +# default +SELECT @@global.wsrep_provider_options; +@@global.wsrep_provider_options + + +# scope +SELECT @@session.wsrep_provider_options; +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'; +SELECT @@global.wsrep_provider_options; +@@global.wsrep_provider_options +name1=value1;name2=value2 +SET @@global.wsrep_provider_options='hyphenated-name:value'; +SELECT @@global.wsrep_provider_options; +@@global.wsrep_provider_options +hyphenated-name:value +SET @@global.wsrep_provider_options=default; +SELECT @@global.wsrep_provider_options; +@@global.wsrep_provider_options + + +# invalid values +SET @@global.wsrep_provider_options=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_provider_options' +SELECT @@global.wsrep_provider_options; +@@global.wsrep_provider_options + +SET @@global.wsrep_provider_options=NULL; +ERROR HY000: Incorrect arguments to SET +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/r/wsrep_recover_basic.result b/mysql-test/suite/sys_vars/r/wsrep_recover_basic.result new file mode 100644 index 00000000000..b26c1121a4c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_recover_basic.result @@ -0,0 +1,22 @@ +# +# wsrep_recover +# +# default +SELECT @@global.wsrep_recover; +@@global.wsrep_recover +0 +SELECT @@session.wsrep_recover; +ERROR HY000: Variable 'wsrep_recover' is a GLOBAL variable + +# scope and valid values +SET @@global.wsrep_recover=OFF; +ERROR HY000: Variable 'wsrep_recover' is a read only variable +SET @@global.wsrep_recover=ON; +ERROR HY000: Variable 'wsrep_recover' is a read only variable + +# invalid values +SET @@global.wsrep_recover=NULL; +ERROR HY000: Variable 'wsrep_recover' is a read only variable +SET @@global.wsrep_recover='junk'; +ERROR HY000: Variable 'wsrep_recover' is a read only variable +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_replicate_myisam_basic.result b/mysql-test/suite/sys_vars/r/wsrep_replicate_myisam_basic.result new file mode 100644 index 00000000000..3625f29aa0f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_replicate_myisam_basic.result @@ -0,0 +1,31 @@ +# +# wsrep_replicate_myisam +# +# save the initial value +SET @wsrep_replicate_myisam_global_saved = @@global.wsrep_replicate_myisam; +# default +SELECT @@global.wsrep_replicate_myisam; +@@global.wsrep_replicate_myisam +0 +SELECT @@session.wsrep_replicate_myisam; +ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable + +# scope and valid values +SET @@global.wsrep_replicate_myisam=OFF; +SELECT @@global.wsrep_replicate_myisam; +@@global.wsrep_replicate_myisam +0 +SET @@global.wsrep_replicate_myisam=ON; +SELECT @@global.wsrep_replicate_myisam; +@@global.wsrep_replicate_myisam +1 + +# invalid values +SET @@global.wsrep_replicate_myisam=NULL; +ERROR 42000: Variable 'wsrep_replicate_myisam' can't be set to the value of 'NULL' +SET @@global.wsrep_replicate_myisam='junk'; +ERROR 42000: Variable 'wsrep_replicate_myisam' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_replicate_myisam = @wsrep_replicate_myisam_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_restart_slave_basic.result b/mysql-test/suite/sys_vars/r/wsrep_restart_slave_basic.result new file mode 100644 index 00000000000..0ecdf915992 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_restart_slave_basic.result @@ -0,0 +1,31 @@ +# +# wsrep_restart_slave +# +# save the initial value +SET @wsrep_restart_slave_global_saved = @@global.wsrep_restart_slave; +# default +SELECT @@global.wsrep_restart_slave; +@@global.wsrep_restart_slave +0 +SELECT @@session.wsrep_restart_slave; +ERROR HY000: Variable 'wsrep_restart_slave' is a GLOBAL variable + +# scope and valid values +SET @@global.wsrep_restart_slave=OFF; +SELECT @@global.wsrep_restart_slave; +@@global.wsrep_restart_slave +0 +SET @@global.wsrep_restart_slave=ON; +SELECT @@global.wsrep_restart_slave; +@@global.wsrep_restart_slave +1 + +# invalid values +SET @@global.wsrep_restart_slave=NULL; +ERROR 42000: Variable 'wsrep_restart_slave' can't be set to the value of 'NULL' +SET @@global.wsrep_restart_slave='junk'; +ERROR 42000: Variable 'wsrep_restart_slave' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_restart_slave = @wsrep_restart_slave_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_retry_autocommit_basic.result b/mysql-test/suite/sys_vars/r/wsrep_retry_autocommit_basic.result new file mode 100644 index 00000000000..d848dadd24d --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_retry_autocommit_basic.result @@ -0,0 +1,63 @@ +# +# wsrep_retry_autocommit +# +# save the initial values +SET @wsrep_retry_autocommit_global_saved = @@global.wsrep_retry_autocommit; +SET @wsrep_retry_autocommit_session_saved = @@session.wsrep_retry_autocommit; +# default +SELECT @@global.wsrep_retry_autocommit; +@@global.wsrep_retry_autocommit +1 + +# scope +SET @@session.wsrep_retry_autocommit=1; +SELECT @@session.wsrep_retry_autocommit; +@@session.wsrep_retry_autocommit +1 +SET @@global.wsrep_retry_autocommit=1; +SELECT @@global.wsrep_retry_autocommit; +@@global.wsrep_retry_autocommit +1 + +# valid values +SET @@global.wsrep_retry_autocommit=10; +SELECT @@global.wsrep_retry_autocommit; +@@global.wsrep_retry_autocommit +10 +SET @@global.wsrep_retry_autocommit=0; +SELECT @@global.wsrep_retry_autocommit; +@@global.wsrep_retry_autocommit +0 +SET @@global.wsrep_retry_autocommit=default; +SELECT @global.wsrep_retry_autocommit; +@global.wsrep_retry_autocommit +NULL +SET @@session.wsrep_retry_autocommit=10; +SELECT @@session.wsrep_retry_autocommit; +@@session.wsrep_retry_autocommit +10 +SET @@session.wsrep_retry_autocommit=0; +SELECT @@session.wsrep_retry_autocommit; +@@session.wsrep_retry_autocommit +0 +SET @@session.wsrep_retry_autocommit=default; +SELECT @session.wsrep_retry_autocommit; +@session.wsrep_retry_autocommit +NULL + +# invalid values +SET @@global.wsrep_retry_autocommit=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_retry_autocommit' +SET @@global.wsrep_retry_autocommit='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_retry_autocommit' +SET @@global.wsrep_retry_autocommit=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_retry_autocommit value: '-1' +SELECT @global.wsrep_retry_autocommit; +@global.wsrep_retry_autocommit +NULL + +# restore the initial value +SET @@global.wsrep_retry_autocommit = @wsrep_retry_autocommit_global_saved; +SET @@session.wsrep_retry_autocommit = @wsrep_retry_autocommit_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result new file mode 100644 index 00000000000..62be5a42416 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_slave_threads_basic.result @@ -0,0 +1,49 @@ +# +# wsrep_slave_threads +# +# save the initial value +SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; +# default +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 + +# scope +SELECT @@session.wsrep_slave_threads; +ERROR HY000: Variable 'wsrep_slave_threads' is a GLOBAL variable +SET @@global.wsrep_slave_threads=1; +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 + +# valid values +SET @@global.wsrep_slave_threads=10; +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +10 +SET @@global.wsrep_slave_threads=0; +Warnings: +Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' +SELECT @@global.wsrep_slave_threads; +@@global.wsrep_slave_threads +1 +SET @@global.wsrep_slave_threads=default; +SELECT @global.wsrep_slave_threads; +@global.wsrep_slave_threads +NULL + +# invalid values +SET @@global.wsrep_slave_threads=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' +SET @@global.wsrep_slave_threads='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_slave_threads' +SET @@global.wsrep_slave_threads=-1; +Warnings: +Warning 1292 Truncated incorrect wsrep_slave_threads value: '-1' +SELECT @global.wsrep_slave_threads; +@global.wsrep_slave_threads +NULL + +# restore the initial value +SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_auth_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_auth_basic.result new file mode 100644 index 00000000000..e6b532c6bba --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_auth_basic.result @@ -0,0 +1,52 @@ +# +# wsrep_sst_auth +# +# save the initial value +SET @wsrep_sst_auth_global_saved = @@global.wsrep_sst_auth; +# default +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +NULL + +# scope +SELECT @@session.wsrep_sst_auth; +ERROR HY000: Variable 'wsrep_sst_auth' is a GLOBAL variable +SET @@global.wsrep_sst_auth='user:pass'; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +******** + +# valid values +SET @@global.wsrep_sst_auth=user; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +******** +SET @@global.wsrep_sst_auth='user:1234'; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +******** +SET @@global.wsrep_sst_auth='hyphenated-user-name:'; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +******** +SET @@global.wsrep_sst_auth=default; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +NULL +SET @@global.wsrep_sst_auth=NULL; +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +NULL + +# invalid values +SET @@global.wsrep_sst_auth=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_sst_auth' +SELECT @@global.wsrep_sst_auth; +@@global.wsrep_sst_auth +NULL +SET @@global.wsrep_sst_auth=user:pass; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':pass' at line 1 + +# restore the initial value +SET @@global.wsrep_sst_auth = @wsrep_sst_auth_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_donor_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_donor_basic.result new file mode 100644 index 00000000000..3d4fc24df7f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_donor_basic.result @@ -0,0 +1,50 @@ +# +# wsrep_sst_donor +# +# save the initial value +SET @wsrep_sst_donor_global_saved = @@global.wsrep_sst_donor; +# default +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor + + +# scope +SELECT @@session.wsrep_sst_donor; +ERROR HY000: Variable 'wsrep_sst_donor' is a GLOBAL variable +SET @@global.wsrep_sst_donor=rsync; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +rsync + +# valid values +SET @@global.wsrep_sst_donor=node1; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +node1 +SET @@global.wsrep_sst_donor='node1,node2'; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +node1,node2 +SET @@global.wsrep_sst_donor='hyphenated-donor-name'; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +hyphenated-donor-name +SET @@global.wsrep_sst_donor=default; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor + +SET @@global.wsrep_sst_donor=NULL; +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +NULL + +# invalid values +SET @@global.wsrep_sst_donor=1; +ERROR 42000: Incorrect argument type to variable 'wsrep_sst_donor' +SELECT @@global.wsrep_sst_donor; +@@global.wsrep_sst_donor +NULL + +# restore the initial value +SET @@global.wsrep_sst_donor = @wsrep_sst_donor_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_donor_rejects_queries_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_donor_rejects_queries_basic.result new file mode 100644 index 00000000000..c9f95beec0a --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_donor_rejects_queries_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_sst_donor_rejects_queries +# +# save the initial value +SET @wsrep_sst_donor_rejects_queries_global_saved = @@global.wsrep_sst_donor_rejects_queries; +# default +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +0 + +# scope +SELECT @@session.wsrep_sst_donor_rejects_queries; +ERROR HY000: Variable 'wsrep_sst_donor_rejects_queries' is a GLOBAL variable +SET @@global.wsrep_sst_donor_rejects_queries=OFF; +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +0 +SET @@global.wsrep_sst_donor_rejects_queries=ON; +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +1 + +# valid values +SET @@global.wsrep_sst_donor_rejects_queries='OFF'; +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +0 +SET @@global.wsrep_sst_donor_rejects_queries=ON; +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +1 +SET @@global.wsrep_sst_donor_rejects_queries=default; +SELECT @@global.wsrep_sst_donor_rejects_queries; +@@global.wsrep_sst_donor_rejects_queries +0 + +# invalid values +SET @@global.wsrep_sst_donor_rejects_queries=NULL; +ERROR 42000: Variable 'wsrep_sst_donor_rejects_queries' can't be set to the value of 'NULL' +SET @@global.wsrep_sst_donor_rejects_queries='junk'; +ERROR 42000: Variable 'wsrep_sst_donor_rejects_queries' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_sst_donor_rejects_queries = @wsrep_sst_donor_rejects_queries_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result new file mode 100644 index 00000000000..cbdac640c36 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result @@ -0,0 +1,54 @@ +# +# wsrep_sst_method +# +# save the initial value +SET @wsrep_sst_method_global_saved = @@global.wsrep_sst_method; +# default +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync + +# scope +SELECT @@session.wsrep_sst_method; +ERROR HY000: Variable 'wsrep_sst_method' is a GLOBAL variable +SET @@global.wsrep_sst_method=rsync; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync + +# valid values +SET @@global.wsrep_sst_method=rsync; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync +SET @@global.wsrep_sst_method=mysqldump; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +mysqldump +SET @@global.wsrep_sst_method=xtrabackup; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +xtrabackup +SET @@global.wsrep_sst_method="xtrabackup-v2"; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +xtrabackup-v2 +SET @@global.wsrep_sst_method=default; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync +SET @@global.wsrep_sst_method='junk'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +junk + +# invalid values +SET @@global.wsrep_sst_method=NULL; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'NULL' +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +junk + +# restore the initial value +SET @@global.wsrep_sst_method = @wsrep_sst_method_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result new file mode 100644 index 00000000000..6db52eb8150 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_receive_address_basic.result @@ -0,0 +1,64 @@ +# +# wsrep_sst_receive_address +# +# save the initial value +SET @wsrep_sst_receive_address_global_saved = @@global.wsrep_sst_receive_address; +# default +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +AUTO + +# scope +SELECT @@session.wsrep_sst_receive_address; +ERROR HY000: Variable 'wsrep_sst_receive_address' is a GLOBAL variable +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +AUTO + +# valid values +SET @@global.wsrep_sst_receive_address=AUTO; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +AUTO +SET @@global.wsrep_sst_receive_address=default; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +AUTO +SET @@global.wsrep_sst_receive_address='192.168.2.254'; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +192.168.2.254 + +# invalid values +SET @@global.wsrep_sst_receive_address='127.0.0.1:4444'; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1:4444' +SET @@global.wsrep_sst_receive_address='127.0.0.1'; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of '127.0.0.1' +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +192.168.2.254 +SET @@global.wsrep_sst_receive_address=NULL; +ERROR 42000: Variable 'wsrep_sst_receive_address' can't be set to the value of 'NULL' +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +192.168.2.254 +SET @@global.wsrep_sst_receive_address='OFF'; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +OFF +SET @@global.wsrep_sst_receive_address=ON; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +ON +SET @@global.wsrep_sst_receive_address=''; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address + +SET @@global.wsrep_sst_receive_address='junk'; +SELECT @@global.wsrep_sst_receive_address; +@@global.wsrep_sst_receive_address +junk + +# restore the initial value +SET @@global.wsrep_sst_receive_address = @wsrep_sst_receive_address_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_start_position_basic.result b/mysql-test/suite/sys_vars/r/wsrep_start_position_basic.result new file mode 100644 index 00000000000..a49e6135d47 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_start_position_basic.result @@ -0,0 +1,57 @@ +# +# wsrep_start_position +# +# save the initial value +SET @wsrep_start_position_global_saved = @@global.wsrep_start_position; +# default +SELECT @@global.wsrep_start_position; +@@global.wsrep_start_position +00000000-0000-0000-0000-000000000000:-1 + +# scope +SELECT @@session.wsrep_start_position; +ERROR HY000: Variable 'wsrep_start_position' is a GLOBAL variable +SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-1'; +SELECT @@global.wsrep_start_position; +@@global.wsrep_start_position +00000000-0000-0000-0000-000000000000:-1 + +# valid values +SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2'; +SELECT @@global.wsrep_start_position; +@@global.wsrep_start_position +00000000-0000-0000-0000-000000000000:-2 +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; +SELECT @@global.wsrep_start_position; +@@global.wsrep_start_position +12345678-1234-1234-1234-123456789012:100 +SET @@global.wsrep_start_position=default; +SELECT @@global.wsrep_start_position; +@@global.wsrep_start_position +00000000-0000-0000-0000-000000000000:-1 + +# invalid values +SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '000000000000000-0000-0000-0000-000000000000:-1' +SET @@global.wsrep_start_position='12345678-1234-1234-12345-123456789012:100'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-1234-12345-123456789012:100' +SET @@global.wsrep_start_position='12345678-1234-123-12345-123456789012:0'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-123-12345-123456789012:0' +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:_99999'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-1234-1234-123456789012:_99999' +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:a'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-1234-1234-123456789012:a' +SET @@global.wsrep_start_position='OFF'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of 'OFF' +SET @@global.wsrep_start_position=ON; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of 'ON' +SET @@global.wsrep_start_position=''; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '' +SET @@global.wsrep_start_position=NULL; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of 'NULL' +SET @@global.wsrep_start_position='junk'; +ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_start_position = @wsrep_start_position_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_auto_increment_control_basic.test b/mysql-test/suite/sys_vars/t/wsrep_auto_increment_control_basic.test new file mode 100644 index 00000000000..5dc23cf2ad6 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_auto_increment_control_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_auto_increment_control +--echo # + +--echo # save the initial value +SET @wsrep_auto_increment_control_global_saved = @@global.wsrep_auto_increment_control; + +--echo # default +SELECT @@global.wsrep_auto_increment_control; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_auto_increment_control; +SET @@global.wsrep_auto_increment_control=OFF; +SELECT @@global.wsrep_auto_increment_control; +SET @@global.wsrep_auto_increment_control=ON; +SELECT @@global.wsrep_auto_increment_control; + +--echo +--echo # valid values +SET @@global.wsrep_auto_increment_control='OFF'; +SELECT @@global.wsrep_auto_increment_control; +SET @@global.wsrep_auto_increment_control=ON; +SELECT @@global.wsrep_auto_increment_control; +SET @@global.wsrep_auto_increment_control=default; +SELECT @@global.wsrep_auto_increment_control; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_auto_increment_control=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_auto_increment_control='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_auto_increment_control = @wsrep_auto_increment_control_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_causal_reads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_causal_reads_basic.test new file mode 100644 index 00000000000..6539e5cba85 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_causal_reads_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_causal_reads +--echo # + +--echo # save the initial values +SET @wsrep_causal_reads_global_saved = @@global.wsrep_causal_reads; +SET @wsrep_causal_reads_session_saved = @@session.wsrep_causal_reads; + +--echo # default +SELECT @@global.wsrep_causal_reads; +SELECT @@session.wsrep_causal_reads; + +--echo +--echo # scope and valid values +SET @@global.wsrep_causal_reads=OFF; +SELECT @@global.wsrep_causal_reads; +SET @@global.wsrep_causal_reads=ON; +SELECT @@global.wsrep_causal_reads; + +SET @@session.wsrep_causal_reads=OFF; +SELECT @@session.wsrep_causal_reads; +SET @@session.wsrep_causal_reads=ON; +SELECT @@session.wsrep_causal_reads; +SET @@session.wsrep_causal_reads=default; +SELECT @@session.wsrep_causal_reads; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_causal_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_causal_reads='junk'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_causal_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_causal_reads='junk'; + +--echo +--echo # restore the initial values +SET @@global.wsrep_causal_reads = @wsrep_causal_reads_global_saved; +SET @@session.wsrep_causal_reads = @wsrep_causal_reads_session_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_certify_nonpk_basic.test b/mysql-test/suite/sys_vars/t/wsrep_certify_nonpk_basic.test new file mode 100644 index 00000000000..a2c690e5954 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_certify_nonpk_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_certify_nonpk +--echo # + +--echo # save the initial value +SET @wsrep_certify_nonpk_global_saved = @@global.wsrep_certify_nonpk; + +--echo # default +SELECT @@global.wsrep_certify_nonpk; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_certify_nonpk; +SET @@global.wsrep_certify_nonpk=OFF; +SELECT @@global.wsrep_certify_nonpk; +SET @@global.wsrep_certify_nonpk=ON; +SELECT @@global.wsrep_certify_nonpk; + +--echo +--echo # valid values +SET @@global.wsrep_certify_nonpk='OFF'; +SELECT @@global.wsrep_certify_nonpk; +SET @@global.wsrep_certify_nonpk=ON; +SELECT @@global.wsrep_certify_nonpk; +SET @@global.wsrep_certify_nonpk=default; +SELECT @@global.wsrep_certify_nonpk; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_certify_nonpk=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_certify_nonpk='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_certify_nonpk = @wsrep_certify_nonpk_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_cluster_address_basic.test b/mysql-test/suite/sys_vars/t/wsrep_cluster_address_basic.test new file mode 100644 index 00000000000..b9e00901eb6 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_cluster_address_basic.test @@ -0,0 +1,48 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_cluster_address +--echo # + +call mtr.add_suppression("safe_mutex: Found wrong usage of mutex.*"); + +--echo # save the initial value +SET @wsrep_cluster_address_global_saved = @@global.wsrep_cluster_address; + +--echo # default +SELECT @@global.wsrep_cluster_address; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_cluster_address; +SELECT @@global.wsrep_cluster_address; + +--echo +--echo # valid values +SET @@global.wsrep_cluster_address='127.0.0.1'; +SELECT @@global.wsrep_cluster_address; +SET @@global.wsrep_cluster_address=AUTO; +SELECT @@global.wsrep_cluster_address; +SET @@global.wsrep_cluster_address=default; +SELECT @@global.wsrep_cluster_address; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_node_address=NULL; +SELECT @@global.wsrep_node_address; +# The values being assigned to wsrep_node_address are not verified so the +# following alues are currently valid too. +SET @@global.wsrep_cluster_address=ON; +SELECT @@global.wsrep_cluster_address; +SET @@global.wsrep_cluster_address='OFF'; +SELECT @@global.wsrep_cluster_address; +SET @@global.wsrep_cluster_address='junk'; +SELECT @@global.wsrep_cluster_address; + +--echo +--echo # restore the initial value +SET @@global.wsrep_cluster_address = @wsrep_cluster_address_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_cluster_name_basic.test b/mysql-test/suite/sys_vars/t/wsrep_cluster_name_basic.test new file mode 100644 index 00000000000..a6fc3ef7b1e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_cluster_name_basic.test @@ -0,0 +1,40 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_cluster_name +--echo # + +--echo # save the initial value +SET @wsrep_cluster_name_global_saved = @@global.wsrep_cluster_name; + +--echo # default +SELECT @@global.wsrep_cluster_name; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_cluster_name; +SET @@global.wsrep_cluster_name='my_galera_cluster'; +SELECT @@global.wsrep_cluster_name; + +--echo +--echo # valid values +SET @@global.wsrep_cluster_name='my_quoted_galera_cluster'; +SELECT @@global.wsrep_cluster_name; +SET @@global.wsrep_cluster_name=my_unquoted_cluster; +SELECT @@global.wsrep_cluster_name; +SET @@global.wsrep_cluster_name=OFF; +SELECT @@global.wsrep_cluster_name; +SET @@global.wsrep_cluster_name=default; +SELECT @@global.wsrep_cluster_name; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_cluster_name=NULL; + +--echo +--echo # restore the initial value +SET @@global.wsrep_cluster_name = @wsrep_cluster_name_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_convert_lock_to_trx_basic.test b/mysql-test/suite/sys_vars/t/wsrep_convert_lock_to_trx_basic.test new file mode 100644 index 00000000000..486832fb394 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_convert_lock_to_trx_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_convert_lock_to_trx +--echo # + +--echo # save the initial value +SET @wsrep_convert_lock_to_trx_global_saved = @@global.wsrep_convert_lock_to_trx; + +--echo # default +SELECT @@global.wsrep_convert_lock_to_trx; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_convert_lock_to_trx; +SET @@global.wsrep_convert_lock_to_trx=OFF; +SELECT @@global.wsrep_convert_lock_to_trx; +SET @@global.wsrep_convert_lock_to_trx=ON; +SELECT @@global.wsrep_convert_lock_to_trx; + +--echo +--echo # valid values +SET @@global.wsrep_convert_lock_to_trx='OFF'; +SELECT @@global.wsrep_convert_lock_to_trx; +SET @@global.wsrep_convert_lock_to_trx=ON; +SELECT @@global.wsrep_convert_lock_to_trx; +SET @@global.wsrep_convert_lock_to_trx=default; +SELECT @@global.wsrep_convert_lock_to_trx; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_convert_lock_to_trx=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_convert_lock_to_trx='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_convert_lock_to_trx = @wsrep_convert_lock_to_trx_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test b/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test new file mode 100644 index 00000000000..41f97cfdaf6 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test @@ -0,0 +1,41 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_data_home_dir (readonly) +--echo # + +--echo # default +SELECT @@global.wsrep_data_home_dir; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_data_home_dir; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir='/tmp/data'; +SELECT @@global.wsrep_data_home_dir; + +--echo +--echo # valid values +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir='/tmp/data'; +SELECT @@global.wsrep_data_home_dir; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir=junk-dir; +SELECT @@global.wsrep_data_home_dir; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir=junk/dir; +SELECT @@global.wsrep_data_home_dir; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir=OFF; +SELECT @@global.wsrep_data_home_dir; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir=default; +SELECT @@global.wsrep_data_home_dir; + +--echo +--echo # invalid values +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_data_home_dir=NULL; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_dbug_option_basic.test b/mysql-test/suite/sys_vars/t/wsrep_dbug_option_basic.test new file mode 100644 index 00000000000..80ce190a154 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_dbug_option_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_dbug_option +--echo # + +--echo # save the initial value +SET @wsrep_dbug_option_global_saved = @@global.wsrep_dbug_option; + +--echo # default +SELECT @@global.wsrep_dbug_option; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_dbug_option; +SET @@global.wsrep_dbug_option='test-dbug-string'; +SELECT @@global.wsrep_dbug_option; + +--echo +--echo # valid values +SET @@global.wsrep_dbug_option='quoted-dbug-string'; +SELECT @@global.wsrep_dbug_option; +SET @@global.wsrep_dbug_option=unquoted_dbug_string; +SELECT @@global.wsrep_dbug_option; +SET @@global.wsrep_dbug_option=OFF; +SELECT @@global.wsrep_dbug_option; +SET @@global.wsrep_dbug_option=NULL; +SELECT @@global.wsrep_dbug_option; +SET @@global.wsrep_dbug_option=default; +SELECT @@global.wsrep_dbug_option; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_dbug_option=1; + +--echo +--echo # restore the initial value +SET @@global.wsrep_dbug_option = @wsrep_dbug_option_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test b/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test new file mode 100644 index 00000000000..50576ff064e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_debug +--echo # + +--echo # save the initial value +SET @wsrep_debug_global_saved = @@global.wsrep_debug; + +--echo # default +SELECT @@global.wsrep_debug; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_debug; +SET @@global.wsrep_debug=OFF; +SELECT @@global.wsrep_debug; +SET @@global.wsrep_debug=ON; +SELECT @@global.wsrep_debug; + +--echo +--echo # valid values +SET @@global.wsrep_debug='OFF'; +SELECT @@global.wsrep_debug; +SET @@global.wsrep_debug=ON; +SELECT @@global.wsrep_debug; +SET @@global.wsrep_debug=default; +SELECT @@global.wsrep_debug; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_debug=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_debug='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_debug = @wsrep_debug_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_desync_basic.test b/mysql-test/suite/sys_vars/t/wsrep_desync_basic.test new file mode 100644 index 00000000000..15226c75d8b --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_desync_basic.test @@ -0,0 +1,49 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_desync +--echo # + +# expected as no wsrep provider is currently loaded +call mtr.add_suppression("WSREP: SET desync failed 9 for SET @@global.wsrep_desync=ON"); + +--echo # save the initial value +SET @wsrep_desync_global_saved = @@global.wsrep_desync; + +--echo # default +SELECT @@global.wsrep_desync; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_desync; +SET @@global.wsrep_desync=OFF; +SELECT @@global.wsrep_desync; +# expected as no wsrep provider is currently loaded +--error ER_CANNOT_USER +SET @@global.wsrep_desync=ON; +SELECT @@global.wsrep_desync; + +--echo +--echo # valid values +SET @@global.wsrep_desync='OFF'; +SELECT @@global.wsrep_desync; +# expected as no wsrep provider is currently loaded +--error ER_CANNOT_USER +SET @@global.wsrep_desync=ON; +SELECT @@global.wsrep_desync; +SET @@global.wsrep_desync=default; +SELECT @@global.wsrep_desync; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_desync=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_desync='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_desync = @wsrep_desync_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_drupal_282555_workaround_basic.test b/mysql-test/suite/sys_vars/t/wsrep_drupal_282555_workaround_basic.test new file mode 100644 index 00000000000..e24f6a15265 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_drupal_282555_workaround_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_drupal_282555_workaround +--echo # + +--echo # save the initial value +SET @wsrep_drupal_282555_workaround_global_saved = @@global.wsrep_drupal_282555_workaround; + +--echo # default +SELECT @@global.wsrep_drupal_282555_workaround; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_drupal_282555_workaround; +SET @@global.wsrep_drupal_282555_workaround=OFF; +SELECT @@global.wsrep_drupal_282555_workaround; +SET @@global.wsrep_drupal_282555_workaround=ON; +SELECT @@global.wsrep_drupal_282555_workaround; + +--echo +--echo # valid values +SET @@global.wsrep_drupal_282555_workaround='OFF'; +SELECT @@global.wsrep_drupal_282555_workaround; +SET @@global.wsrep_drupal_282555_workaround=ON; +SELECT @@global.wsrep_drupal_282555_workaround; +SET @@global.wsrep_drupal_282555_workaround=default; +SELECT @@global.wsrep_drupal_282555_workaround; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_drupal_282555_workaround=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_drupal_282555_workaround='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_drupal_282555_workaround = @wsrep_drupal_282555_workaround_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_forced_binlog_format_basic.test b/mysql-test/suite/sys_vars/t/wsrep_forced_binlog_format_basic.test new file mode 100644 index 00000000000..455034bb623 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_forced_binlog_format_basic.test @@ -0,0 +1,46 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_forced_binlog_format +--echo # + +--echo # save the initial value +SET @wsrep_forced_binlog_format_global_saved = @@global.wsrep_forced_binlog_format; + +--echo # default +SELECT @@global.wsrep_forced_binlog_format; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_forced_binlog_format; +SET @@global.wsrep_forced_binlog_format=STATEMENT; +SELECT @@global.wsrep_forced_binlog_format; + +--echo +--echo # valid values +SET @@global.wsrep_forced_binlog_format=STATEMENT; +SELECT @@global.wsrep_forced_binlog_format; +SET @@global.wsrep_forced_binlog_format=ROW; +SELECT @@global.wsrep_forced_binlog_format; +SET @@global.wsrep_forced_binlog_format=MIXED; +SELECT @@global.wsrep_forced_binlog_format; +SET @@global.wsrep_forced_binlog_format=NONE; +SELECT @@global.wsrep_forced_binlog_format; +SET @@global.wsrep_forced_binlog_format=default; +SELECT @@global.wsrep_forced_binlog_format; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_forced_binlog_format=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_forced_binlog_format='junk'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_forced_binlog_format=ON; + +--echo +--echo # restore the initial value +SET @@global.wsrep_forced_binlog_format = @wsrep_forced_binlog_format_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_load_data_splitting_basic.test b/mysql-test/suite/sys_vars/t/wsrep_load_data_splitting_basic.test new file mode 100644 index 00000000000..d52e388fc60 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_load_data_splitting_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_load_data_splitting +--echo # + +--echo # save the initial value +SET @wsrep_load_data_splitting_global_saved = @@global.wsrep_load_data_splitting; + +--echo # default +SELECT @@global.wsrep_load_data_splitting; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_load_data_splitting; +SET @@global.wsrep_load_data_splitting=OFF; +SELECT @@global.wsrep_load_data_splitting; +SET @@global.wsrep_load_data_splitting=ON; +SELECT @@global.wsrep_load_data_splitting; + +--echo +--echo # valid values +SET @@global.wsrep_load_data_splitting='OFF'; +SELECT @@global.wsrep_load_data_splitting; +SET @@global.wsrep_load_data_splitting=ON; +SELECT @@global.wsrep_load_data_splitting; +SET @@global.wsrep_load_data_splitting=default; +SELECT @@global.wsrep_load_data_splitting; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_load_data_splitting=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_load_data_splitting='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_load_data_splitting = @wsrep_load_data_splitting_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_log_conflicts_basic.test b/mysql-test/suite/sys_vars/t/wsrep_log_conflicts_basic.test new file mode 100644 index 00000000000..eee4d966855 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_log_conflicts_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_log_conflicts +--echo # + +--echo # save the initial value +SET @wsrep_log_conflicts_global_saved = @@global.wsrep_log_conflicts; + +--echo # default +SELECT @@global.wsrep_log_conflicts; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_log_conflicts; +SET @@global.wsrep_log_conflicts=OFF; +SELECT @@global.wsrep_log_conflicts; +SET @@global.wsrep_log_conflicts=ON; +SELECT @@global.wsrep_log_conflicts; + +--echo +--echo # valid values +SET @@global.wsrep_log_conflicts='OFF'; +SELECT @@global.wsrep_log_conflicts; +SET @@global.wsrep_log_conflicts=ON; +SELECT @@global.wsrep_log_conflicts; +SET @@global.wsrep_log_conflicts=default; +SELECT @@global.wsrep_log_conflicts; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_log_conflicts=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_log_conflicts='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_log_conflicts = @wsrep_log_conflicts_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_max_ws_rows_basic.test b/mysql-test/suite/sys_vars/t/wsrep_max_ws_rows_basic.test new file mode 100644 index 00000000000..ed78662c02d --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_max_ws_rows_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_max_ws_rows +--echo # + +--echo # save the initial value +SET @wsrep_max_ws_rows_global_saved = @@global.wsrep_max_ws_rows; + +--echo # default +SELECT @@global.wsrep_max_ws_rows; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_max_ws_rows; +SET @@global.wsrep_max_ws_rows=1; +SELECT @@global.wsrep_max_ws_rows; + +--echo +--echo # valid values +SET @@global.wsrep_max_ws_rows=131072; +SELECT @@global.wsrep_max_ws_rows; +SET @@global.wsrep_max_ws_rows=131073; +SELECT @@global.wsrep_max_ws_rows; +SET @@global.wsrep_max_ws_rows=0; +SELECT @@global.wsrep_max_ws_rows; +SET @@global.wsrep_max_ws_rows=default; +SELECT @global.wsrep_max_ws_rows; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_max_ws_rows=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_max_ws_rows='junk'; +# expect warnings (Truncated incorrect wsrep_max_ws_rows value: '-1') +SET @@global.wsrep_max_ws_rows=-1; +SELECT @global.wsrep_max_ws_rows; + +--echo +--echo # restore the initial value +SET @@global.wsrep_max_ws_rows = @wsrep_max_ws_rows_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_max_ws_size_basic.test b/mysql-test/suite/sys_vars/t/wsrep_max_ws_size_basic.test new file mode 100644 index 00000000000..e7af4558f24 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_max_ws_size_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_max_ws_size +--echo # + +--echo # save the initial value +SET @wsrep_max_ws_size_global_saved = @@global.wsrep_max_ws_size; + +--echo # default +SELECT @@global.wsrep_max_ws_size; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_max_ws_size; +SET @@global.wsrep_max_ws_size=1; +SELECT @@global.wsrep_max_ws_size; + +--echo +--echo # valid values +SET @@global.wsrep_max_ws_size=1073741824; +SELECT @@global.wsrep_max_ws_size; +SET @@global.wsrep_max_ws_size=1073741825; +SELECT @@global.wsrep_max_ws_size; +SET @@global.wsrep_max_ws_size=0; +SELECT @@global.wsrep_max_ws_size; +SET @@global.wsrep_max_ws_size=default; +SELECT @global.wsrep_max_ws_size; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_max_ws_size=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_max_ws_size='junk'; +SELECT @global.wsrep_max_ws_size; +SET @@global.wsrep_max_ws_size=-1; +SELECT @global.wsrep_max_ws_size; + +--echo +--echo # restore the initial value +SET @@global.wsrep_max_ws_size = @wsrep_max_ws_size_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_mysql_replication_bundle_basic.test b/mysql-test/suite/sys_vars/t/wsrep_mysql_replication_bundle_basic.test new file mode 100644 index 00000000000..c293048c43f --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_mysql_replication_bundle_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_mysql_replication_bundle +--echo # + +--echo # save the initial value +SET @wsrep_mysql_replication_bundle_global_saved = @@global.wsrep_mysql_replication_bundle; + +--echo # default +SELECT @@global.wsrep_mysql_replication_bundle; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_mysql_replication_bundle; +SELECT @@global.wsrep_mysql_replication_bundle; + +--echo +--echo # valid values +SET @@global.wsrep_mysql_replication_bundle=0; +SELECT @@global.wsrep_mysql_replication_bundle; +SET @@global.wsrep_mysql_replication_bundle=1000; +SELECT @@global.wsrep_mysql_replication_bundle; +SET @@global.wsrep_mysql_replication_bundle=default; +SELECT @@global.wsrep_mysql_replication_bundle; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_mysql_replication_bundle=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_mysql_replication_bundle='junk'; +# expect warning (truncated incorrect value) +SET @@global.wsrep_mysql_replication_bundle=-1; +SELECT @@global.wsrep_mysql_replication_bundle; +# expect warning (truncated incorrect value) +SET @@global.wsrep_mysql_replication_bundle=1001; +SELECT @@global.wsrep_mysql_replication_bundle; + +--echo +--echo # restore the initial value +SET @@global.wsrep_mysql_replication_bundle = @wsrep_mysql_replication_bundle_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_node_address_basic.test b/mysql-test/suite/sys_vars/t/wsrep_node_address_basic.test new file mode 100644 index 00000000000..fccb40de6bf --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_node_address_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_node_address +--echo # + +--echo # save the initial value +SET @wsrep_node_address_global_saved = @@global.wsrep_node_address; + +--echo # default +SELECT @@global.wsrep_node_address; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_node_address; +SELECT @@global.wsrep_node_address; + +--echo +--echo # valid values +SET @@global.wsrep_node_address='127.0.0.1'; +SELECT @@global.wsrep_node_address; +# default == '' +SET @@global.wsrep_node_address=default; +SELECT @@global.wsrep_node_address; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_node_address=NULL; +SELECT @@global.wsrep_node_address; +# The values being assigned to wsrep_node_address are not verified so the +# following alues are currently valid too. +SET @@global.wsrep_node_address=ON; +SELECT @@global.wsrep_node_address; +SET @@global.wsrep_node_address='OFF'; +SELECT @@global.wsrep_node_address; +SET @@global.wsrep_node_address='junk'; +SELECT @@global.wsrep_node_address; + +--echo +--echo # restore the initial value +SET @@global.wsrep_node_address = @wsrep_node_address_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_node_incoming_address_basic.test b/mysql-test/suite/sys_vars/t/wsrep_node_incoming_address_basic.test new file mode 100644 index 00000000000..9ab9525d2a9 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_node_incoming_address_basic.test @@ -0,0 +1,47 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_node_incoming_address +--echo # + +--echo # save the initial value +SET @wsrep_node_incoming_address_global_saved = @@global.wsrep_node_incoming_address; + +--echo # default +SELECT @@global.wsrep_node_incoming_address; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_node_incoming_address; +SELECT @@global.wsrep_node_incoming_address; + +--echo +--echo # valid values +SET @@global.wsrep_node_incoming_address='127.0.0.1:4444'; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address='127.0.0.1'; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address=AUTO; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address=default; +SELECT @@global.wsrep_node_incoming_address; + +--echo +--echo # invalid values +# The values being assigned to wsrep_node_incoming_address are not verified so +# the following values are currently valid too. +SET @@global.wsrep_node_incoming_address=ON; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address='OFF'; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address=NULL; +SELECT @@global.wsrep_node_incoming_address; +SET @@global.wsrep_node_incoming_address='junk'; +SELECT @@global.wsrep_node_incoming_address; + +--echo +--echo # restore the initial value +SET @@global.wsrep_node_incoming_address = @wsrep_node_incoming_address_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test b/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test new file mode 100644 index 00000000000..1f3ccc0de2c --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test @@ -0,0 +1,44 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_node_name +--echo # + +call mtr.add_suppression("WSREP: Failed to get provider options"); + +--echo # save the initial value +SET @wsrep_node_name_global_saved = @@global.wsrep_node_name; + +--echo # default +SELECT @@global.wsrep_node_name; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_node_name; +SET @@global.wsrep_node_name='node_name'; +SELECT @@global.wsrep_node_name; + +--echo +--echo # valid values +SET @@global.wsrep_node_name='my_node'; +SELECT @@global.wsrep_node_name; +SET @@global.wsrep_node_name='hyphenated-node-name'; +SELECT @@global.wsrep_node_name; +SET @@global.wsrep_node_name=default; +SELECT @@global.wsrep_node_name; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_node_name=NULL; +SELECT @@global.wsrep_node_name; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_node_name=1; +SELECT @@global.wsrep_node_name; + +--echo +--echo # restore the initial value +SET @@global.wsrep_node_name = @wsrep_node_name_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_notify_cmd_basic.test b/mysql-test/suite/sys_vars/t/wsrep_notify_cmd_basic.test new file mode 100644 index 00000000000..6d1535ba148 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_notify_cmd_basic.test @@ -0,0 +1,43 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_notify_cmd +--echo # + +call mtr.add_suppression("WSREP: Failed to get provider options"); + +--echo # save the initial value +SET @wsrep_notify_cmd_global_saved = @@global.wsrep_notify_cmd; + +--echo # default +SELECT @@global.wsrep_notify_cmd; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_notify_cmd; +SET @@global.wsrep_notify_cmd='notify_cmd'; +SELECT @@global.wsrep_notify_cmd; + +--echo +--echo # valid values +SET @@global.wsrep_notify_cmd='command'; +SELECT @@global.wsrep_notify_cmd; +SET @@global.wsrep_notify_cmd='hyphenated-command'; +SELECT @@global.wsrep_notify_cmd; +SET @@global.wsrep_notify_cmd=default; +SELECT @@global.wsrep_notify_cmd; +SET @@global.wsrep_notify_cmd=NULL; +SELECT @@global.wsrep_notify_cmd; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_notify_cmd=1; +SELECT @@global.wsrep_notify_cmd; + +--echo +--echo # restore the initial value +SET @@global.wsrep_notify_cmd = @wsrep_notify_cmd_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_on_basic.test b/mysql-test/suite/sys_vars/t/wsrep_on_basic.test new file mode 100644 index 00000000000..229d771b5e7 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_on_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_on +--echo # + +--echo # save the initial values +SET @wsrep_on_global_saved = @@global.wsrep_on; +SET @wsrep_on_session_saved = @@session.wsrep_on; + +--echo # default +SELECT @@global.wsrep_on; +SELECT @@session.wsrep_on; + +--echo +--echo # scope and valid values +SET @@global.wsrep_on=OFF; +SELECT @@global.wsrep_on; +SET @@global.wsrep_on=ON; +SELECT @@global.wsrep_on; + +SET @@session.wsrep_on=OFF; +SELECT @@session.wsrep_on; +SET @@session.wsrep_on=ON; +SELECT @@session.wsrep_on; +SET @@session.wsrep_on=default; +SELECT @@session.wsrep_on; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_on=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_on='junk'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_on=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_on='junk'; + +--echo +--echo # restore the initial values +SET @@global.wsrep_on = @wsrep_on_global_saved; +SET @@session.wsrep_on = @wsrep_on_session_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test b/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test new file mode 100644 index 00000000000..d6d461075a5 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test @@ -0,0 +1,50 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_osu_method +--echo # + +--echo # save the initial value +SET @wsrep_osu_method_global_saved = @@global.wsrep_osu_method; + +--echo # default +SELECT @@global.wsrep_osu_method; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_osu_method; +SET @@global.wsrep_osu_method=TOI; +SELECT @@global.wsrep_osu_method; + +--echo +--echo # valid values +SET @@global.wsrep_osu_method=TOI; +SELECT @@global.wsrep_osu_method; +SET @@global.wsrep_osu_method=RSU; +SELECT @@global.wsrep_osu_method; +SET @@global.wsrep_osu_method="RSU"; +SELECT @@global.wsrep_osu_method; +SET @@global.wsrep_osu_method=default; +SELECT @@global.wsrep_osu_method; +# numeric value +SET @@global.wsrep_osu_method=1; +SELECT @@global.wsrep_osu_method; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_osu_method=4; +SELECT @@global.wsrep_osu_method; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_osu_method=NULL; +SELECT @@global.wsrep_osu_method; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_osu_method='junk'; +SELECT @@global.wsrep_osu_method; + +--echo +--echo # restore the initial value +SET @@global.wsrep_osu_method = @wsrep_osu_method_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_provider_basic.test b/mysql-test/suite/sys_vars/t/wsrep_provider_basic.test new file mode 100644 index 00000000000..1190ab41bb0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_provider_basic.test @@ -0,0 +1,39 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_provider +--echo # + +--echo # save the initial value +SET @wsrep_provider_global_saved = @@global.wsrep_provider; + +--echo # default +SELECT @@global.wsrep_provider; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_provider; +SELECT @@global.wsrep_provider; + +--echo +--echo # valid values +SET @@global.wsrep_provider=default; +SELECT @@global.wsrep_provider; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_provider='/invalid/libgalera_smm.so'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_provider=NULL; +SELECT @@global.wsrep_provider; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_provider=1; +SELECT @@global.wsrep_provider; + +--echo +--echo # restore the initial value +SET @@global.wsrep_provider = @wsrep_provider_global_saved; + +--echo # 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 new file mode 100644 index 00000000000..10ca8298029 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test @@ -0,0 +1,44 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_provider_options +--echo # + +call mtr.add_suppression("WSREP: Failed to get provider options"); + +--echo # save the initial value +SET @wsrep_provider_options_global_saved = @@global.wsrep_provider_options; + +--echo # default +SELECT @@global.wsrep_provider_options; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_provider_options; +SET @@global.wsrep_provider_options='option1'; +SELECT @@global.wsrep_provider_options; + +--echo +--echo # valid values +SET @@global.wsrep_provider_options='name1=value1;name2=value2'; +SELECT @@global.wsrep_provider_options; +SET @@global.wsrep_provider_options='hyphenated-name:value'; +SELECT @@global.wsrep_provider_options; +SET @@global.wsrep_provider_options=default; +SELECT @@global.wsrep_provider_options; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_provider_options=1; +SELECT @@global.wsrep_provider_options; +--error ER_WRONG_ARGUMENTS +SET @@global.wsrep_provider_options=NULL; +SELECT @@global.wsrep_provider_options; + +--echo +--echo # restore the initial value +SET @@global.wsrep_provider_options = @wsrep_provider_options_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_recover_basic.test b/mysql-test/suite/sys_vars/t/wsrep_recover_basic.test new file mode 100644 index 00000000000..f935e12e258 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_recover_basic.test @@ -0,0 +1,26 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_recover +--echo # + +--echo # default +SELECT @@global.wsrep_recover; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_recover; + +--echo +--echo # scope and valid values +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_recover=OFF; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_recover=ON; + +--echo +--echo # invalid values +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_recover=NULL; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_recover='junk'; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_replicate_myisam_basic.test b/mysql-test/suite/sys_vars/t/wsrep_replicate_myisam_basic.test new file mode 100644 index 00000000000..812fb0cfd73 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_replicate_myisam_basic.test @@ -0,0 +1,36 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_replicate_myisam +--echo # + +--echo # save the initial value +SET @wsrep_replicate_myisam_global_saved = @@global.wsrep_replicate_myisam; + +--echo # default +SELECT @@global.wsrep_replicate_myisam; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_replicate_myisam; + +--echo +--echo # scope and valid values +#--error ER_INCORRECT_GLOBAL_LOCAL_VAR +#TODO: check if it is expected for variable to be dynamic? +SET @@global.wsrep_replicate_myisam=OFF; +SELECT @@global.wsrep_replicate_myisam; +#--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_replicate_myisam=ON; +SELECT @@global.wsrep_replicate_myisam; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_replicate_myisam=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_replicate_myisam='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_replicate_myisam = @wsrep_replicate_myisam_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_restart_slave_basic.test b/mysql-test/suite/sys_vars/t/wsrep_restart_slave_basic.test new file mode 100644 index 00000000000..c656111aed6 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_restart_slave_basic.test @@ -0,0 +1,36 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_restart_slave +--echo # + +--echo # save the initial value +SET @wsrep_restart_slave_global_saved = @@global.wsrep_restart_slave; + +--echo # default +SELECT @@global.wsrep_restart_slave; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_restart_slave; + +--echo +--echo # scope and valid values +#--error ER_INCORRECT_GLOBAL_LOCAL_VAR +#TODO: check if it is expected for variable to be dynamic? +SET @@global.wsrep_restart_slave=OFF; +SELECT @@global.wsrep_restart_slave; +#--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.wsrep_restart_slave=ON; +SELECT @@global.wsrep_restart_slave; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_restart_slave=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_restart_slave='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_restart_slave = @wsrep_restart_slave_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_retry_autocommit_basic.test b/mysql-test/suite/sys_vars/t/wsrep_retry_autocommit_basic.test new file mode 100644 index 00000000000..aa6f27f816d --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_retry_autocommit_basic.test @@ -0,0 +1,52 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_retry_autocommit +--echo # + +--echo # save the initial values +SET @wsrep_retry_autocommit_global_saved = @@global.wsrep_retry_autocommit; +SET @wsrep_retry_autocommit_session_saved = @@session.wsrep_retry_autocommit; + +--echo # default +SELECT @@global.wsrep_retry_autocommit; + +--echo +--echo # scope +SET @@session.wsrep_retry_autocommit=1; +SELECT @@session.wsrep_retry_autocommit; +SET @@global.wsrep_retry_autocommit=1; +SELECT @@global.wsrep_retry_autocommit; + +--echo +--echo # valid values +SET @@global.wsrep_retry_autocommit=10; +SELECT @@global.wsrep_retry_autocommit; +SET @@global.wsrep_retry_autocommit=0; +SELECT @@global.wsrep_retry_autocommit; +SET @@global.wsrep_retry_autocommit=default; +SELECT @global.wsrep_retry_autocommit; + +SET @@session.wsrep_retry_autocommit=10; +SELECT @@session.wsrep_retry_autocommit; +SET @@session.wsrep_retry_autocommit=0; +SELECT @@session.wsrep_retry_autocommit; +SET @@session.wsrep_retry_autocommit=default; +SELECT @session.wsrep_retry_autocommit; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_retry_autocommit=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_retry_autocommit='junk'; +# expect warning : Truncated incorrect wsrep_retry_autocommit value: '-1' +SET @@global.wsrep_retry_autocommit=-1; +SELECT @global.wsrep_retry_autocommit; + +--echo +--echo # restore the initial value +SET @@global.wsrep_retry_autocommit = @wsrep_retry_autocommit_global_saved; +SET @@session.wsrep_retry_autocommit = @wsrep_retry_autocommit_session_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test new file mode 100644 index 00000000000..80b4648982d --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_slave_threads_basic.test @@ -0,0 +1,43 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_slave_threads +--echo # + +--echo # save the initial value +SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; + +--echo # default +SELECT @@global.wsrep_slave_threads; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=1; +SELECT @@global.wsrep_slave_threads; + +--echo +--echo # valid values +SET @@global.wsrep_slave_threads=10; +SELECT @@global.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=0; +SELECT @@global.wsrep_slave_threads; +SET @@global.wsrep_slave_threads=default; +SELECT @global.wsrep_slave_threads; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_slave_threads=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_slave_threads='junk'; +# expect warning : Truncated incorrect wsrep_slave_threads value: '-1' +SET @@global.wsrep_slave_threads=-1; +SELECT @global.wsrep_slave_threads; + +--echo +--echo # restore the initial value +SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_auth_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_auth_basic.test new file mode 100644 index 00000000000..aa901ef9ff7 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_auth_basic.test @@ -0,0 +1,45 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sst_auth +--echo # + +--echo # save the initial value +SET @wsrep_sst_auth_global_saved = @@global.wsrep_sst_auth; + +--echo # default +SELECT @@global.wsrep_sst_auth; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_sst_auth; +SET @@global.wsrep_sst_auth='user:pass'; +SELECT @@global.wsrep_sst_auth; + +--echo +--echo # valid values +SET @@global.wsrep_sst_auth=user; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth='user:1234'; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth='hyphenated-user-name:'; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth=default; +SELECT @@global.wsrep_sst_auth; +SET @@global.wsrep_sst_auth=NULL; +SELECT @@global.wsrep_sst_auth; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_sst_auth=1; +SELECT @@global.wsrep_sst_auth; +--error ER_PARSE_ERROR +SET @@global.wsrep_sst_auth=user:pass; + +--echo +--echo # restore the initial value +SET @@global.wsrep_sst_auth = @wsrep_sst_auth_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_donor_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_donor_basic.test new file mode 100644 index 00000000000..7d3d6598557 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_donor_basic.test @@ -0,0 +1,43 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sst_donor +--echo # + +--echo # save the initial value +SET @wsrep_sst_donor_global_saved = @@global.wsrep_sst_donor; + +--echo # default +SELECT @@global.wsrep_sst_donor; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_sst_donor; +SET @@global.wsrep_sst_donor=rsync; +SELECT @@global.wsrep_sst_donor; + +--echo +--echo # valid values +SET @@global.wsrep_sst_donor=node1; +SELECT @@global.wsrep_sst_donor; +SET @@global.wsrep_sst_donor='node1,node2'; +SELECT @@global.wsrep_sst_donor; +SET @@global.wsrep_sst_donor='hyphenated-donor-name'; +SELECT @@global.wsrep_sst_donor; +SET @@global.wsrep_sst_donor=default; +SELECT @@global.wsrep_sst_donor; +SET @@global.wsrep_sst_donor=NULL; +SELECT @@global.wsrep_sst_donor; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_sst_donor=1; +SELECT @@global.wsrep_sst_donor; + +--echo +--echo # restore the initial value +SET @@global.wsrep_sst_donor = @wsrep_sst_donor_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_donor_rejects_queries_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_donor_rejects_queries_basic.test new file mode 100644 index 00000000000..bd34e23cd2a --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_donor_rejects_queries_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sst_donor_rejects_queries +--echo # + +--echo # save the initial value +SET @wsrep_sst_donor_rejects_queries_global_saved = @@global.wsrep_sst_donor_rejects_queries; + +--echo # default +SELECT @@global.wsrep_sst_donor_rejects_queries; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_sst_donor_rejects_queries; +SET @@global.wsrep_sst_donor_rejects_queries=OFF; +SELECT @@global.wsrep_sst_donor_rejects_queries; +SET @@global.wsrep_sst_donor_rejects_queries=ON; +SELECT @@global.wsrep_sst_donor_rejects_queries; + +--echo +--echo # valid values +SET @@global.wsrep_sst_donor_rejects_queries='OFF'; +SELECT @@global.wsrep_sst_donor_rejects_queries; +SET @@global.wsrep_sst_donor_rejects_queries=ON; +SELECT @@global.wsrep_sst_donor_rejects_queries; +SET @@global.wsrep_sst_donor_rejects_queries=default; +SELECT @@global.wsrep_sst_donor_rejects_queries; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_donor_rejects_queries=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_donor_rejects_queries='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_sst_donor_rejects_queries = @wsrep_sst_donor_rejects_queries_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test new file mode 100644 index 00000000000..3f40a3922dd --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test @@ -0,0 +1,47 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sst_method +--echo # + +--echo # save the initial value +SET @wsrep_sst_method_global_saved = @@global.wsrep_sst_method; + +--echo # default +SELECT @@global.wsrep_sst_method; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_sst_method; +SET @@global.wsrep_sst_method=rsync; +SELECT @@global.wsrep_sst_method; + +--echo +--echo # valid values +SET @@global.wsrep_sst_method=rsync; +SELECT @@global.wsrep_sst_method; +SET @@global.wsrep_sst_method=mysqldump; +SELECT @@global.wsrep_sst_method; +SET @@global.wsrep_sst_method=xtrabackup; +SELECT @@global.wsrep_sst_method; +SET @@global.wsrep_sst_method="xtrabackup-v2"; +SELECT @@global.wsrep_sst_method; +SET @@global.wsrep_sst_method=default; +SELECT @@global.wsrep_sst_method; + +# Its a valid name for an SST method +SET @@global.wsrep_sst_method='junk'; +SELECT @@global.wsrep_sst_method; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_method=NULL; +SELECT @@global.wsrep_sst_method; + +--echo +--echo # restore the initial value +SET @@global.wsrep_sst_method = @wsrep_sst_method_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test new file mode 100644 index 00000000000..9e50cbf8947 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_receive_address_basic.test @@ -0,0 +1,53 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sst_receive_address +--echo # + +--echo # save the initial value +SET @wsrep_sst_receive_address_global_saved = @@global.wsrep_sst_receive_address; + +--echo # default +SELECT @@global.wsrep_sst_receive_address; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_sst_receive_address; +SELECT @@global.wsrep_sst_receive_address; + +--echo +--echo # valid values +SET @@global.wsrep_sst_receive_address=AUTO; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address=default; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address='192.168.2.254'; +SELECT @@global.wsrep_sst_receive_address; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_receive_address='127.0.0.1:4444'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_receive_address='127.0.0.1'; +SELECT @@global.wsrep_sst_receive_address; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_sst_receive_address=NULL; +SELECT @@global.wsrep_sst_receive_address; +# Currently there is no strict checking performed for wsrep_sst_receive_address +# so following values jusr pass through. +SET @@global.wsrep_sst_receive_address='OFF'; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address=ON; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address=''; +SELECT @@global.wsrep_sst_receive_address; +SET @@global.wsrep_sst_receive_address='junk'; +SELECT @@global.wsrep_sst_receive_address; + +--echo +--echo # restore the initial value +SET @@global.wsrep_sst_receive_address = @wsrep_sst_receive_address_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_start_position_basic.test b/mysql-test/suite/sys_vars/t/wsrep_start_position_basic.test new file mode 100644 index 00000000000..3e57cfa6da2 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_start_position_basic.test @@ -0,0 +1,56 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_start_position +--echo # + +--echo # save the initial value +SET @wsrep_start_position_global_saved = @@global.wsrep_start_position; + +--echo # default +SELECT @@global.wsrep_start_position; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_start_position; +SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-1'; +SELECT @@global.wsrep_start_position; + +--echo +--echo # valid values +SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2'; +SELECT @@global.wsrep_start_position; +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; +SELECT @@global.wsrep_start_position; +SET @@global.wsrep_start_position=default; +SELECT @@global.wsrep_start_position; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='12345678-1234-1234-12345-123456789012:100'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='12345678-1234-123-12345-123456789012:0'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:_99999'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:a'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='OFF'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position=ON; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position=''; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_start_position='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_start_position = @wsrep_start_position_global_saved; + +--echo # End of test From e4e55f7968d961e0cb07800397bc3108f960956a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 5 Aug 2014 18:55:05 -0400 Subject: [PATCH 168/294] MDEV-6495: innodb_flush_log_at_trx_commit=0 as suggestion for galera vs =2 Updated innodb_flush_log_at_trx_commit value in cnfs as per recommendation. --- debian/additions/my.cnf | 2 +- support-files/rpm/server.cnf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index 962a65c89ae..eed29b90a2b 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -165,7 +165,7 @@ innodb_flush_method = O_DIRECT #query_cache_size=0 # # Optional setting -#innodb_flush_log_at_trx_commit=2 +#innodb_flush_log_at_trx_commit=0 [mysqldump] quick diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index 56b4eaf4202..173abefa7e6 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -25,7 +25,7 @@ #query_cache_size=0 # # Optional setting -#innodb_flush_log_at_trx_commit=2 +#innodb_flush_log_at_trx_commit=0 # this is only for embedded server [embedded] From 4788577c203402ba228f0dbf874ca2becb6b8fa1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 6 Aug 2014 15:45:53 -0400 Subject: [PATCH 169/294] bzr merge -r3997..4010 codership-mysql/5.5 --- sql/event_data_objects.cc | 18 +++--- sql/sql_parse.cc | 3 + sql/sys_vars.cc | 12 ++++ sql/wsrep_applier.cc | 11 ++++ sql/wsrep_mysqld.cc | 21 +++++-- sql/wsrep_mysqld.h | 2 + sql/wsrep_thd.cc | 11 ++++ sql/wsrep_thd.h | 1 + storage/innobase/handler/ha_innodb.cc | 74 ++++++++++++++++++------ storage/innobase/include/ha_prototypes.h | 9 +-- storage/innobase/lock/lock0lock.c | 10 ---- storage/innobase/rem/rem0rec.c | 8 +-- storage/innobase/row/row0ins.c | 7 --- support-files/mysql.server.sh | 5 +- 14 files changed, 136 insertions(+), 56 deletions(-) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index dbf35bd94b7..656881b9977 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1468,17 +1468,21 @@ end: thd->security_ctx->master_access |= SUPER_ACL; #ifdef WITH_WSREP - // sql_print_information("sizeof(LEX) = %d", sizeof(struct LEX)); - // sizeof(LEX) = 4512, so it's relatively safe to allocate it on stack. - LEX lex; - lex.sql_command = SQLCOM_DROP_EVENT; - thd->lex = &lex; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); + if (WSREP(thd)) { + // sql_print_information("sizeof(LEX) = %d", sizeof(struct LEX)); + // sizeof(LEX) = 4512, so it's relatively safe to allocate it on stack. + LEX lex; + lex.sql_command = SQLCOM_DROP_EVENT; + LEX* saved = thd->lex; + thd->lex = &lex; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); + thd->lex = saved; + } #endif ret= Events::drop_event(thd, dbname, name, FALSE); -#ifdef WITH_WSREP +#ifdef WITH_WSREP WSREP_TO_ISOLATION_END; error: #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 602fc860539..3b5e8a8585f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -993,6 +993,9 @@ static void wsrep_copy_query(THD *thd) { thd->wsrep_retry_command = thd->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); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fff4773f5de..5ad40f2c147 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3918,6 +3918,18 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting( GLOBAL_VAR(wsrep_load_data_splitting), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); +static Sys_var_mybool Sys_wsrep_slave_FK_checks( + "wsrep_slave_FK_checks", "Should slave thread do " + "foreign key constraint checks", + GLOBAL_VAR(wsrep_slave_FK_checks), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_slave_UK_checks( + "wsrep_slave_UK_checks", "Should slave thread do " + "secondary index uniqueness chesks", + GLOBAL_VAR(wsrep_slave_UK_checks), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + static Sys_var_mybool Sys_wsrep_restart_slave( "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 8e9e8b5ca8d..6701d3fd28a 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -207,6 +207,17 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx, 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; + if (flags & WSREP_FLAG_ISOLATION) { thd->wsrep_apply_toi= true; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a0ea67c51ab..ff8fb74164d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -51,7 +51,7 @@ ulong wsrep_max_ws_size = 1073741824UL;//max ws (RBR buffer) size ulong wsrep_max_ws_rows = 65536; // max number of rows in ws int wsrep_to_isolation = 0; // # of active TO isolation threads my_bool wsrep_certify_nonPK = 1; // certify, even when no primary key -long wsrep_max_protocol_version = 2; // maximum protocol version to use +long wsrep_max_protocol_version = 3; // maximum protocol version to use ulong wsrep_forced_binlog_format = BINLOG_FORMAT_UNSPEC; my_bool wsrep_recovery = 0; // recovery my_bool wsrep_replicate_myisam = 0; // enable myisam replication @@ -64,6 +64,8 @@ my_bool wsrep_restart_slave = 0; // should mysql slave thread be // restarted, if node joins back my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave // restart will be needed +my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks +my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks /* * End configuration options */ @@ -109,7 +111,7 @@ const char* wsrep_provider_vendor = provider_vendor; wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; -long wsrep_protocol_version = 2; +long wsrep_protocol_version = 3; // 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 @@ -130,7 +132,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { sql_print_error("WSREP: %s", msg); break; case WSREP_LOG_DEBUG: - sql_print_information ("[Debug] WSREP: %s", msg); + if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); default: break; } @@ -252,6 +254,7 @@ wsrep_view_handler_cb (void* app_ctx, case 0: case 1: case 2: + case 3: // version change if (view->proto_ver != wsrep_protocol_version) { @@ -356,7 +359,7 @@ wsrep_view_handler_cb (void* app_ctx, } out: - wsrep_startup= FALSE; + if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE; local_status.set(new_status, view); return WSREP_CB_SUCCESS; @@ -948,6 +951,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db, break; case 1: case 2: + case 3: { *key_len= 0; if (db) @@ -1079,6 +1083,7 @@ bool wsrep_prepare_key_for_innodb(const uchar* cache_key, } case 1: case 2: + case 3: { key[0].ptr = cache_key; key[0].len = strlen( (char*)cache_key ); @@ -1279,6 +1284,14 @@ static void wsrep_TOI_end(THD *thd) { WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); + + XID xid; + wsrep_xid_init(&xid, &thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + wsrep_set_SE_checkpoint(&xid); + 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)); } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 8e5b14f37a0..73e43deced7 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -97,6 +97,8 @@ 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; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 132cfc7c5d2..5d5917ad3fc 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -414,6 +414,17 @@ void wsrep_create_rollbacker() } } + +extern "C" +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; + } +} + extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync) { diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 74e3bff120c..597033a7c70 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -25,6 +25,7 @@ void wsrep_create_appliers(long threads); void wsrep_create_rollbacker(); extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +extern "C" void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); 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_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index aa4bedc5188..748c0569636 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4572,18 +4572,21 @@ innobase_mysql_cmp( } #ifdef WITH_WSREP extern "C" UNIV_INTERN -void +int wsrep_innobase_mysql_sort( /*===============*/ /* out: str contains sort string */ int mysql_type, /* in: MySQL type */ uint charset_number, /* in: number of the charset */ unsigned char* str, /* in: data field */ - unsigned int str_length) /* in: data field length, + unsigned int str_length, /* in: data field length, not UNIV_SQL_NULL */ + unsigned int buf_length) /* in: total str buffer length */ + { CHARSET_INFO* charset; enum_field_types mysql_tp; + int ret_length = str_length; DBUG_ASSERT(str_length != UNIV_SQL_NULL); @@ -4627,9 +4630,29 @@ wsrep_innobase_mysql_sort( ut_a(str_length <= tmp_length); memcpy(tmp_str, str, str_length); - tmp_length = charset->coll->strnxfrm(charset, str, str_length, - tmp_str, str_length); - DBUG_ASSERT(tmp_length <= str_length); + if (wsrep_protocol_version < 3) { + tmp_length = charset->coll->strnxfrm( + charset, str, str_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length <= str_length); + } else { + /* strnxfrm will expand the destination string, + protocols < 3 truncated the sorted sring + protocols > 3 gets full sorted sring + */ + /* 5.5 strnxfrm pads the tail with spaces and + always returns the full destination buffer lenght + we cannot know how many characters were converted + using 2 * str length here as best guess + */ + uint dst_length = (str_length * 2 < tmp_length) ? + (str_length * 2) : tmp_length; + tmp_length = charset->coll->strnxfrm( + charset, str, dst_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length <= buf_length); + ret_length = tmp_length; + } break; } @@ -4657,7 +4680,7 @@ wsrep_innobase_mysql_sort( break; } - return; + return ret_length; } #endif // WITH_WSREP /**************************************************************//** @@ -4871,8 +4894,9 @@ wsrep_store_key_val_for_row( } memcpy(sorted, data, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); if (wsrep_protocol_version > 1) { memcpy(buff, sorted, true_len); @@ -4944,8 +4968,9 @@ wsrep_store_key_val_for_row( } memcpy(sorted, blob_data, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); memcpy(buff, sorted, true_len); @@ -5008,8 +5033,10 @@ wsrep_store_key_val_for_row( &error); } memcpy(sorted, src_start, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); + memcpy(buff, sorted, true_len); } else { memcpy(buff, src_start, true_len); @@ -7269,7 +7296,7 @@ wsrep_append_foreign_key( wsrep_thd_query(thd) : "void"); return DB_ERROR; } - byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; dict_index_t *idx_target = (referenced) ? @@ -7439,11 +7466,11 @@ ha_innobase::wsrep_append_keys( uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char *key = &keyval[0]; - KEY *key_info = table->key_info; ibool is_null; len = wsrep_store_key_val_for_row( - table, 0, key, key_info->key_length, record0, &is_null); + table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH, + record0, &is_null); if (!is_null) { int rcode = wsrep_append_key( @@ -7461,9 +7488,14 @@ ha_innobase::wsrep_append_keys( uint i; bool hasPK= false; - for (i=0; is->keys && !hasPK; ++i) { + for (i=0; is->keys; ++i) { KEY* key_info = table->key_info + i; - if (key_info->flags & HA_NOSAME) hasPK = true; + if (key_info->flags & HA_NOSAME) { + hasPK = true; + if (i != table->s->primary_key) { + wsrep_thd_set_PA_safe(thd, FALSE); + } + } } for (i=0; is->keys; ++i) { @@ -7486,13 +7518,15 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } + /* !hasPK == table with no PK, must append all non-unique keys */ if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { len = wsrep_store_key_val_for_row( - table, i, key0, key_info->key_length, + table, i, key0, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record0, &is_null); if (!is_null) { int rcode = wsrep_append_key( @@ -7510,7 +7544,8 @@ ha_innobase::wsrep_append_keys( } if (record1) { len = wsrep_store_key_val_for_row( - table, i, key1, key_info->key_length, + table, i, key1, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record1, &is_null); if (!is_null && memcmp(key0, key1, len)) { int rcode = wsrep_append_key( @@ -12846,6 +12881,7 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) trx_sysf_t* sys_header = trx_sysf_get(&mtr); trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); + innobase_flush_logs(hton); return 0; } else { return 1; diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 7b6774fd53b..e72da36b2e0 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -291,11 +291,12 @@ UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *vic my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); //int64_t wsrep_thd_trx_seqno(THD *thd); int wsrep_trx_order_before(void *thd1, void *thd2); -void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, - unsigned char* str, unsigned int str_length); -int -wsrep_on(void *thd_ptr); +int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length, + unsigned int buf_length); +int wsrep_on(void *thd_ptr); int wsrep_is_wsrep_xid(const void*); +my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); #endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 48bb3183f9f..98cb239befc 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1820,12 +1820,7 @@ lock_rec_create( automatically of the gap type */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { -#ifdef WITH_WSREP - ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || - wsrep_thd_is_BF(trx->mysql_thd, FALSE)); -#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); -#endif /* WITH_WSREP */ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } @@ -2109,12 +2104,7 @@ lock_rec_add_to_queue( struct for a gap type lock */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { -#ifdef WITH_WSREP - ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || - wsrep_thd_is_BF(trx->mysql_thd, FALSE)); -#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); -#endif /* WITH_WSREP */ /* There should never be LOCK_REC_NOT_GAP on a supremum record, but let us play safe */ diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index f08fe5c822f..cb4e8ca1cb1 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1961,10 +1961,10 @@ wsrep_rec_get_foreign_key( key_len++; } memcpy(buf, data, len); - wsrep_innobase_mysql_sort( + *buf_len = wsrep_innobase_mysql_sort( (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), (uint)dtype_get_charset_coll(col_f->prtype), - buf, len); + buf, len, *buf_len); } else { /* new protocol */ if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; @@ -1994,12 +1994,12 @@ wsrep_rec_get_foreign_key( case DATA_MYSQL: /* Copy the actual data */ ut_memcpy(buf, data, len); - wsrep_innobase_mysql_sort( + len = wsrep_innobase_mysql_sort( (int) (col_f->prtype & DATA_MYSQL_TYPE_MASK), (uint) dtype_get_charset_coll(col_f->prtype), - buf, len); + buf, len, *buf_len); break; case DATA_BLOB: case DATA_BINARY: diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index d250a8b47b8..a407ed67a83 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1760,13 +1760,6 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { -#ifdef WITH_WSREP - if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) { - if (!(lock_type & LOCK_REC_NOT_GAP)) { - lock_type |= LOCK_REC_NOT_GAP; - } - } -#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index ae3dd2e8bc1..19f07dcf2fc 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -364,7 +364,10 @@ case "$mode" in # Stop the service and regardless of whether it was # running or not, start it again. if $0 stop $other_args; then - $0 start $other_args + if ! $0 start $other_args; then + log_failure_msg "Failed to restart server." + exit 1 + fi else log_failure_msg "Failed to stop running server, so refusing to try to start." exit 1 From b09f1f9e652ad5c805d7a2df3fef3d8e6cc55973 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 6 Aug 2014 15:47:17 -0400 Subject: [PATCH 170/294] bzr merge -r4011..4013 codership-mysql/5.5 --- sql/sql_parse.cc | 3 +-- sql/wsrep_mysqld.cc | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3b5e8a8585f..a876f68ea73 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3339,8 +3339,7 @@ end_with_restore_list: if ((res= insert_precheck(thd, all_tables))) break; #ifdef WITH_WSREP - if (lex->sql_command == SQLCOM_INSERT_SELECT && - thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) + if (thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) { thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING; WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index ff8fb74164d..c6f391fb109 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -776,10 +776,10 @@ void wsrep_filter_new_cluster (int* argc, char* argv[]) { /* make a copy of the argument to convert possible underscores to hyphens. * the copy need not to be longer than WSREP_NEW_CLUSTER option */ - char arg[sizeof(WSREP_NEW_CLUSTER) + 2]= { 0, }; + char arg[sizeof(WSREP_NEW_CLUSTER) + 1]= { 0, }; strncpy(arg, argv[i], sizeof(arg) - 1); - char* underscore; - while (NULL != (underscore= strchr(arg, '_'))) *underscore= '-'; + char* underscore(arg); + while (NULL != (underscore= strchr(underscore, '_'))) *underscore= '-'; if (!strcmp(arg, WSREP_NEW_CLUSTER)) { @@ -886,7 +886,7 @@ wsrep_causal_wait (THD* thd) switch (ret) { case WSREP_NOT_IMPLEMENTED: - msg= "consistent reads by wsrep backend. " + msg= "synchronous reads by wsrep backend. " "Please unset wsrep_causal_reads variable."; err= ER_NOT_SUPPORTED_YET; break; From f20b1fd5e3fbb74e179d499302eefde545e3e1c1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 6 Aug 2014 17:55:29 -0400 Subject: [PATCH 171/294] Merge of innobase changes to xtradb. --- storage/xtradb/handler/ha_innodb.cc | 74 +++++++++++++++++++------- storage/xtradb/include/ha_prototypes.h | 10 ++-- storage/xtradb/lock/lock0lock.c | 10 ---- storage/xtradb/rem/rem0rec.c | 8 +-- storage/xtradb/row/row0ins.c | 7 --- 5 files changed, 64 insertions(+), 45 deletions(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 1df71f8c90e..5085870af67 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5290,18 +5290,21 @@ innobase_mysql_cmp( } #ifdef WITH_WSREP extern "C" UNIV_INTERN -void +int wsrep_innobase_mysql_sort( /*===============*/ /* out: str contains sort string */ int mysql_type, /* in: MySQL type */ uint charset_number, /* in: number of the charset */ unsigned char* str, /* in: data field */ - unsigned int str_length) /* in: data field length, + unsigned int str_length, /* in: data field length, not UNIV_SQL_NULL */ + unsigned int buf_length) /* in: total str buffer length */ + { CHARSET_INFO* charset; enum_field_types mysql_tp; + int ret_length = str_length; DBUG_ASSERT(str_length != UNIV_SQL_NULL); @@ -5345,9 +5348,29 @@ wsrep_innobase_mysql_sort( ut_a(str_length <= tmp_length); memcpy(tmp_str, str, str_length); - tmp_length = charset->coll->strnxfrm(charset, str, str_length, - tmp_str, str_length); - DBUG_ASSERT(tmp_length <= str_length); + if (wsrep_protocol_version < 3) { + tmp_length = charset->coll->strnxfrm( + charset, str, str_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length <= str_length); + } else { + /* strnxfrm will expand the destination string, + protocols < 3 truncated the sorted sring + protocols > 3 gets full sorted sring + */ + /* 5.5 strnxfrm pads the tail with spaces and + always returns the full destination buffer lenght + we cannot know how many characters were converted + using 2 * str length here as best guess + */ + uint dst_length = (str_length * 2 < tmp_length) ? + (str_length * 2) : tmp_length; + tmp_length = charset->coll->strnxfrm( + charset, str, dst_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length <= buf_length); + ret_length = tmp_length; + } break; } @@ -5375,7 +5398,7 @@ wsrep_innobase_mysql_sort( break; } - return; + return ret_length; } #endif // WITH_WSREP /**************************************************************//** @@ -5624,8 +5647,9 @@ wsrep_store_key_val_for_row( } memcpy(sorted, data, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); if (wsrep_protocol_version > 1) { memcpy(buff, sorted, true_len); @@ -5697,8 +5721,9 @@ wsrep_store_key_val_for_row( } memcpy(sorted, blob_data, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); memcpy(buff, sorted, true_len); @@ -5761,8 +5786,10 @@ wsrep_store_key_val_for_row( &error); } memcpy(sorted, src_start, true_len); - wsrep_innobase_mysql_sort( - mysql_type, cs->number, sorted, true_len); + true_len = wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len, + REC_VERSION_56_MAX_INDEX_COL_LEN); + memcpy(buff, sorted, true_len); } else { memcpy(buff, src_start, true_len); @@ -8312,7 +8339,7 @@ wsrep_append_foreign_key( wsrep_thd_query(thd) : "void"); return DB_ERROR; } - byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; dict_index_t *idx_target = (referenced) ? @@ -8482,11 +8509,11 @@ ha_innobase::wsrep_append_keys( uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char *key = &keyval[0]; - KEY *key_info = table->key_info; ibool is_null; len = wsrep_store_key_val_for_row( - table, 0, key, key_info->key_length, record0, &is_null); + table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH, + record0, &is_null); if (!is_null) { int rcode = wsrep_append_key( @@ -8504,9 +8531,14 @@ ha_innobase::wsrep_append_keys( uint i; bool hasPK= false; - for (i=0; is->keys && !hasPK; ++i) { + for (i=0; is->keys; ++i) { KEY* key_info = table->key_info + i; - if (key_info->flags & HA_NOSAME) hasPK = true; + if (key_info->flags & HA_NOSAME) { + hasPK = true; + if (i != table->s->primary_key) { + wsrep_thd_set_PA_safe(thd, FALSE); + } + } } for (i=0; is->keys; ++i) { @@ -8529,13 +8561,15 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } + /* !hasPK == table with no PK, must append all non-unique keys */ if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { len = wsrep_store_key_val_for_row( - table, i, key0, key_info->key_length, + table, i, key0, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record0, &is_null); if (!is_null) { int rcode = wsrep_append_key( @@ -8553,7 +8587,8 @@ ha_innobase::wsrep_append_keys( } if (record1) { len = wsrep_store_key_val_for_row( - table, i, key1, key_info->key_length, + table, i, key1, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record1, &is_null); if (!is_null && memcmp(key0, key1, len)) { int rcode = wsrep_append_key( @@ -14175,6 +14210,7 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) trx_sysf_t* sys_header = trx_sysf_get(&mtr); trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); + innobase_flush_logs(hton); return 0; } else { return 1; diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index cff6478570f..60d792fc5f1 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -306,12 +306,12 @@ UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *vic my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); //int64_t wsrep_thd_trx_seqno(THD *thd); int wsrep_trx_order_before(void *thd1, void *thd2); -void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, - unsigned char* str, unsigned int str_length); -//UNIV_INTERN -int -wsrep_on(void *thd_ptr); +int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length, + unsigned int buf_length); +int wsrep_on(void *thd_ptr); int wsrep_is_wsrep_xid(const void*); +my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); #endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index e17398fe0e3..d9a5768d94c 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -1821,12 +1821,7 @@ lock_rec_create( automatically of the gap type */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { -#ifdef WITH_WSREP - ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || - wsrep_thd_is_BF(trx->mysql_thd, FALSE)); -#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); -#endif /* WITH_WSREP */ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } @@ -2116,12 +2111,7 @@ lock_rec_add_to_queue( struct for a gap type lock */ if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) { -#ifdef WITH_WSREP - ut_ad(!(type_mode & LOCK_REC_NOT_GAP) || - wsrep_thd_is_BF(trx->mysql_thd, FALSE)); -#else ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); -#endif /* WITH_WSREP */ /* There should never be LOCK_REC_NOT_GAP on a supremum record, but let us play safe */ diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index f08fe5c822f..cb4e8ca1cb1 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -1961,10 +1961,10 @@ wsrep_rec_get_foreign_key( key_len++; } memcpy(buf, data, len); - wsrep_innobase_mysql_sort( + *buf_len = wsrep_innobase_mysql_sort( (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), (uint)dtype_get_charset_coll(col_f->prtype), - buf, len); + buf, len, *buf_len); } else { /* new protocol */ if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; @@ -1994,12 +1994,12 @@ wsrep_rec_get_foreign_key( case DATA_MYSQL: /* Copy the actual data */ ut_memcpy(buf, data, len); - wsrep_innobase_mysql_sort( + len = wsrep_innobase_mysql_sort( (int) (col_f->prtype & DATA_MYSQL_TYPE_MASK), (uint) dtype_get_charset_coll(col_f->prtype), - buf, len); + buf, len, *buf_len); break; case DATA_BLOB: case DATA_BINARY: diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index b71d888004f..f6eb391302f 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1772,13 +1772,6 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { -#ifdef WITH_WSREP - if (wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) { - if (!(lock_type & LOCK_REC_NOT_GAP)) { - lock_type |= LOCK_REC_NOT_GAP; - } - } -#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } From f64a0c3f859fbaa8160b8ea31a4b548e62a15e0f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 6 Aug 2014 19:11:55 -0400 Subject: [PATCH 172/294] Updated WSREP_PATCH_REVNO. --- cmake/wsrep.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index dde6c0b4d2d..c66f5716c28 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "10") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "3997") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "4013") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. From e1facda416897c35b9dde90a14d3578f3ca2df9b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 11 Aug 2014 17:09:59 -0400 Subject: [PATCH 173/294] Fix for some failing tests. --- .../include/have_innodb_disallow_writes.inc | 6 +++ mysql-test/include/have_wsrep.inc | 2 +- mysql-test/r/innodb_load_xa_with_wsrep.result | 18 ++++++++ mysql-test/r/mysqld--help.result | 7 +++ mysql-test/suite/sys_vars/r/all_vars.result | 1 - .../r/innodb_disallow_writes_basic.result | 45 +++++++++++++++++++ .../r/wsrep_slave_fk_checks_basic.result | 45 +++++++++++++++++++ .../r/wsrep_slave_uk_checks_basic.result | 45 +++++++++++++++++++ .../t/innodb_disallow_writes_basic.test | 42 +++++++++++++++++ .../t/wsrep_slave_fk_checks_basic.test | 42 +++++++++++++++++ .../t/wsrep_slave_uk_checks_basic.test | 42 +++++++++++++++++ mysql-test/t/innodb_load_xa.test | 1 + mysql-test/t/innodb_load_xa_with_wsrep.opt | 1 + mysql-test/t/innodb_load_xa_with_wsrep.test | 19 ++++++++ 14 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 mysql-test/include/have_innodb_disallow_writes.inc create mode 100644 mysql-test/r/innodb_load_xa_with_wsrep.result create mode 100644 mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_slave_fk_checks_basic.result create mode 100644 mysql-test/suite/sys_vars/r/wsrep_slave_uk_checks_basic.result create mode 100644 mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_slave_fk_checks_basic.test create mode 100644 mysql-test/suite/sys_vars/t/wsrep_slave_uk_checks_basic.test create mode 100644 mysql-test/t/innodb_load_xa_with_wsrep.opt create mode 100644 mysql-test/t/innodb_load_xa_with_wsrep.test diff --git a/mysql-test/include/have_innodb_disallow_writes.inc b/mysql-test/include/have_innodb_disallow_writes.inc new file mode 100644 index 00000000000..83b516b7a34 --- /dev/null +++ b/mysql-test/include/have_innodb_disallow_writes.inc @@ -0,0 +1,6 @@ +--source include/have_innodb.inc + +if (`SELECT COUNT(*) = 0 from INFORMATION_SCHEMA.GLOBAL_VARIABLES + WHERE VARIABLE_NAME = 'INNODB_DISALLOW_WRITES'`) { + --skip Test requires 'innodb_disallow_writes' +} diff --git a/mysql-test/include/have_wsrep.inc b/mysql-test/include/have_wsrep.inc index a3ceae41d40..52220edf481 100644 --- a/mysql-test/include/have_wsrep.inc +++ b/mysql-test/include/have_wsrep.inc @@ -3,6 +3,6 @@ if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`) { - --skip Test required wsrep plugin. + --skip Test requires wsrep plugin. } diff --git a/mysql-test/r/innodb_load_xa_with_wsrep.result b/mysql-test/r/innodb_load_xa_with_wsrep.result new file mode 100644 index 00000000000..6064dcd22d3 --- /dev/null +++ b/mysql-test/r/innodb_load_xa_with_wsrep.result @@ -0,0 +1,18 @@ +install plugin innodb soname 'ha_innodb'; +select engine,support,transactions,xa from information_schema.engines where engine='innodb'; +engine support transactions xa +InnoDB YES YES YES +create table t1 (a int) engine=innodb; +start transaction; +insert t1 values (1); +insert t1 values (2); +commit; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 # Query # # use `test`; create table t1 (a int) engine=innodb +mysqld-bin.000001 # Query # # BEGIN +mysqld-bin.000001 # Query # # use `test`; insert t1 values (1) +mysqld-bin.000001 # Query # # use `test`; insert t1 values (2) +mysqld-bin.000001 # Xid # # COMMIT /* XID */ +drop table t1; +uninstall plugin innodb; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 1b6aeaf6326..82ef0aee3d5 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -917,6 +917,11 @@ The following options may be given as the first argument: --wsrep-retry-autocommit=# Max number of times to retry a failed autocommit statement + --wsrep-slave-FK-checks + Should slave thread do foreign key constraint checks + (Defaults to on; use --skip-wsrep-slave-FK-checks to disable.) + --wsrep-slave-UK-checks + Should slave thread do secondary index uniqueness chesks --wsrep-slave-threads=# Number of slave appliers to launch --wsrep-sst-auth=name @@ -1209,6 +1214,8 @@ wsrep-recover FALSE wsrep-replicate-myisam FALSE wsrep-restart-slave FALSE wsrep-retry-autocommit 1 +wsrep-slave-FK-checks TRUE +wsrep-slave-UK-checks FALSE wsrep-slave-threads 1 wsrep-sst-auth (No default value) wsrep-sst-donor diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index aa40005f5e2..1bd4e394f6a 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -10,6 +10,5 @@ there should be *no* long test name listed below: select distinct variable_name as `there should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; there should be *no* variables listed below: -innodb_disallow_writes drop table t1; drop table t2; diff --git a/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result b/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result new file mode 100644 index 00000000000..bfb6b67b5d8 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result @@ -0,0 +1,45 @@ +# +# innodb_disallow_writes +# +# save the initial value +SET @innodb_disallow_writes_global_saved = @@global.innodb_disallow_writes; +# default +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +0 + +# scope +SELECT @@session.innodb_disallow_writes; +ERROR HY000: Variable 'innodb_disallow_writes' is a GLOBAL variable +SET @@global.innodb_disallow_writes=OFF; +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +0 +SET @@global.innodb_disallow_writes=ON; +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +1 + +# valid values +SET @@global.innodb_disallow_writes='OFF'; +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +0 +SET @@global.innodb_disallow_writes=ON; +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +1 +SET @@global.innodb_disallow_writes=default; +SELECT @@global.innodb_disallow_writes; +@@global.innodb_disallow_writes +0 + +# invalid values +SET @@global.innodb_disallow_writes=NULL; +ERROR 42000: Variable 'innodb_disallow_writes' can't be set to the value of 'NULL' +SET @@global.innodb_disallow_writes='junk'; +ERROR 42000: Variable 'innodb_disallow_writes' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.innodb_disallow_writes = @innodb_disallow_writes_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_slave_fk_checks_basic.result b/mysql-test/suite/sys_vars/r/wsrep_slave_fk_checks_basic.result new file mode 100644 index 00000000000..40b3270e221 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_slave_fk_checks_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_slave_fk_checks +# +# save the initial value +SET @wsrep_slave_fk_checks_global_saved = @@global.wsrep_slave_fk_checks; +# default +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +1 + +# scope +SELECT @@session.wsrep_slave_fk_checks; +ERROR HY000: Variable 'wsrep_slave_FK_checks' is a GLOBAL variable +SET @@global.wsrep_slave_fk_checks=OFF; +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +0 +SET @@global.wsrep_slave_fk_checks=ON; +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +1 + +# valid values +SET @@global.wsrep_slave_fk_checks='OFF'; +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +0 +SET @@global.wsrep_slave_fk_checks=ON; +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +1 +SET @@global.wsrep_slave_fk_checks=default; +SELECT @@global.wsrep_slave_fk_checks; +@@global.wsrep_slave_fk_checks +1 + +# invalid values +SET @@global.wsrep_slave_fk_checks=NULL; +ERROR 42000: Variable 'wsrep_slave_FK_checks' can't be set to the value of 'NULL' +SET @@global.wsrep_slave_fk_checks='junk'; +ERROR 42000: Variable 'wsrep_slave_FK_checks' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_slave_fk_checks = @wsrep_slave_fk_checks_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/r/wsrep_slave_uk_checks_basic.result b/mysql-test/suite/sys_vars/r/wsrep_slave_uk_checks_basic.result new file mode 100644 index 00000000000..b78a83b547d --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_slave_uk_checks_basic.result @@ -0,0 +1,45 @@ +# +# wsrep_slave_uk_checks +# +# save the initial value +SET @wsrep_slave_uk_checks_global_saved = @@global.wsrep_slave_uk_checks; +# default +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +0 + +# scope +SELECT @@session.wsrep_slave_uk_checks; +ERROR HY000: Variable 'wsrep_slave_UK_checks' is a GLOBAL variable +SET @@global.wsrep_slave_uk_checks=OFF; +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +0 +SET @@global.wsrep_slave_uk_checks=ON; +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +1 + +# valid values +SET @@global.wsrep_slave_uk_checks='OFF'; +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +0 +SET @@global.wsrep_slave_uk_checks=ON; +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +1 +SET @@global.wsrep_slave_uk_checks=default; +SELECT @@global.wsrep_slave_uk_checks; +@@global.wsrep_slave_uk_checks +0 + +# invalid values +SET @@global.wsrep_slave_uk_checks=NULL; +ERROR 42000: Variable 'wsrep_slave_UK_checks' can't be set to the value of 'NULL' +SET @@global.wsrep_slave_uk_checks='junk'; +ERROR 42000: Variable 'wsrep_slave_UK_checks' can't be set to the value of 'junk' + +# restore the initial value +SET @@global.wsrep_slave_uk_checks = @wsrep_slave_uk_checks_global_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test b/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test new file mode 100644 index 00000000000..b8e5c127377 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test @@ -0,0 +1,42 @@ +--source include/have_innodb_disallow_writes.inc + +--echo # +--echo # innodb_disallow_writes +--echo # + +--echo # save the initial value +SET @innodb_disallow_writes_global_saved = @@global.innodb_disallow_writes; + +--echo # default +SELECT @@global.innodb_disallow_writes; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_disallow_writes; +SET @@global.innodb_disallow_writes=OFF; +SELECT @@global.innodb_disallow_writes; +SET @@global.innodb_disallow_writes=ON; +SELECT @@global.innodb_disallow_writes; + +--echo +--echo # valid values +SET @@global.innodb_disallow_writes='OFF'; +SELECT @@global.innodb_disallow_writes; +SET @@global.innodb_disallow_writes=ON; +SELECT @@global.innodb_disallow_writes; +SET @@global.innodb_disallow_writes=default; +SELECT @@global.innodb_disallow_writes; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.innodb_disallow_writes=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.innodb_disallow_writes='junk'; + +--echo +--echo # restore the initial value +SET @@global.innodb_disallow_writes = @innodb_disallow_writes_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_slave_fk_checks_basic.test b/mysql-test/suite/sys_vars/t/wsrep_slave_fk_checks_basic.test new file mode 100644 index 00000000000..dd60eb8694b --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_slave_fk_checks_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_slave_fk_checks +--echo # + +--echo # save the initial value +SET @wsrep_slave_fk_checks_global_saved = @@global.wsrep_slave_fk_checks; + +--echo # default +SELECT @@global.wsrep_slave_fk_checks; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_slave_fk_checks; +SET @@global.wsrep_slave_fk_checks=OFF; +SELECT @@global.wsrep_slave_fk_checks; +SET @@global.wsrep_slave_fk_checks=ON; +SELECT @@global.wsrep_slave_fk_checks; + +--echo +--echo # valid values +SET @@global.wsrep_slave_fk_checks='OFF'; +SELECT @@global.wsrep_slave_fk_checks; +SET @@global.wsrep_slave_fk_checks=ON; +SELECT @@global.wsrep_slave_fk_checks; +SET @@global.wsrep_slave_fk_checks=default; +SELECT @@global.wsrep_slave_fk_checks; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_slave_fk_checks=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_slave_fk_checks='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_slave_fk_checks = @wsrep_slave_fk_checks_global_saved; + +--echo # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_slave_uk_checks_basic.test b/mysql-test/suite/sys_vars/t/wsrep_slave_uk_checks_basic.test new file mode 100644 index 00000000000..c9012954371 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_slave_uk_checks_basic.test @@ -0,0 +1,42 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_slave_uk_checks +--echo # + +--echo # save the initial value +SET @wsrep_slave_uk_checks_global_saved = @@global.wsrep_slave_uk_checks; + +--echo # default +SELECT @@global.wsrep_slave_uk_checks; + +--echo +--echo # scope +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.wsrep_slave_uk_checks; +SET @@global.wsrep_slave_uk_checks=OFF; +SELECT @@global.wsrep_slave_uk_checks; +SET @@global.wsrep_slave_uk_checks=ON; +SELECT @@global.wsrep_slave_uk_checks; + +--echo +--echo # valid values +SET @@global.wsrep_slave_uk_checks='OFF'; +SELECT @@global.wsrep_slave_uk_checks; +SET @@global.wsrep_slave_uk_checks=ON; +SELECT @@global.wsrep_slave_uk_checks; +SET @@global.wsrep_slave_uk_checks=default; +SELECT @@global.wsrep_slave_uk_checks; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_slave_uk_checks=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_slave_uk_checks='junk'; + +--echo +--echo # restore the initial value +SET @@global.wsrep_slave_uk_checks = @wsrep_slave_uk_checks_global_saved; + +--echo # End of test diff --git a/mysql-test/t/innodb_load_xa.test b/mysql-test/t/innodb_load_xa.test index 52862151b22..7eac20441ca 100644 --- a/mysql-test/t/innodb_load_xa.test +++ b/mysql-test/t/innodb_load_xa.test @@ -2,6 +2,7 @@ # MDEV-6082 Assertion `0' fails in TC_LOG_DUMMY::log_and_order on DML after installing TokuDB at runtime on server with disabled InnoDB # --source include/not_embedded.inc +--source include/not_wsrep.inc if (!$HA_INNODB_SO) { --skip Need InnoDB plugin diff --git a/mysql-test/t/innodb_load_xa_with_wsrep.opt b/mysql-test/t/innodb_load_xa_with_wsrep.opt new file mode 100644 index 00000000000..4ff27e659ce --- /dev/null +++ b/mysql-test/t/innodb_load_xa_with_wsrep.opt @@ -0,0 +1 @@ +--ignore-builtin-innodb --loose-innodb --log-bin diff --git a/mysql-test/t/innodb_load_xa_with_wsrep.test b/mysql-test/t/innodb_load_xa_with_wsrep.test new file mode 100644 index 00000000000..413faf54864 --- /dev/null +++ b/mysql-test/t/innodb_load_xa_with_wsrep.test @@ -0,0 +1,19 @@ +# +# MDEV-6082 Assertion `0' fails in TC_LOG_DUMMY::log_and_order on DML after installing TokuDB at runtime on server with disabled InnoDB +# +--source include/not_embedded.inc +--source include/have_wsrep.inc + +if (!$HA_INNODB_SO) { + --skip Need InnoDB plugin +} +install plugin innodb soname 'ha_innodb'; +select engine,support,transactions,xa from information_schema.engines where engine='innodb'; +create table t1 (a int) engine=innodb; +start transaction; +insert t1 values (1); +insert t1 values (2); +commit; +--source include/show_binlog_events.inc +drop table t1; +uninstall plugin innodb; From 5add5855390fde8b8e8730c244d149123d8cf7ec Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 12 Aug 2014 18:23:53 -0400 Subject: [PATCH 174/294] Merged r4014 from codership/5.5 --- cmake/wsrep.cmake | 2 +- sql/sql_class.h | 1 + sql/sql_parse.cc | 38 +++++++++++++++++++++++++++++++++----- sql/sys_vars.cc | 16 ++++++++++++++-- sql/transaction.cc | 2 +- sql/wsrep_mysqld.cc | 10 ++++++---- sql/wsrep_mysqld.h | 11 ++++++++++- sql/wsrep_var.cc | 24 +++++++++++++++++++++--- sql/wsrep_var.h | 3 ++- 9 files changed, 89 insertions(+), 18 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index c66f5716c28..97eb47fc587 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "10") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "4013") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "4014") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. diff --git a/sql/sql_class.h b/sql/sql_class.h index bee35bfda7c..cca9d1d63bd 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -594,6 +594,7 @@ typedef struct system_variables #ifdef WITH_WSREP my_bool wsrep_on; my_bool wsrep_causal_reads; + uint wsrep_sync_wait; ulong wsrep_retry_autocommit; #endif double long_query_time_double; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a876f68ea73..3d8b2d4ff1e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2475,7 +2475,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; #endif /* WITH_WSREP */ if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))) @@ -2485,7 +2485,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STATUS: { #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; #endif /* WITH_WSREP */ execute_show_status(thd, all_tables); #ifdef WITH_WSREP @@ -2514,7 +2514,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_INDEX_STATS: case SQLCOM_SELECT: #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: @@ -3079,7 +3079,7 @@ end_with_restore_list: #else { #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; #endif /* WITH_WSREP */ /* @@ -3138,7 +3138,7 @@ end_with_restore_list: { DBUG_ASSERT(first_table == all_tables && first_table != 0); #ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; #endif /* WITH_WSREP */ if (check_table_access(thd, SELECT_ACL, all_tables, @@ -3149,6 +3149,10 @@ end_with_restore_list: break; } case SQLCOM_UPDATE: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) goto error; +#endif /* WITH_WSREP */ { ha_rows found= 0, updated= 0; DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -3188,6 +3192,10 @@ end_with_restore_list: /* if we switched from normal update, rights are checked */ if (up_result != 2) { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) goto error; +#endif /* WITH_WSREP */ if ((res= multi_update_precheck(thd, all_tables))) break; } @@ -3257,6 +3265,10 @@ end_with_restore_list: break; } case SQLCOM_REPLACE: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE)) goto error; +#endif /* WITH_WSREP */ #ifndef DBUG_OFF if (mysql_bin_log.is_open()) { @@ -3292,6 +3304,10 @@ end_with_restore_list: } #endif case SQLCOM_INSERT: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE)) goto error; +#endif /* WITH_WSREP */ { DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) @@ -3333,6 +3349,10 @@ end_with_restore_list: } case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE)) goto error; +#endif /* WITH_WSREP */ { select_result *sel_result; DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -3429,6 +3449,10 @@ end_with_restore_list: break; } case SQLCOM_DELETE: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) goto error; +#endif /* WITH_WSREP */ { DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= delete_precheck(thd, all_tables))) @@ -3444,6 +3468,10 @@ end_with_restore_list: break; } case SQLCOM_DELETE_MULTI: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) goto error; +#endif /* WITH_WSREP */ { DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5ad40f2c147..703ece33872 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3865,9 +3865,21 @@ static Sys_var_mybool Sys_wsrep_certify_nonPK( CMD_LINE(OPT_ARG), DEFAULT(TRUE)); static Sys_var_mybool Sys_wsrep_causal_reads( - "wsrep_causal_reads", "Enable \"strictly synchronous\" semantics for read operations", + "wsrep_causal_reads", "(DEPRECATED) setting this variable is equivalent to setting wsrep_sync_wait READ flag", SESSION_VAR(wsrep_causal_reads), - CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_causal_reads_update)); + +static Sys_var_uint Sys_wsrep_sync_wait( + "wsrep_sync_wait", "Ensure \"synchronous\" read view before executing an operation of the type specified by bitmask: 1 - READ(includes SELECT, SHOW and BEGIN/START TRANSACTION); 2 - UPDATE and DELETE; 4 - INSERT and REPLACE", + SESSION_VAR(wsrep_sync_wait), + CMD_LINE(OPT_ARG), + VALID_RANGE(WSREP_SYNC_WAIT_NONE, WSREP_SYNC_WAIT_MAX), + DEFAULT(WSREP_SYNC_WAIT_NONE), + BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_sync_wait_update)); static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; static Sys_var_enum Sys_wsrep_OSU_method( diff --git a/sql/transaction.cc b/sql/transaction.cc index 36ed15bfe9c..c293c651c04 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -161,7 +161,7 @@ bool trans_begin(THD *thd, uint flags) #ifdef WITH_WSREP thd->wsrep_PA_safe= true; - if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c6f391fb109..687481fa1da 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -861,13 +861,15 @@ bool wsrep_start_replication() return true; } -bool -wsrep_causal_wait (THD* thd) +bool wsrep_sync_wait (THD* thd, uint mask) { - if (thd->variables.wsrep_causal_reads && thd->variables.wsrep_on && + if ((thd->variables.wsrep_sync_wait & mask) && + thd->variables.wsrep_on && !thd->in_active_multi_stmt_transaction() && thd->wsrep_conflict_state != REPLAYING) { + 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_gtid_t gtid; @@ -891,7 +893,7 @@ wsrep_causal_wait (THD* thd) err= ER_NOT_SUPPORTED_YET; break; default: - msg= "Causal wait failed."; + msg= "Synchronous wait failed."; err= ER_LOCK_WAIT_TIMEOUT; // NOTE: the above msg won't be displayed // with ER_LOCK_WAIT_TIMEOUT } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 73e43deced7..28643af3718 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -101,6 +101,14 @@ extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; +enum enum_wsrep_sync_wait { + WSREP_SYNC_WAIT_NONE = 0x0, + // show, 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_MAX = 0x7 +}; // MySQL status variables extern my_bool wsrep_connected; @@ -174,9 +182,10 @@ extern void wsrep_kill_mysql(THD *thd); /* new defines */ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(); -extern bool wsrep_causal_wait(THD* thd); +extern bool wsrep_sync_wait (THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern int wsrep_check_opts (int argc, char* const* argv); extern void wsrep_prepend_PATH (const char* path); +/* some inline functions are defined in wsrep_mysqld_inl.h */ /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index a633b72bc0d..3aa2ac66073 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -60,11 +60,29 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type) return false; } -void wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) +bool wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) { - if (var_type == OPT_GLOBAL) { - thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; + // 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 { + thd->variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ; } + return false; +} + +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 & + WSREP_SYNC_WAIT_BEFORE_READ; + return false; } static int wsrep_start_position_verify (const char* start_str) diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 2a5e94b6724..524dabfd9c0 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -35,7 +35,8 @@ int wsrep_init_vars(); #define INIT_ARGS (const char* opt) extern bool wsrep_on_update UPDATE_ARGS; -extern void wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_sync_wait_update UPDATE_ARGS; extern bool wsrep_start_position_check CHECK_ARGS; extern bool wsrep_start_position_update UPDATE_ARGS; extern void wsrep_start_position_init INIT_ARGS; From a2d5a54374fe8b80da727782078541433f732324 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 13 Aug 2014 10:39:01 -0400 Subject: [PATCH 175/294] Added a basic test for wsrep_sync_wait system variable. Also made some coding style related changes. --- mysql-test/r/mysqld--help.result | 10 +++- .../sys_vars/r/wsrep_sync_wait_basic.result | 56 +++++++++++++++++++ .../sys_vars/t/wsrep_sync_wait_basic.test | 47 ++++++++++++++++ sql/sys_vars.cc | 17 +++--- 4 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result create mode 100644 mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 82ef0aee3d5..49039b4616a 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -862,8 +862,8 @@ The following options may be given as the first argument: variables (Defaults to on; use --skip-wsrep-auto-increment-control to disable.) --wsrep-causal-reads - Enable "strictly synchronous" semantics for read - operations + (DEPRECATED) Setting this variable is equivalent to + setting wsrep_sync_wait READ flag --wsrep-certify-nonPK Certify tables with no primary key (Defaults to on; use --skip-wsrep-certify-nonPK to disable.) @@ -937,6 +937,11 @@ The following options may be given as the first argument: Address where node is waiting for SST contact --wsrep-start-position=name global transaction position to start from + --wsrep-sync-wait[=#] + Ensure "synchronous" read view before executing an + operation of the type specified by bitmask: 1 - + READ(includes SELECT, SHOW and BEGIN/START TRANSACTION); + 2 - UPDATE and DELETE; 4 - INSERT and REPLACE Variables (--variable-name=value) allow-suspicious-udfs FALSE @@ -1223,6 +1228,7 @@ wsrep-sst-donor-rejects-queries FALSE wsrep-sst-method rsync wsrep-sst-receive-address AUTO wsrep-start-position 00000000-0000-0000-0000-000000000000:-1 +wsrep-sync-wait 0 To see what values a running MySQL server is using, type 'mysqladmin variables' instead of 'mysqld --verbose --help'. diff --git a/mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result new file mode 100644 index 00000000000..1e7b9364570 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_sync_wait_basic.result @@ -0,0 +1,56 @@ +# +# wsrep_sync_wait +# +# save the initial values +SET @wsrep_sync_wait_global_saved = @@global.wsrep_sync_wait; +SET @wsrep_sync_wait_session_saved = @@session.wsrep_sync_wait; +# default +SELECT @@global.wsrep_sync_wait; +@@global.wsrep_sync_wait +0 +SELECT @@session.wsrep_sync_wait; +@@session.wsrep_sync_wait +0 + +# scope and valid values +SET @@global.wsrep_sync_wait=0; +SELECT @@global.wsrep_sync_wait; +@@global.wsrep_sync_wait +0 +SET @@global.wsrep_sync_wait=7; +SELECT @@global.wsrep_sync_wait; +@@global.wsrep_sync_wait +7 +SET @@session.wsrep_sync_wait=0; +SELECT @@session.wsrep_sync_wait; +@@session.wsrep_sync_wait +0 +SET @@session.wsrep_sync_wait=7; +SELECT @@session.wsrep_sync_wait; +@@session.wsrep_sync_wait +7 +SET @@session.wsrep_sync_wait=default; +SELECT @@session.wsrep_sync_wait; +@@session.wsrep_sync_wait +7 +SET @@session.wsrep_sync_wait=8; +Warnings: +Warning 1292 Truncated incorrect wsrep_sync_wait value: '8' +SELECT @@session.wsrep_sync_wait; +@@session.wsrep_sync_wait +7 + +# invalid values +SET @@global.wsrep_sync_wait=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait' +SET @@global.wsrep_sync_wait='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait' +SET @@session.wsrep_sync_wait=NULL; +ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait' +SET @@session.wsrep_sync_wait='junk'; +ERROR 42000: Incorrect argument type to variable 'wsrep_sync_wait' + +# restore the initial values +SET @@global.wsrep_sync_wait = @wsrep_sync_wait_global_saved; +SET @@session.wsrep_sync_wait = @wsrep_sync_wait_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test new file mode 100644 index 00000000000..cd0d545f80e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_sync_wait_basic.test @@ -0,0 +1,47 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_sync_wait +--echo # + +--echo # save the initial values +SET @wsrep_sync_wait_global_saved = @@global.wsrep_sync_wait; +SET @wsrep_sync_wait_session_saved = @@session.wsrep_sync_wait; + +--echo # default +SELECT @@global.wsrep_sync_wait; +SELECT @@session.wsrep_sync_wait; + +--echo +--echo # scope and valid values +SET @@global.wsrep_sync_wait=0; +SELECT @@global.wsrep_sync_wait; +SET @@global.wsrep_sync_wait=7; +SELECT @@global.wsrep_sync_wait; + +SET @@session.wsrep_sync_wait=0; +SELECT @@session.wsrep_sync_wait; +SET @@session.wsrep_sync_wait=7; +SELECT @@session.wsrep_sync_wait; +SET @@session.wsrep_sync_wait=default; +SELECT @@session.wsrep_sync_wait; +SET @@session.wsrep_sync_wait=8; +SELECT @@session.wsrep_sync_wait; + +--echo +--echo # invalid values +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_sync_wait=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@global.wsrep_sync_wait='junk'; +--error ER_WRONG_TYPE_FOR_VAR +SET @@session.wsrep_sync_wait=NULL; +--error ER_WRONG_TYPE_FOR_VAR +SET @@session.wsrep_sync_wait='junk'; + +--echo +--echo # restore the initial values +SET @@global.wsrep_sync_wait = @wsrep_sync_wait_global_saved; +SET @@session.wsrep_sync_wait = @wsrep_sync_wait_session_saved; + +--echo # End of test diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 703ece33872..3914d150a7c 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3865,19 +3865,20 @@ static Sys_var_mybool Sys_wsrep_certify_nonPK( CMD_LINE(OPT_ARG), DEFAULT(TRUE)); static Sys_var_mybool Sys_wsrep_causal_reads( - "wsrep_causal_reads", "(DEPRECATED) setting this variable is equivalent to setting wsrep_sync_wait READ flag", - SESSION_VAR(wsrep_causal_reads), - CMD_LINE(OPT_ARG), DEFAULT(FALSE), + "wsrep_causal_reads", "(DEPRECATED) Setting this variable is equivalent " + "to setting wsrep_sync_wait READ flag", + SESSION_VAR(wsrep_causal_reads), CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(wsrep_causal_reads_update)); static Sys_var_uint Sys_wsrep_sync_wait( - "wsrep_sync_wait", "Ensure \"synchronous\" read view before executing an operation of the type specified by bitmask: 1 - READ(includes SELECT, SHOW and BEGIN/START TRANSACTION); 2 - UPDATE and DELETE; 4 - INSERT and REPLACE", - SESSION_VAR(wsrep_sync_wait), - CMD_LINE(OPT_ARG), + "wsrep_sync_wait", "Ensure \"synchronous\" read view before executing " + "an operation of the type specified by bitmask: 1 - READ(includes " + "SELECT, SHOW and BEGIN/START TRANSACTION); 2 - UPDATE and DELETE; 4 - " + "INSERT and REPLACE", + SESSION_VAR(wsrep_sync_wait), CMD_LINE(OPT_ARG), VALID_RANGE(WSREP_SYNC_WAIT_NONE, WSREP_SYNC_WAIT_MAX), - DEFAULT(WSREP_SYNC_WAIT_NONE), - BLOCK_SIZE(1), + DEFAULT(WSREP_SYNC_WAIT_NONE), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(wsrep_sync_wait_update)); From 9ee0dca5d9917b3b3e860442d624135de03648d1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 13 Aug 2014 10:41:41 -0400 Subject: [PATCH 176/294] Updated file_contents.test with correct file location. --- mysql-test/t/file_contents.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/file_contents.test b/mysql-test/t/file_contents.test index 48189aa33a3..746f4e3ae06 100644 --- a/mysql-test/t/file_contents.test +++ b/mysql-test/t/file_contents.test @@ -30,7 +30,7 @@ if ($dir_bin eq '/usr/') { $dir_docs = glob "$dir_docs/packages/MySQL-server*"; } else { # RedHat/Debian: version number in directory name - $dir_docs = glob "$dir_docs/mariadb-server-*"; + $dir_docs = glob "$dir_docs/mariadb-galera-server-*"; $dir_docs = glob "$dir_docs/MySQL-server*" unless -d $dir_docs; } # Slackware From dc0f1864ae09068dee8c340e4b3a687854c3200f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 15 Aug 2014 18:41:36 -0400 Subject: [PATCH 177/294] Fix for binlog tests. --- mysql-test/extra/binlog_tests/binlog.test | 6 +++--- mysql-test/suite/binlog/r/binlog_row_binlog.result | 6 +++--- mysql-test/suite/binlog/r/binlog_stm_binlog.result | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index 63088365b0c..afaaef7b04b 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -369,7 +369,7 @@ dfLtTBcBAAAAIgAAAPkAAAAAABcAAAAAAAcAAf/+AQAAAA== SELECT * FROM t1; --echo # Their values should be ON -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; --echo SET @@SESSION.foreign_key_checks= OFF; @@ -384,7 +384,7 @@ dfLtTBcBAAAAIgAAAM0BAAAAABcAAAAAAAEAAf/+AgAAAA== SELECT * FROM t1; --echo # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; --echo # INSERT INTO t1 VALUES(2) --echo # foreign_key_checks=1 and unique_checks=1 @@ -398,7 +398,7 @@ dfLtTBcBAAAAIgAAAM0BAAAAABcAAAAAAAEAAf/+AgAAAA== SELECT * FROM t1; --echo # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index ba160aabb23..70a72baf49c 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -780,7 +780,7 @@ SELECT * FROM t1; c1 1 # Their values should be ON -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks ON unique_checks ON @@ -798,7 +798,7 @@ c1 1 2 # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks OFF unique_checks OFF @@ -816,7 +816,7 @@ c1 1 2 # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks OFF unique_checks OFF diff --git a/mysql-test/suite/binlog/r/binlog_stm_binlog.result b/mysql-test/suite/binlog/r/binlog_stm_binlog.result index 68e76921ff3..97a2846d063 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_stm_binlog.result @@ -587,7 +587,7 @@ SELECT * FROM t1; c1 1 # Their values should be ON -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks ON unique_checks ON @@ -605,7 +605,7 @@ c1 1 2 # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks OFF unique_checks OFF @@ -623,7 +623,7 @@ c1 1 2 # Their values should be OFF -SHOW SESSION VARIABLES LIKE "%_checks"; +SHOW SESSION VARIABLES WHERE VARIABLE_NAME LIKE "%_checks" AND VARIABLE_NAME NOT LIKE 'wsrep%'; Variable_name Value foreign_key_checks OFF unique_checks OFF From bc5c65f9b468d81d761174a152f762b791b491e8 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 25 Aug 2014 17:03:17 -0400 Subject: [PATCH 178/294] MDEV-6636 : Merged fixes for lp:1167368 and lp:1250805. --- sql/wsrep_utils.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 90af2fb8156..f90d65da8cf 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -373,11 +373,8 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str); if (INADDR_NONE == ip_type) { - WSREP_ERROR("Networking not configured, cannot receive state transfer."); - return 0; - } - - if (INADDR_ANY != ip_type) {; + WSREP_ERROR("Node IP address not obtained from bind_address, trying alternate methods"); + } else if (INADDR_ANY != ip_type) { strncpy (buf, my_bind_addr_str, buf_len); return strlen(buf); } @@ -404,8 +401,8 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) // try to find the address of the first one #if (TARGET_OS_LINUX == 1) - const char cmd[] = "ip addr show | grep -E '^\\s*inet' | grep -m1 global |" - " awk '{ print $2 }' | sed 's/\\/.*//'"; + const char cmd[] = "ip addr show | grep -E '^[[:space:]]*inet' | grep -m1 global |" + " awk '{ print $2 }' | sed -e 's/\\/.*//'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; From aece04a02c25386485c77e7140ab33e51473e366 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 26 Aug 2014 15:56:03 -0400 Subject: [PATCH 179/294] MDEV-6646 : global.wsrep_causal_reads no longer honored During THD initialization, the value of wsrep_causal_reads (now being exclusively handled via wsrep_sync_wait, lp:1277053) was being ignored. Fixed by updating wsrep_sync_wait appropriately. --- sql/sql_class.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 348dd488d2a..14821f0e027 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1484,6 +1484,14 @@ void THD::init(void) wsrep_bf_thd = NULL; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + + /* + @@wsrep_causal_reads is now being handled via wsrep_sync_wait, update it + appropriately. + */ + if (variables.wsrep_causal_reads) + variables.wsrep_sync_wait|= WSREP_SYNC_WAIT_BEFORE_READ; + #endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; From bc59e4c17fe2db77a0f0faa179b49ce2b0a1ab26 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 26 Aug 2014 16:14:46 -0400 Subject: [PATCH 180/294] Switched wsrep_causal_reads ON for galera test suite. --- mysql-test/suite/galera/galera_2nodes.cnf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index 5a08125089a..c0d5b3add3f 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -7,6 +7,8 @@ wsrep_provider=@ENV.WSREP_PROVIDER 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' +# enforce read-committed characteristics across the cluster +wsrep_causal_reads=ON [mysqld.2] binlog-format=row @@ -14,6 +16,8 @@ wsrep_provider=@ENV.WSREP_PROVIDER 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' +# enforce read-committed characteristics across the cluster +wsrep_causal_reads=ON [ENV] NODE_MYPORT_1= @mysqld.1.port From 4cccd57849283667d193b324f8fcaafdf9987e5b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 28 Aug 2014 23:42:45 -0400 Subject: [PATCH 181/294] MDEV-6659: mysqld --help --verbose initializes wsrep Do not initialize/load wsrep subsystem if server is started in help mode. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8d1365a40b6..9cc80662e41 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4467,7 +4467,7 @@ will be ignored as the --log-bin option is not defined."); #endif #ifdef WITH_WSREP /* WSREP BEFORE SE */ - if (!wsrep_recovery) + if (!wsrep_recovery && !opt_help) { if (opt_bootstrap) // bootsrap option given - disable wsrep functionality { From 9e63cc07802deb3a83ad79310ebf9a5dab904f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 3 Sep 2014 18:51:02 +0300 Subject: [PATCH 182/294] MDEV-6651: MariaDB galera cluster crashes in file row0mysql.cc line 684 DELETE FROM ports WHERE ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516' where table ports have foreign keys. Verified that current 5.5-galera is not affected and added test case to regression set. --- mysql-test/suite/galera/r/fk.result | 96 +++++++++++++++++++++++ mysql-test/suite/galera/t/fk.test | 116 ++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 mysql-test/suite/galera/r/fk.result create mode 100644 mysql-test/suite/galera/t/fk.test diff --git a/mysql-test/suite/galera/r/fk.result b/mysql-test/suite/galera/r/fk.result new file mode 100644 index 00000000000..d6a3a25b01a --- /dev/null +++ b/mysql-test/suite/galera/r/fk.result @@ -0,0 +1,96 @@ +USE test; + +# On node_1 +CREATE TABLE networks ( +`tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`status` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, +`admin_state_up` tinyint(1) DEFAULT NULL, +`shared` tinyint(1) DEFAULT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE TABLE ports ( +`tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`network_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +`mac_address` varchar(32) COLLATE utf8_unicode_ci NOT NULL, +`admin_state_up` tinyint(1) NOT NULL, +`status` varchar(16) COLLATE utf8_unicode_ci NOT NULL, +`device_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, +`device_owner` varchar(255) COLLATE utf8_unicode_ci NOT NULL, +PRIMARY KEY (`id`), +KEY `network_id` (`network_id`), +CONSTRAINT `ports_ibfk_1` FOREIGN KEY (`network_id`) REFERENCES networks (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE TABLE subnets ( +`tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, +`network_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, +`ip_version` int(11) NOT NULL, +`cidr` varchar(64) COLLATE utf8_unicode_ci NOT NULL, +`gateway_ip` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, +`enable_dhcp` tinyint(1) DEFAULT NULL, +`shared` tinyint(1) DEFAULT NULL, +`ipv6_ra_mode` enum('slaac','dhcpv6-stateful','dhcpv6-stateless') COLLATE utf8_unicode_ci DEFAULT NULL, +`ipv6_address_mode` enum('slaac','dhcpv6-stateful','dhcpv6-stateless') COLLATE utf8_unicode_ci DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `network_id` (`network_id`), +CONSTRAINT `subnets_ibfk_1` FOREIGN KEY (`network_id`) REFERENCES networks (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE TABLE `ipallocations` ( +`port_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, +`ip_address` varchar(64) COLLATE utf8_unicode_ci NOT NULL, +`subnet_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +`network_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, +PRIMARY KEY (`ip_address`,`subnet_id`,`network_id`), +KEY `port_id` (`port_id`), +KEY `subnet_id` (`subnet_id`), +KEY `network_id` (`network_id`), +CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`port_id`) REFERENCES `ports` (`id`) ON DELETE CASCADE, +CONSTRAINT `ipallocations_ibfk_2` FOREIGN KEY (`subnet_id`) REFERENCES `subnets` (`id`) ON DELETE CASCADE, +CONSTRAINT `ipallocations_ibfk_3` FOREIGN KEY (`network_id`) REFERENCES `networks` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +INSERT INTO networks VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','MyNet','ACTIVE',0,0); +INSERT INTO ports VALUES ('','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','fa:16:3e:e3:cc:bb',1,'DOWN','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','network:router_gateway'); +INSERT INTO subnets VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','ext-subnet','f37aa3fe-ab99-4d0f-a566-6cd3169d7516',4,'10.25.0.0/24','10.25.0.4',0,1,NULL,NULL); +INSERT INTO ipallocations VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','10.25.0.17','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516'); +select * from ports where ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner + f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 fa:16:3e:e3:cc:bb 1 DOWN f37aa3fe-ab99-4d0f-a566-6cd3169d7516 network:router_gateway +select * from ports where ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner + f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 fa:16:3e:e3:cc:bb 1 DOWN f37aa3fe-ab99-4d0f-a566-6cd3169d7516 network:router_gateway +DELETE FROM ports WHERE ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; +select * from networks; +tenant_id id name status admin_state_up shared +f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 MyNet ACTIVE 0 0 +select * from ports; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner +select * from subnets; +tenant_id id name network_id ip_version cidr gateway_ip enable_dhcp shared ipv6_ra_mode ipv6_address_mode +f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 ext-subnet f37aa3fe-ab99-4d0f-a566-6cd3169d7516 4 10.25.0.0/24 10.25.0.4 0 1 NULL NULL +select * from ipallocations; +port_id ip_address subnet_id network_id +select * from ports; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner + +# On node_2 +select * from networks; +tenant_id id name status admin_state_up shared +f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 MyNet ACTIVE 0 0 +select * from ports; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner +select * from subnets; +tenant_id id name network_id ip_version cidr gateway_ip enable_dhcp shared ipv6_ra_mode ipv6_address_mode +f37aa3fe-ab99-4d0f-a566-6cd3169d7516 f37aa3fe-ab99-4d0f-a566-6cd3169d7516 ext-subnet f37aa3fe-ab99-4d0f-a566-6cd3169d7516 4 10.25.0.0/24 10.25.0.4 0 1 NULL NULL +select * from ipallocations; +port_id ip_address subnet_id network_id +select * from ports; +tenant_id id name network_id mac_address admin_state_up status device_id device_owner +drop table ipallocations; +drop table subnets; +drop table ports; +drop table networks; diff --git a/mysql-test/suite/galera/t/fk.test b/mysql-test/suite/galera/t/fk.test new file mode 100644 index 00000000000..e0b7cf06ed0 --- /dev/null +++ b/mysql-test/suite/galera/t/fk.test @@ -0,0 +1,116 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# MDEV-6651: MariaDB galera cluster crashes in file row0mysql.cc line 684 +# DELETE FROM ports WHERE ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516' +# where table ports have foreign keys +# + +USE test; +--echo +--echo # On node_1 +--connection node_1 + + CREATE TABLE networks ( + `tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `status` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, + `admin_state_up` tinyint(1) DEFAULT NULL, + `shared` tinyint(1) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + CREATE TABLE ports ( + `tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `network_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `mac_address` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `admin_state_up` tinyint(1) NOT NULL, + `status` varchar(16) COLLATE utf8_unicode_ci NOT NULL, + `device_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + `device_owner` varchar(255) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `network_id` (`network_id`), + CONSTRAINT `ports_ibfk_1` FOREIGN KEY (`network_id`) REFERENCES networks (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE TABLE subnets ( + `tenant_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `network_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, + `ip_version` int(11) NOT NULL, + `cidr` varchar(64) COLLATE utf8_unicode_ci NOT NULL, + `gateway_ip` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, + `enable_dhcp` tinyint(1) DEFAULT NULL, + `shared` tinyint(1) DEFAULT NULL, + `ipv6_ra_mode` enum('slaac','dhcpv6-stateful','dhcpv6-stateless') COLLATE utf8_unicode_ci DEFAULT NULL, + `ipv6_address_mode` enum('slaac','dhcpv6-stateful','dhcpv6-stateless') COLLATE utf8_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `network_id` (`network_id`), + CONSTRAINT `subnets_ibfk_1` FOREIGN KEY (`network_id`) REFERENCES networks (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + CREATE TABLE `ipallocations` ( + `port_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, + `ip_address` varchar(64) COLLATE utf8_unicode_ci NOT NULL, + `subnet_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `network_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`ip_address`,`subnet_id`,`network_id`), + KEY `port_id` (`port_id`), + KEY `subnet_id` (`subnet_id`), + KEY `network_id` (`network_id`), + CONSTRAINT `ipallocations_ibfk_1` FOREIGN KEY (`port_id`) REFERENCES `ports` (`id`) ON DELETE CASCADE, + CONSTRAINT `ipallocations_ibfk_2` FOREIGN KEY (`subnet_id`) REFERENCES `subnets` (`id`) ON DELETE CASCADE, + CONSTRAINT `ipallocations_ibfk_3` FOREIGN KEY (`network_id`) REFERENCES `networks` (`id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +INSERT INTO networks VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','MyNet','ACTIVE',0,0); + +INSERT INTO ports VALUES ('','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','fa:16:3e:e3:cc:bb',1,'DOWN','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','network:router_gateway'); + +INSERT INTO subnets VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','ext-subnet','f37aa3fe-ab99-4d0f-a566-6cd3169d7516',4,'10.25.0.0/24','10.25.0.4',0,1,NULL,NULL); + +INSERT INTO ipallocations VALUES ('f37aa3fe-ab99-4d0f-a566-6cd3169d7516','10.25.0.17','f37aa3fe-ab99-4d0f-a566-6cd3169d7516','f37aa3fe-ab99-4d0f-a566-6cd3169d7516'); + +select * from ports where ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; + +--connection node_2 + +select * from ports where ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; + +--let $galera_diff_statement = SELECT * FROM ports +--source include/galera_diff.inc + +--connection node_1 + +DELETE FROM ports WHERE ports.id = 'f37aa3fe-ab99-4d0f-a566-6cd3169d7516'; + +select * from networks; +select * from ports; +select * from subnets; +select * from ipallocations; +select * from ports; + +--echo +--echo # On node_2 +--connection node_2 +select * from networks; +select * from ports; +select * from subnets; +select * from ipallocations; +select * from ports; + +--let $galera_diff_statement = SELECT * FROM ports +--source include/galera_diff.inc + +--connection node_1 +drop table ipallocations; +drop table subnets; +drop table ports; +drop table networks; + +--source include/galera_end.inc From 6421f5f147c7f68444a499b305a037f17a7f0bd5 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 8 Sep 2014 13:58:43 -0400 Subject: [PATCH 183/294] Bumping server version. (5.5.40-galera) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 67a35621511..ae997143dac 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=39 +MYSQL_VERSION_PATCH=40 MYSQL_VERSION_EXTRA= From 140fd7adbdf5a998c5e984d3b8e3737587efc680 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 9 Sep 2014 09:18:35 -0400 Subject: [PATCH 184/294] MDEV-6699 : wsrep_node_name not automatically set to hostname Fixed by using hostname (glob_hostname) as default value for wsrep_node_name system variable. Added a test case. --- .../sys_vars/r/wsrep_node_name_basic.result | 39 ++++++++++++------- .../sys_vars/t/wsrep_node_name_basic.test | 20 +++++++--- sql/mysqld.cc | 7 ---- sql/sys_vars.cc | 2 +- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result b/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result index 9657e6bf428..763d0612a1b 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_node_name_basic.result @@ -4,10 +4,10 @@ call mtr.add_suppression("WSREP: Failed to get provider options"); # save the initial value SET @wsrep_node_name_global_saved = @@global.wsrep_node_name; -# default -SELECT @@global.wsrep_node_name; -@@global.wsrep_node_name - +# default (expect 1) +SELECT COUNT(@@global.wsrep_node_name); +COUNT(@@global.wsrep_node_name) +1 # scope SELECT @@session.wsrep_node_name; @@ -27,21 +27,34 @@ SELECT @@global.wsrep_node_name; @@global.wsrep_node_name hyphenated-node-name SET @@global.wsrep_node_name=default; -SELECT @@global.wsrep_node_name; -@@global.wsrep_node_name - +# default (expect 1) +SELECT COUNT(@@global.wsrep_node_name); +COUNT(@@global.wsrep_node_name) +1 # invalid values SET @@global.wsrep_node_name=NULL; ERROR 42000: Variable 'wsrep_node_name' can't be set to the value of 'NULL' -SELECT @@global.wsrep_node_name; -@@global.wsrep_node_name - +SELECT COUNT(@@global.wsrep_node_name); +COUNT(@@global.wsrep_node_name) +1 SET @@global.wsrep_node_name=1; ERROR 42000: Incorrect argument type to variable 'wsrep_node_name' -SELECT @@global.wsrep_node_name; -@@global.wsrep_node_name - +SELECT COUNT(@@global.wsrep_node_name); +COUNT(@@global.wsrep_node_name) +1 +# +# MDEV-6699 : wsrep_node_name not automaticly set to hostname +# +SET @@global.wsrep_node_name=default; +SELECT @@GLOBAL.wsrep_node_name = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='hostname'; +@@GLOBAL.wsrep_node_name = VARIABLE_VALUE +1 +SELECT @@GLOBAL.wsrep_node_name = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='wsrep_node_name'; +@@GLOBAL.wsrep_node_name = VARIABLE_VALUE +1 # restore the initial value SET @@global.wsrep_node_name = @wsrep_node_name_global_saved; diff --git a/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test b/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test index 1f3ccc0de2c..7bc9bec8b95 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_node_name_basic.test @@ -9,8 +9,8 @@ call mtr.add_suppression("WSREP: Failed to get provider options"); --echo # save the initial value SET @wsrep_node_name_global_saved = @@global.wsrep_node_name; ---echo # default -SELECT @@global.wsrep_node_name; +--echo # default (expect 1) +SELECT COUNT(@@global.wsrep_node_name); --echo --echo # scope @@ -26,16 +26,26 @@ SELECT @@global.wsrep_node_name; SET @@global.wsrep_node_name='hyphenated-node-name'; SELECT @@global.wsrep_node_name; SET @@global.wsrep_node_name=default; -SELECT @@global.wsrep_node_name; +--echo # default (expect 1) +SELECT COUNT(@@global.wsrep_node_name); --echo --echo # invalid values --error ER_WRONG_VALUE_FOR_VAR SET @@global.wsrep_node_name=NULL; -SELECT @@global.wsrep_node_name; +SELECT COUNT(@@global.wsrep_node_name); --error ER_WRONG_TYPE_FOR_VAR SET @@global.wsrep_node_name=1; -SELECT @@global.wsrep_node_name; +SELECT COUNT(@@global.wsrep_node_name); + +--echo # +--echo # MDEV-6699 : wsrep_node_name not automaticly set to hostname +--echo # +SET @@global.wsrep_node_name=default; +SELECT @@GLOBAL.wsrep_node_name = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='hostname'; +SELECT @@GLOBAL.wsrep_node_name = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='wsrep_node_name'; --echo --echo # restore the initial value diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9cc80662e41..55df08b367c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3705,13 +3705,6 @@ static int init_common_variables() } else opt_log_basename= glob_hostname; -#ifdef WITH_WSREP - if (0 == wsrep_node_name || 0 == wsrep_node_name[0]) - { - my_free((void *)wsrep_node_name); - wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME)); - } -#endif /* WITH_WSREP */ if (!*pidfile_name) { strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 3914d150a7c..8fbd96ed662 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3731,7 +3731,7 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + IN_FS_CHARSET, DEFAULT(glob_hostname), NO_MUTEX_GUARD, NOT_IN_BINLOG, wsrep_node_name_check, wsrep_node_name_update); static Sys_var_charptr Sys_wsrep_node_address ( From e5267cae8ae4e09aaedeba0fea8408585f1f409f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 9 Sep 2014 13:41:22 -0400 Subject: [PATCH 185/294] MDEV-6717 : wsrep_data_home_dir should default to @@datadir Used mysql_real_data_home as wsrep_data_home_dir's default. Added a test case. --- .../r/wsrep_data_home_dir_basic.result | 53 +++++++++++-------- .../sys_vars/t/wsrep_data_home_dir_basic.test | 22 +++++--- sql/sys_vars.cc | 2 +- sql/wsrep_mysqld.cc | 3 -- 4 files changed, 48 insertions(+), 32 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result b/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result index 044ef8bf3bc..e0f4b478c90 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_data_home_dir_basic.result @@ -2,47 +2,58 @@ # wsrep_data_home_dir (readonly) # # default -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 # scope SELECT @@session.wsrep_data_home_dir; ERROR HY000: Variable 'wsrep_data_home_dir' is a GLOBAL variable SET @@global.wsrep_data_home_dir='/tmp/data'; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 # valid values SET @@global.wsrep_data_home_dir='/tmp/data'; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 SET @@global.wsrep_data_home_dir=junk-dir; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 SET @@global.wsrep_data_home_dir=junk/dir; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 SET @@global.wsrep_data_home_dir=OFF; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 SET @@global.wsrep_data_home_dir=default; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable -SELECT @@global.wsrep_data_home_dir; -@@global.wsrep_data_home_dir - +SELECT COUNT(@@global.wsrep_data_home_dir); +COUNT(@@global.wsrep_data_home_dir) +1 # invalid values SET @@global.wsrep_data_home_dir=NULL; ERROR HY000: Variable 'wsrep_data_home_dir' is a read only variable +# +# MDEV-6717 : wsrep_data_home_dir should default to @@datadir +# +SELECT @@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='datadir'; +@@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE +1 +SELECT @@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='wsrep_data_home_dir'; +@@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE +1 # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test b/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test index 41f97cfdaf6..cd50fbc389e 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_data_home_dir_basic.test @@ -5,7 +5,7 @@ --echo # --echo # default -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --echo --echo # scope @@ -13,29 +13,37 @@ SELECT @@global.wsrep_data_home_dir; SELECT @@session.wsrep_data_home_dir; --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir='/tmp/data'; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --echo --echo # valid values --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir='/tmp/data'; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir=junk-dir; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir=junk/dir; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir=OFF; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir=default; -SELECT @@global.wsrep_data_home_dir; +SELECT COUNT(@@global.wsrep_data_home_dir); --echo --echo # invalid values --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.wsrep_data_home_dir=NULL; +--echo # +--echo # MDEV-6717 : wsrep_data_home_dir should default to @@datadir +--echo # +SELECT @@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='datadir'; +SELECT @@GLOBAL.wsrep_data_home_dir = VARIABLE_VALUE FROM +INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='wsrep_data_home_dir'; + --echo # End of test diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8fbd96ed662..0868d0ebdfd 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3707,7 +3707,7 @@ static Sys_var_charptr Sys_wsrep_provider_options( static Sys_var_charptr Sys_wsrep_data_home_dir( "wsrep_data_home_dir", "home directory for wsrep provider", READ_ONLY GLOBAL_VAR(wsrep_data_home_dir), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(""), + IN_FS_CHARSET, DEFAULT(mysql_real_data_home), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_charptr Sys_wsrep_cluster_name( diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 687481fa1da..7223e176c56 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -538,9 +538,6 @@ int wsrep_init() wsrep->provider_vendor, sizeof(provider_vendor) - 1); } - if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) - wsrep_data_home_dir = mysql_real_data_home; - char node_addr[512]= { 0, }; size_t const node_addr_max= sizeof(node_addr) - 1; if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) From be055b38351797b938d7bf8af5814cbefe4f8b34 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 9 Sep 2014 19:05:25 -0400 Subject: [PATCH 186/294] Minor improvements in mtr and wsrep test files. --- mysql-test/include/galera_init.inc | 1 + mysql-test/include/have_wsrep_enabled.inc | 2 +- mysql-test/include/have_wsrep_provider.inc | 6 ++ mysql-test/include/wait_until_ready.inc | 34 ++++++++++ mysql-test/mysql-test-run.pl | 65 ++++++++----------- ...ve_wsrep.require => have_wsrep_on.require} | 0 mysql-test/suite/wsrep/t/binlog_format.test | 2 +- 7 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 mysql-test/include/have_wsrep_provider.inc create mode 100644 mysql-test/include/wait_until_ready.inc rename mysql-test/r/{have_wsrep.require => have_wsrep_on.require} (100%) diff --git a/mysql-test/include/galera_init.inc b/mysql-test/include/galera_init.inc index 79591973862..7c79d6fc138 100644 --- a/mysql-test/include/galera_init.inc +++ b/mysql-test/include/galera_init.inc @@ -11,6 +11,7 @@ # Number of nodes in the cluster. # +--source include/have_wsrep_provider.inc --source include/have_wsrep_enabled.inc --let $_galera_node= $galera_cluster_size diff --git a/mysql-test/include/have_wsrep_enabled.inc b/mysql-test/include/have_wsrep_enabled.inc index edb919fd852..4b322f769c7 100644 --- a/mysql-test/include/have_wsrep_enabled.inc +++ b/mysql-test/include/have_wsrep_enabled.inc @@ -3,7 +3,7 @@ --source include/have_wsrep.inc ---require r/have_wsrep.require +--require r/have_wsrep_on.require disable_query_log; SHOW VARIABLES LIKE 'wsrep_on'; enable_query_log; diff --git a/mysql-test/include/have_wsrep_provider.inc b/mysql-test/include/have_wsrep_provider.inc new file mode 100644 index 00000000000..818abdd43b0 --- /dev/null +++ b/mysql-test/include/have_wsrep_provider.inc @@ -0,0 +1,6 @@ +if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE + VARIABLE_NAME LIKE 'wsrep_provider' AND VARIABLE_VALUE NOT LIKE 'none'`) +{ + --skip Test requires wsrep provider library (libgalera_smm.so) +} + diff --git a/mysql-test/include/wait_until_ready.inc b/mysql-test/include/wait_until_ready.inc new file mode 100644 index 00000000000..e7a6940975a --- /dev/null +++ b/mysql-test/include/wait_until_ready.inc @@ -0,0 +1,34 @@ +# If wsrep patch is enabled, wait for a minute until node is ready. +# Note: include/wait_for_status_var.inc cannot be used here, as server rejects +# all commands except SHOW & SET until its ready. (see wsrep_ready status +# variable) + +--disable_result_log +--disable_query_log +--enable_reconnect + +let $counter= 600; + +# Check if wsrep_ready status variable exists. +if (`SHOW STATUS LIKE 'wsrep_ready'`) +{ + let $wsrep_ready= query_get_value("SHOW STATUS LIKE 'wsrep_ready'", Value, 1); + + while ($wsrep_ready == 'OFF') + { + if (!$counter) + { + echo ===============================================; + echo Node still not ready after a minute, giving up!; + echo ===============================================; + die; + } + dec $counter; + sleep 0.1; + let $wsrep_ready= query_get_value("SHOW STATUS LIKE 'wsrep_ready'", Value, 1); + } +} + +--disable_reconnect +--enable_query_log +--enable_result_log diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c0b4598663d..77e33fbaae1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -135,7 +135,6 @@ my $opt_start; my $opt_start_dirty; my $opt_start_exit; my $start_only; -my $file_wsrep_provider; END { if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) @@ -2395,24 +2394,6 @@ sub environment_setup { $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log; } - # ---------------------------------------------------- - # Setup env for wsrep - # ---------------------------------------------------- - if (have_wsrep()) { - if (defined $ENV{'WSREP_PROVIDER'} ) { - # Nothing needs to be done! WSREP_PROVIDER env is already set & checked; - # will be used. - } else { - $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; - } - - if ((defined $ENV{'WSREP_PROVIDER'}) && ($ENV{'WSREP_PROVIDER'} ne "")) { - mtr_verbose("WSREP_PROVIDER set to $ENV{'WSREP_PROVIDER'}"); - } else { - mtr_verbose("WSREP_PROVIDER isn't available"); - } - } - # ---------------------------------------------------- # mysql clients # ---------------------------------------------------- @@ -3181,32 +3162,38 @@ sub have_wsrep() { return defined $wsrep_on } -sub check_wsrep_provider_env { - if (defined $ENV{'WSREP_PROVIDER'}) { - if (mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") { - mtr_error("WSREP_PROVIDER env set to an invalid path"); - return 0; # error - } - # Ok, WSREP_PROVIDER set to a valid path. - return 1; - } - # Ok, WSREP_PROVIDER not defined. - return 2; -} - sub check_wsrep_support() { if (have_wsrep()) { mtr_report(" - binaries built with wsrep patch"); - $file_wsrep_provider= - mtr_file_exists("/usr/lib/galera/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so"); + # Add galera test suites + mtr_report(" - adding wsrep, galera to default test suites"); + push @DEFAULT_SUITES, qw(wsrep galera); - if ((check_wsrep_provider_env() == 1) || ($file_wsrep_provider ne "")) { - # Add galera test suites - mtr_report(" - adding wsrep, galera to default test suites"); - push @DEFAULT_SUITES, qw(wsrep galera); + # Check whether WSREP_PROVIDER environment variable is set. + if (defined $ENV{'WSREP_PROVIDER'}) { + if ((mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") && + ($ENV{'WSREP_PROVIDER'} ne "none")) { + mtr_error("WSREP_PROVIDER env set to an invalid path"); + } + # WSREP_PROVIDER is valid; set to a valid path or "none"). + mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); + } else { + # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider + # library. + my $file_wsrep_provider= + mtr_file_exists("/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"); + + if ($file_wsrep_provider ne "") { + # wsrep provider library found ! + mtr_verbose("wsrep provider library found : $file_wsrep_provider"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + } else { + mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); + $ENV{'WSREP_PROVIDER'}= "none"; + } } } } diff --git a/mysql-test/r/have_wsrep.require b/mysql-test/r/have_wsrep_on.require similarity index 100% rename from mysql-test/r/have_wsrep.require rename to mysql-test/r/have_wsrep_on.require diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 99d34873512..d2035b28550 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,4 +1,4 @@ ---source include/have_wsrep_enabled.inc +--source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc # # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT From 5f3cfbb59d673eb594497121e9fc0d1d4f3e9d2f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 16 Sep 2014 12:55:29 -0400 Subject: [PATCH 187/294] Updated mysqld--help test and result (MDEV-6717, MDEV-6659). --- mysql-test/r/mysqld--help.result | 3 +-- mysql-test/t/mysqld--help.test | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 49039b4616a..5407745a125 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1198,7 +1198,6 @@ wsrep-certify-nonPK TRUE wsrep-cluster-address wsrep-cluster-name my_wsrep_cluster wsrep-convert-LOCK-to-trx FALSE -wsrep-data-home-dir wsrep-dbug-option wsrep-debug FALSE wsrep-desync FALSE @@ -1212,7 +1211,7 @@ wsrep-mysql-replication-bundle 0 wsrep-node-address wsrep-node-incoming-address AUTO wsrep-notify-cmd -wsrep-on FALSE +wsrep-on TRUE wsrep-provider none wsrep-provider-options wsrep-recover FALSE diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 4e7a4ff87ac..b28cc8bfd8d 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -20,7 +20,8 @@ perl; # their paths may vary: @skipvars=qw/basedir open-files-limit general-log-file log plugin-dir log-slow-queries pid-file slow-query-log-file log-basename - datadir slave-load-tmpdir tmpdir socket wsrep-node-name/; + datadir slave-load-tmpdir tmpdir socket wsrep-node-name + wsrep-data-home-dir/; # Plugins which may or may not be there: @plugins=qw/innodb ndb archive blackhole federated partition ndbcluster From 99b449bbb816a2467257c60fb6967b615db2ef4f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 17 Sep 2014 09:53:06 -0400 Subject: [PATCH 188/294] Reverting version change to match the version of supporting packages available on buildbot. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ae997143dac..67a35621511 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=40 +MYSQL_VERSION_PATCH=39 MYSQL_VERSION_EXTRA= From 9a0566b09b075f29ff5f9f8b3a70b473433e6c58 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 17 Sep 2014 14:12:00 -0400 Subject: [PATCH 189/294] MDEV-6447: Galera: Enable QC * Added galera/query_cache test * Merged patch for lp:1296403 --- mysql-test/suite/galera/r/query_cache.result | 1645 ++++++++++++++++++ mysql-test/suite/galera/t/query_cache.test | 1002 +++++++++++ sql/wsrep_check_opts.cc | 4 + sql/wsrep_mysqld.cc | 6 +- 4 files changed, 2656 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/query_cache.result create mode 100644 mysql-test/suite/galera/t/query_cache.test diff --git a/mysql-test/suite/galera/r/query_cache.result b/mysql-test/suite/galera/r/query_cache.result new file mode 100644 index 00000000000..4b1b950e5c3 --- /dev/null +++ b/mysql-test/suite/galera/r/query_cache.result @@ -0,0 +1,1645 @@ + +# Execute FLUSH/RESET commands. +# On node-1 +SET @query_cache_size_saved=@@GLOBAL.query_cache_size; +SET @query_cache_type_saved=@@GLOBAL.query_cache_type; +set GLOBAL query_cache_size=1355776; +flush query cache; +reset query cache; +flush status; +# On node-2 +SET @query_cache_size_saved=@@GLOBAL.query_cache_size; +SET @query_cache_type_saved=@@GLOBAL.query_cache_type; +set GLOBAL query_cache_size=1355776; +flush query cache; +reset query cache; +flush status; +# On node-1 +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +select sql_no_cache * from t1; +a +1 +2 +3 +select length(now()) from t1; +length(now()) +19 +19 +19 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +select sql_no_cache * from t1; +a +1 +2 +3 +select length(now()) from t1; +length(now()) +19 +19 +19 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-1 +delete from t1 where a=1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-1 +select * from t1; +a +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +select * from t1; +a +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-1 +update t1 set a=1 where a=3; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-1 +select * from t1; +a +2 +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +select * from t1; +a +2 +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-1 +drop table t1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +# On node-2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 + +# On node-1 +create table t1 (a int not null) ENGINE=MyISAM; +insert into t1 values (1),(2),(3); +create table t2 (a int not null) ENGINE=MyISAM; +insert into t2 values (4),(5),(6); +create table t3 (a int not null) engine=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; +select * from t3; +a +1 +2 +3 +4 +5 +6 +select * from t3; +a +1 +2 +3 +4 +5 +6 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +insert into t2 values (7); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +insert into t3 values (8); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select * from t3; +a +1 +2 +3 +8 +4 +5 +6 +7 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +update t2 set a=9 where a=7; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select * from t1; +a +1 +2 +3 +8 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +update t3 set a=10 where a=1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select * from t3; +a +10 +2 +3 +8 +4 +5 +6 +9 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +delete from t2 where a=9; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select * from t1; +a +10 +2 +3 +8 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +delete from t3 where a=10; +select * from t3; +a +2 +3 +8 +4 +5 +6 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +# On node-2 +select * from t3; +a +select * from t3; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop table t1, t2, t3; +# On node-1 +set query_cache_type=demand; +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select sql_cache * from t1 union select * from t1; +a +1 +2 +3 +set query_cache_type=2; +select sql_cache * from t1 union select * from t1; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +set query_cache_type=on; +# On node-2 +set query_cache_type=demand; +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +select sql_cache * from t1 union select * from t1; +a +1 +2 +3 +set query_cache_type=2; +select sql_cache * from t1 union select * from t1; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +set query_cache_type=on; +# On node-1 +reset query cache; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +# On node-2 +reset query cache; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +# On node-1 +select sql_no_cache * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +# On node-2 +select sql_no_cache * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +drop table t1; +# On node-1 +create table t1 (a text not null) engine=innodb; +select CONNECTION_ID() from t1; +CONNECTION_ID() +select FOUND_ROWS(); +FOUND_ROWS() +0 +select NOW() from t1; +NOW() +select CURDATE() from t1; +CURDATE() +select CURTIME() from t1; +CURTIME() +select DATABASE() from t1; +DATABASE() +select ENCRYPT("test") from t1; +ENCRYPT("test") +select LAST_INSERT_ID() from t1; +LAST_INSERT_ID() +select RAND() from t1; +RAND() +select UNIX_TIMESTAMP() from t1; +UNIX_TIMESTAMP() +select USER() from t1; +USER() +select CURRENT_USER() from t1; +CURRENT_USER() +select benchmark(1,1) from t1; +benchmark(1,1) +explain extended select benchmark(1,1) from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1003 select benchmark(1,1) AS `benchmark(1,1)` from `test`.`t1` +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +# On node-2 +select CONNECTION_ID() from t1; +CONNECTION_ID() +select FOUND_ROWS(); +FOUND_ROWS() +0 +select NOW() from t1; +NOW() +select CURDATE() from t1; +CURDATE() +select CURTIME() from t1; +CURTIME() +select DATABASE() from t1; +DATABASE() +select ENCRYPT("test") from t1; +ENCRYPT("test") +select LAST_INSERT_ID() from t1; +LAST_INSERT_ID() +select RAND() from t1; +RAND() +select UNIX_TIMESTAMP() from t1; +UNIX_TIMESTAMP() +select USER() from t1; +USER() +select CURRENT_USER() from t1; +CURRENT_USER() +select benchmark(1,1) from t1; +benchmark(1,1) +explain extended select benchmark(1,1) from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1003 select benchmark(1,1) AS `benchmark(1,1)` from `test`.`t1` +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +drop table t1; +# On node-1 +create database mysqltest; +create table mysqltest.t1 (i int not null auto_increment, a int, primary key +(i)) engine=innodb; +insert into mysqltest.t1 values (1, 1); +select * from mysqltest.t1 where i is null; +i a +create table t1(a int) engine=innodb; +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +select * from mysqltest.t1; +i a +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +# On node-2 +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +select * from mysqltest.t1; +i a +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +drop database mysqltest; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +drop table t1; +# On node-1 +create table t1 (a char(1) not null collate koi8r_general_ci) engine=innodb; +insert into t1 values(_koi8r"á"); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +set CHARACTER SET koi8r; +select * from t1; +a +à +set CHARACTER SET cp1251_koi8; +select * from t1; +a +ö +set CHARACTER SET DEFAULT; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 4 +# On node-2 +set CHARACTER SET koi8r; +select * from t1; +a +à +set CHARACTER SET cp1251_koi8; +select * from t1; +a +ö +set CHARACTER SET DEFAULT; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 3 +drop table t1; +# On node-1 +create database if not exists mysqltest; +create table mysqltest.t1 (i int not null) engine=innodb; +create table t1 (i int not null) engine=innodb; +insert into mysqltest.t1 (i) values (1); +insert into t1 (i) values (2); +select * from t1; +i +2 +use mysqltest; +select * from t1; +i +1 +select * from t1; +i +1 +use test; +select * from t1; +i +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 6 +# On node-2 +select * from t1; +i +2 +use mysqltest; +select * from t1; +i +1 +select * from t1; +i +1 +use test; +select * from t1; +i +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 5 +drop database mysqltest; +drop table t1; +# On node-1 +create table t1 (i int not null) engine=innodb; +insert into t1 (i) values (1),(2),(3),(4); +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +i +1 +2 +select FOUND_ROWS(); +FOUND_ROWS() +4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 6 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +select * from t1 where i=1; +i +1 +select FOUND_ROWS(); +FOUND_ROWS() +1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 6 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +i +1 +2 +select FOUND_ROWS(); +FOUND_ROWS() +4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 7 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +select * from t1 where i=1; +i +1 +select FOUND_ROWS(); +FOUND_ROWS() +1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 8 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +# On node-2 +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +i +1 +2 +select FOUND_ROWS(); +FOUND_ROWS() +4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 5 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +select * from t1 where i=1; +i +1 +select FOUND_ROWS(); +FOUND_ROWS() +1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 5 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +i +1 +2 +select FOUND_ROWS(); +FOUND_ROWS() +4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 6 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +select * from t1 where i=1; +i +1 +select FOUND_ROWS(); +FOUND_ROWS() +1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 7 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +drop table t1; +# On node-2 +flush query cache; +reset query cache; +# On node-1 +flush query cache; +reset query cache; +create table t1 (a int not null) ENGINE=MYISAM; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 9 +insert delayed into t1 values (4); +select a from t1; +a +1 +2 +3 +4 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 9 +# On node-2 +select * from t1; +a +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 8 +insert delayed into t1 values (4); +select a from t1; +a +4 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 8 +drop table t1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 8 +# On node-1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 9 +# On node-2 +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 4096 +set GLOBAL query_cache_min_res_unit=1001; +Warnings: +Warning 1292 Truncated incorrect query_cache_min_res_unit value: '1001' +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 1000 +# On node-1 +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 4096 +set GLOBAL query_cache_min_res_unit=1001; +Warnings: +Warning 1292 Truncated incorrect query_cache_min_res_unit value: '1001' +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 1000 +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +create table t2 (a int not null) engine=innodb; +insert into t2 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +select * from t2; +a +1 +2 +3 +select * from t2; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +# On node-2 +select * from t1; +a +1 +2 +3 +select * from t1; +a +1 +2 +3 +select * from t2; +a +1 +2 +3 +select * from t2; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 10 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +drop table t1; +select a from t2; +a +1 +2 +3 +select a from t2; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +set GLOBAL query_cache_min_res_unit=default; +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 4096 +# On node-1 +select a from t2; +a +1 +2 +3 +select a from t2; +a +1 +2 +3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +drop table t2; +set GLOBAL query_cache_min_res_unit=default; +show global variables like "query_cache_min_res_unit"; +Variable_name Value +query_cache_min_res_unit 4096 +# On node-1 +create table t1 (a int not null) engine=innodb; +insert into t1 values (1); +select "aaa" from t1; +aaa +aaa +select "AAA" from t1; +AAA +AAA +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +# On node-2 +select "aaa" from t1; +aaa +aaa +select "AAA" from t1; +AAA +AAA +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +drop table t1; +# On node-1 +create table t1 (a int) engine=innodb; +set GLOBAL query_cache_size=1000; +Warnings: +Warning 1292 Truncated incorrect query_cache_size value: '1000' +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=1024; +Warnings: +Warning 1282 Query cache failed to set size 1024; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=10240; +Warnings: +Warning 1282 Query cache failed to set size 10240; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=20480; +Warnings: +Warning 1282 Query cache failed to set size 20480; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=40960; +Warnings: +Warning 1282 Query cache failed to set size 40960; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 51200 +select * from t1; +a +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 61440 +select * from t1; +a +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 81920 +select * from t1; +a +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 102400 +select * from t1; +a +# On node-2 +set GLOBAL query_cache_size=1000; +Warnings: +Warning 1292 Truncated incorrect query_cache_size value: '1000' +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=1024; +Warnings: +Warning 1282 Query cache failed to set size 1024; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=10240; +Warnings: +Warning 1282 Query cache failed to set size 10240; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=20480; +Warnings: +Warning 1282 Query cache failed to set size 20480; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=40960; +Warnings: +Warning 1282 Query cache failed to set size 40960; new query cache size is 0 +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 0 +select * from t1; +a +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 51200 +select * from t1; +a +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 61440 +select * from t1; +a +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 81920 +select * from t1; +a +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +Variable_name Value +query_cache_size 102400 +select * from t1; +a +drop table t1; +# On node-1 +set GLOBAL query_cache_size=1048576; +create table t1 (i int not null) engine=innodb; +create table t2 (i int not null) engine=innodb; +select * from t1; +i +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +create temporary table t3 (i int not null); +select * from t2; +i +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +select * from t3; +i +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +update t1 set i=(select distinct 1 from (select * from t2) a); +drop table t3; +# On node-2 +set GLOBAL query_cache_size=1048576; +select * from t1; +i +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +select * from t2; +i +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +drop table t1, t2; +# On node-1 +use mysql; +select * from db; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +use test; +select * from mysql.db; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +# On node-1 +create table t1(id int auto_increment primary key) engine=innodb; +insert into t1 values (1), (2), (3); +select * from t1; +id +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +# On node-2 +select * from t1; +id +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +# On node-1 +alter table t1 rename to t2; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +# On node-2 +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +drop table t2; +# On node-1 +create table t1 (word char(20) not null) engine=innodb; +select * from t1; +word +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +load data infile 'MYSQLTEST_VARDIR/std_data/words.dat' into table t1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +select count(*) from t1; +count(*) +70 +# On node-2 +select count(*) from t1; +count(*) +70 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +load data infile 'MYSQLTEST_VARDIR/std_data/words.dat' into table t1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +select count(*) from t1; +count(*) +140 +drop table t1; +# On node-1 +create table t1 (a int) engine=innodb; +insert into t1 values (1),(2),(3); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +select * from t1 into outfile "query_cache.out.file"; +select * from t1 into outfile "query_cache.out.file"; +ERROR HY000: File 'query_cache.out.file' already exists +select * from t1 limit 1 into dumpfile "query_cache.dump.file"; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +drop table t1; +# On node-1 +create table t1 (a int) engine=innodb; +insert into t1 values (1),(2); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +select * from t1; +a +1 +2 +SET SQL_SELECT_LIMIT=1; +select * from t1; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +SET SQL_SELECT_LIMIT=DEFAULT; +# On node-2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +select * from t1; +a +1 +2 +SET SQL_SELECT_LIMIT=1; +select * from t1; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +SET SQL_SELECT_LIMIT=DEFAULT; +drop table t1; +# On node-1 +create table t1 (a int not null) engine=innodb; +create table t2 (a int not null) engine=innodb; +set query_cache_wlock_invalidate=1; +create view v1 as select * from t1; +select * from t1; +a +select * from t2; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +lock table t1 write, t2 read; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +unlock table; +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +lock table v1 write; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +unlock table; +drop view v1; +set query_cache_wlock_invalidate=default; +# On node-2 +set query_cache_wlock_invalidate=1; +create view v1 as select * from t1; +select * from t1; +a +select * from t2; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +lock table t1 write, t2 read; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +unlock table; +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +lock table v1 write; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +unlock table; +drop view v1; +set query_cache_wlock_invalidate=default; +drop table t1,t2; +# On node-1 +create table t1 (id int primary key) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +id +1 +2 +3 +create temporary table t1 (a int not null auto_increment primary key); +select * from t1; +a +drop table t1; +drop table t1; +# On node-1 +SET NAMES koi8r; +CREATE TABLE t1 (a char(1) character set koi8r) engine=innodb; +INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Ã'); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +Warning 1265 Data truncated for column 'a' at row 2 +SELECT a,'Â','â'='Â' FROM t1; +a  'â'='Â' +à  0 +à  0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +set collation_connection=koi8r_bin; +SELECT a,'Â','â'='Â' FROM t1; +a  'â'='Â' +à  0 +à  0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +set character_set_client=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +a ç? 'ç?'='ç?' +à ç? 1 +à ç? 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 3 +set character_set_results=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +a Ã? 'â'='Â' +ö Ã? 1 +ö Ã? 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 4 +SET NAMES default; +# On node-2 +SELECT a,'Â','â'='Â' FROM t1; +a  'â'='Â' +?  0 +?  0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +set collation_connection=koi8r_bin; +SELECT a,'Â','â'='Â' FROM t1; +a ?? 'â'='Â' +? ?? 1 +? ?? 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +set character_set_client=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +a ?? '??'='?‚' +? ?? 1 +? ?? 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 3 +set character_set_results=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +a Ã? 'â'='Â' +ö Ã? 1 +ö Ã? 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 4 +drop table t1; +# On node-1 +create table t1 (a int) engine=innodb; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 46 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +/**/ select * from t1; +a +/**/ select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 47 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 13 +# On node-2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 38 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 11 +/**/ select * from t1; +a +/**/ select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 39 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 12 +drop table t1; +# On node-1 +set session query_cache_type = 2; +create table t1(a int) engine=innodb; +select table_name from information_schema.tables +where table_schema="test"; +table_name +t1 +drop table t1; +select table_name from information_schema.tables +where table_schema="test"; +table_name +set session query_cache_type = 1; +set global query_cache_size=1024*1024; +flush query cache; +create table t1 ( a int ) engine=myisam; +insert into t1 values (1); +select a from t1; +a +1 +select a from t1; +a +1 +show status like 'qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 14 +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +show status like 'qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 14 +# On node-2 +select a from t1; +a +select a from t1; +a +show status like 'qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 13 +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +show status like 'qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 13 +drop table t1; +# Restore original settings. +# On node-1 +SET GLOBAL query_cache_size=@query_cache_size_saved; +SET GLOBAL query_cache_type=@query_cache_type_saved; + +# On node-2 +SET GLOBAL query_cache_size=@query_cache_size_saved; +SET GLOBAL query_cache_type=@query_cache_type_saved; +# End of test diff --git a/mysql-test/suite/galera/t/query_cache.test b/mysql-test/suite/galera/t/query_cache.test new file mode 100644 index 00000000000..24ed8ecd077 --- /dev/null +++ b/mysql-test/suite/galera/t/query_cache.test @@ -0,0 +1,1002 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_query_cache.inc + +--echo +--echo # Execute FLUSH/RESET commands. +--echo # On node-1 +--connection node_1 +SET @query_cache_size_saved=@@GLOBAL.query_cache_size; +SET @query_cache_type_saved=@@GLOBAL.query_cache_type; +set GLOBAL query_cache_size=1355776; +flush query cache; # This crashed in some versions +reset query cache; +flush status; + +--echo # On node-2 +--connection node_2 +SET @query_cache_size_saved=@@GLOBAL.query_cache_size; +SET @query_cache_type_saved=@@GLOBAL.query_cache_type; +set GLOBAL query_cache_size=1355776; +flush query cache; # This crashed in some versions +reset query cache; +flush status; + +# +# INSERT/UPDATE/DELETE/DROP/SELECT +# + +--echo # On node-1 +--connection node_1 +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +select * from t1; +select sql_no_cache * from t1; +select length(now()) from t1; + +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 + +select * from t1; +select * from t1; +select sql_no_cache * from t1; +select length(now()) from t1; + +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; + +# DELETE should invalidate cache on both the nodes. +--echo # On node-1 +--connection node_1 +delete from t1 where a=1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# Add a SELECT to the cache. +--echo # On node-1 +--connection node_1 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# UPDATE should invalidate cache on both the nodes. +--echo # On node-1 +--connection node_1 +update t1 set a=1 where a=3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# Add a SELECT to the cache. +--echo # On node-1 +--connection node_1 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# DROP should invalidate cache on both the nodes. +--echo # On node-1 +--connection node_1 +drop table t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# +# MERGE TABLES with INSERT/UPDATE and DELETE +# +--echo +--echo # On node-1 +--connection node_1 +create table t1 (a int not null) ENGINE=MyISAM; +insert into t1 values (1),(2),(3); +create table t2 (a int not null) ENGINE=MyISAM; +insert into t2 values (4),(5),(6); +create table t3 (a int not null) engine=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; +# insert +select * from t3; +select * from t3; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +insert into t2 values (7); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1; +select * from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +insert into t3 values (8); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +# update +select * from t3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +update t2 set a=9 where a=7; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +update t3 set a=10 where a=1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +#delete +select * from t3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +delete from t2 where a=9; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +delete from t3 where a=10; +select * from t3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +# MERGE table, expect no records. +select * from t3; +select * from t3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; + +drop table t1, t2, t3; + +# +# SELECT SQL_CACHE ... +# +--echo # On node-1 +--connection node_1 +set query_cache_type=demand; +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select sql_cache * from t1 union select * from t1; +set query_cache_type=2; +select sql_cache * from t1 union select * from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +set query_cache_type=on; + +--echo # On node-2 +--connection node_2 +set query_cache_type=demand; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select sql_cache * from t1 union select * from t1; +set query_cache_type=2; +select sql_cache * from t1 union select * from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +set query_cache_type=on; + +# +# RESET QUERY CACHE +# +--echo # On node-1 +--connection node_1 +reset query cache; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +--echo # On node-2 +--connection node_2 +reset query cache; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# +# SELECT SQL_NO_CACHE +# +--echo # On node-1 +--connection node_1 +select sql_no_cache * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +--echo # On node-2 +--connection node_2 +select sql_no_cache * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; + +# +# Check that queries that uses NOW(), LAST_INSERT_ID()... are not cached. +# +--echo # On node-1 +--connection node_1 +create table t1 (a text not null) engine=innodb; +select CONNECTION_ID() from t1; +select FOUND_ROWS(); +select NOW() from t1; +select CURDATE() from t1; +select CURTIME() from t1; +select DATABASE() from t1; +select ENCRYPT("test") from t1; +select LAST_INSERT_ID() from t1; +select RAND() from t1; +select UNIX_TIMESTAMP() from t1; +select USER() from t1; +select CURRENT_USER() from t1; +select benchmark(1,1) from t1; +explain extended select benchmark(1,1) from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +--echo # On node-2 +--connection node_2 +select CONNECTION_ID() from t1; +select FOUND_ROWS(); +select NOW() from t1; +select CURDATE() from t1; +select CURTIME() from t1; +select DATABASE() from t1; +select ENCRYPT("test") from t1; +select LAST_INSERT_ID() from t1; +select RAND() from t1; +select UNIX_TIMESTAMP() from t1; +select USER() from t1; +select CURRENT_USER() from t1; +select benchmark(1,1) from t1; +explain extended select benchmark(1,1) from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; + +# +# Non-cachable ODBC work around (and prepare cache for drop database) +# +--echo # On node-1 +--connection node_1 +create database mysqltest; +create table mysqltest.t1 (i int not null auto_increment, a int, primary key + (i)) engine=innodb; +insert into mysqltest.t1 values (1, 1); +select * from mysqltest.t1 where i is null; +create table t1(a int) engine=innodb; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from mysqltest.t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from mysqltest.t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +# +# drop db +# +drop database mysqltest; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; + +# +# Charset conversion (cp1251_koi8 always present) +# Note: Queries using different default character sets are cached separately. +# +--echo # On node-1 +--connection node_1 +create table t1 (a char(1) not null collate koi8r_general_ci) engine=innodb; +insert into t1 values(_koi8r"á"); +set CHARACTER SET koi8r; +select * from t1; +set CHARACTER SET cp1251_koi8; +select * from t1; +set CHARACTER SET DEFAULT; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +set CHARACTER SET koi8r; +select * from t1; +set CHARACTER SET cp1251_koi8; +select * from t1; +set CHARACTER SET DEFAULT; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; + +# +# Same tables in different dbs +# +--echo # On node-1 +--connection node_1 +create database if not exists mysqltest; +create table mysqltest.t1 (i int not null) engine=innodb; +create table t1 (i int not null) engine=innodb; +insert into mysqltest.t1 (i) values (1); +insert into t1 (i) values (2); + +select * from t1; +use mysqltest; +select * from t1; +select * from t1; +use test; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +use mysqltest; +select * from t1; +select * from t1; +use test; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop database mysqltest; +drop table t1; + +# +# FOUND_ROWS() +# +--echo # On node-1 +--connection node_1 +create table t1 (i int not null) engine=innodb; +insert into t1 (i) values (1),(2),(3),(4); + +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select * from t1 where i=1; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select * from t1 where i=1; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +--echo # On node-2 +--connection node_2 +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select * from t1 where i=1; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select SQL_CALC_FOUND_ROWS * from t1 limit 2; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select * from t1 where i=1; +select FOUND_ROWS(); +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +drop table t1; + +# +# Test insert delayed (MYISAM) +# + +--echo # On node-2 +--connection node_2 +flush query cache; +reset query cache; + +--echo # On node-1 +--connection node_1 +flush query cache; +reset query cache; + +create table t1 (a int not null) ENGINE=MYISAM; +insert into t1 values (1),(2),(3); +select * from t1; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +insert delayed into t1 values (4); +--sleep 5 # Wait for insert delayed to be executed. +select a from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +insert delayed into t1 values (4); +--sleep 5 # Wait for insert delayed to be executed. +select a from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +drop table t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-1 +--connection node_1 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# +# Test of min result data unit size changing +# +--echo # On node-2 +--connection node_2 +show global variables like "query_cache_min_res_unit"; +set GLOBAL query_cache_min_res_unit=1001; +show global variables like "query_cache_min_res_unit"; + +--echo # On node-1 +--connection node_1 +show global variables like "query_cache_min_res_unit"; +set GLOBAL query_cache_min_res_unit=1001; +show global variables like "query_cache_min_res_unit"; +create table t1 (a int not null) engine=innodb; +insert into t1 values (1),(2),(3); +create table t2 (a int not null) engine=innodb; +insert into t2 values (1),(2),(3); +select * from t1; +select * from t1; +select * from t2; +select * from t2; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +--echo # On node-2 +--connection node_2 +select * from t1; +select * from t1; +select * from t2; +select * from t2; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +drop table t1; +select a from t2; +select a from t2; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +set GLOBAL query_cache_min_res_unit=default; +show global variables like "query_cache_min_res_unit"; + +--echo # On node-1 +--connection node_1 +select a from t2; +select a from t2; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +drop table t2; +set GLOBAL query_cache_min_res_unit=default; +show global variables like "query_cache_min_res_unit"; + +# +# Case sensitive test +# +--echo # On node-1 +--connection node_1 +create table t1 (a int not null) engine=innodb; +insert into t1 values (1); +select "aaa" from t1; +select "AAA" from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select "aaa" from t1; +select "AAA" from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; + +# +# Test of query cache resizing +# +--echo # On node-1 +--connection node_1 +create table t1 (a int) engine=innodb; +set GLOBAL query_cache_size=1000; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=1024; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=10240; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=20480; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=40960; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +select * from t1; + +--echo # On node-2 +--connection node_2 +set GLOBAL query_cache_size=1000; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=1024; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=10240; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=20480; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=40960; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=51200; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=61440; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=81920; +show global variables like "query_cache_size"; +select * from t1; +set GLOBAL query_cache_size=102400; +show global variables like "query_cache_size"; +select * from t1; + +drop table t1; + +# +# Temporary tables (ignored by Galera) +# +--echo # On node-1 +--connection node_1 +set GLOBAL query_cache_size=1048576; +create table t1 (i int not null) engine=innodb; +create table t2 (i int not null) engine=innodb; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +create temporary table t3 (i int not null); +select * from t2; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t3; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +update t1 set i=(select distinct 1 from (select * from t2) a); +drop table t3; + +--echo # On node-2 +--connection node_2 +set GLOBAL query_cache_size=1048576; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t2; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +drop table t1, t2; + +# +# System databse test (no need to perform it on node_2) +# Note: Queries on system tables are not cached. +# +--echo # On node-1 +--connection node_1 +use mysql; +disable_result_log; +select * from db; +enable_result_log; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +use test; +disable_result_log; +select * from mysql.db; +enable_result_log; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# +# Simple rename test +# +--echo # On node-1 +--connection node_1 +create table t1(id int auto_increment primary key) engine=innodb; +insert into t1 values (1), (2), (3); +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-1 +--connection node_1 +alter table t1 rename to t2; +--error ER_NO_SUCH_TABLE +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +--error ER_NO_SUCH_TABLE +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t2; + +# +# Load data invalidation test +# +--echo # On node-1 +--connection node_1 +create table t1 (word char(20) not null) engine=innodb; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval load data infile '$MYSQLTEST_VARDIR/std_data/words.dat' into table t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select count(*) from t1; + +# Wait for "load data" to replicate. +--sleep 5 + +--echo # On node-2 +--connection node_2 +select count(*) from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval load data infile '$MYSQLTEST_VARDIR/std_data/words.dat' into table t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select count(*) from t1; + +drop table t1; + +# +# INTO OUTFILE/DUMPFILE test +# +--echo # On node-1 +--connection node_1 +create table t1 (a int) engine=innodb; +insert into t1 values (1),(2),(3); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1 into outfile "query_cache.out.file"; +--error ER_FILE_EXISTS_ERROR +select * from t1 into outfile "query_cache.out.file"; +select * from t1 limit 1 into dumpfile "query_cache.dump.file"; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +drop table t1; +let $datadir=`select @@datadir`; +--remove_file $datadir/test/query_cache.dump.file +--remove_file $datadir/test/query_cache.out.file + +# +# Test of SQL_SELECT_LIMIT +# +--echo # On node-1 +--connection node_1 +create table t1 (a int) engine=innodb; +insert into t1 values (1),(2); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1; +SET SQL_SELECT_LIMIT=1; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +SET SQL_SELECT_LIMIT=DEFAULT; + +--echo # On node-2 +--connection node_2 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +select * from t1; +SET SQL_SELECT_LIMIT=1; +select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +SET SQL_SELECT_LIMIT=DEFAULT; + +drop table t1; + +# +# WRITE LOCK & QC +# +--echo # On node-1 +--connection node_1 +create table t1 (a int not null) engine=innodb; +create table t2 (a int not null) engine=innodb; + +set query_cache_wlock_invalidate=1; +create view v1 as select * from t1; +select * from t1; +select * from t2; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +lock table t1 write, t2 read; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +unlock table; +select * from t1; +# Implicit locking of t1 does not invalidate QC +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +lock table v1 write; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +unlock table; +drop view v1; +set query_cache_wlock_invalidate=default; + +--echo # On node-2 +--connection node_2 +set query_cache_wlock_invalidate=1; +create view v1 as select * from t1; +select * from t1; +select * from t2; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +lock table t1 write, t2 read; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +unlock table; +select * from t1; +# Implicit locking of t1 does not invalidate QC +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +lock table v1 write; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +unlock table; +drop view v1; +set query_cache_wlock_invalidate=default; + +drop table t1,t2; + +# +# Hiding real table stored in query cache by temporary table +# +--echo # On node-1 +--connection node_1 +create table t1 (id int primary key) engine=innodb; +insert into t1 values (1),(2),(3); +select * from t1; +create temporary table t1 (a int not null auto_increment primary key); +select * from t1; +drop table t1; +drop table t1; + +# +# Test character set related variables: +# character_set_result +# character_set_client +# charactet_set_connection/collation_connection +# If at least one of the above variables has changed, +# the cached query can't be reused. In the below test +# absolutely the same query is used several times, +# SELECT should fetch different results for every instance. +# No hits should be produced. +# New cache entry should appear for every SELECT. +# + +--echo # On node-1 +--connection node_1 +SET NAMES koi8r; +CREATE TABLE t1 (a char(1) character set koi8r) engine=innodb; +INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Ã'); +# +# Run select +# +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# Change collation_connection and run the same query again +# +set collation_connection=koi8r_bin; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# Now change character_set_client and run the same query again +# +set character_set_client=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# And finally change character_set_results and run the same query again +# +set character_set_results=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +SET NAMES default; + +--echo # On node-2 +--connection node_2 +# +# Run select +# +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# Change collation_connection and run the same query again +# +set collation_connection=koi8r_bin; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# Now change character_set_client and run the same query again +# +set character_set_client=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; +# +# And finally change character_set_results and run the same query again +# +set character_set_results=cp1251; +SELECT a,'Â','â'='Â' FROM t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +drop table t1; + +# +# Comments before command +# +--echo # On node-1 +--connection node_1 +create table t1 (a int) engine=innodb; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +/**/ select * from t1; +/**/ select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +/**/ select * from t1; +/**/ select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; + +drop table t1; + +# +# Information schema & query cache test +# +--echo # On node-1 +--connection node_1 +set session query_cache_type = 2; +create table t1(a int) engine=innodb; +select table_name from information_schema.tables +where table_schema="test"; +drop table t1; +select table_name from information_schema.tables +where table_schema="test"; +# Bug #8480: REPAIR TABLE needs to flush the table from the query cache +set session query_cache_type = 1; +set global query_cache_size=1024*1024; +flush query cache; +create table t1 ( a int ) engine=myisam; # myisam for repair tables +insert into t1 values (1); +select a from t1; +select a from t1; +show status like 'qcache_queries_in_cache'; +show status like "Qcache_hits"; +repair table t1; +show status like 'qcache_queries_in_cache'; +show status like "Qcache_hits"; + +--echo # On node-2 +--connection node_2 +select a from t1; +select a from t1; +show status like 'qcache_queries_in_cache'; +show status like "Qcache_hits"; +repair table t1; +show status like 'qcache_queries_in_cache'; +show status like "Qcache_hits"; +drop table t1; + +--echo # Restore original settings. +--echo # On node-1 +--connection node_1 +SET GLOBAL query_cache_size=@query_cache_size_saved; +SET GLOBAL query_cache_type=@query_cache_type_saved; +--echo +--echo # On node-2 +--connection node_2 +SET GLOBAL query_cache_size=@query_cache_size_saved; +SET GLOBAL query_cache_type=@query_cache_type_saved; + +--echo # End of test diff --git a/sql/wsrep_check_opts.cc b/sql/wsrep_check_opts.cc index 5ec18c79978..75894061d3f 100644 --- a/sql/wsrep_check_opts.cc +++ b/sql/wsrep_check_opts.cc @@ -44,8 +44,10 @@ static struct opt opts[] = { "wsrep_sst_receive_address","AUTO"}, // mysqld.cc { "binlog_format", "ROW" }, // mysqld.cc { "wsrep_provider", "none" }, // mysqld.cc +#if 0 { "query_cache_type", "0" }, // mysqld.cc { "query_cache_size", "0" }, // mysqld.cc +#endif { "locked_in_memory", "0" }, // mysqld.cc { "wsrep_cluster_address", "0" }, // mysqld.cc { "locks_unsafe_for_binlog", "0" }, // ha_innodb.cc @@ -61,8 +63,10 @@ enum WSREP_SST_RECEIVE_ADDRESS, BINLOG_FORMAT, WSREP_PROVIDER, +#if 0 QUERY_CACHE_TYPE, QUERY_CACHE_SIZE, +#endif LOCKED_IN_MEMORY, WSREP_CLUSTER_ADDRESS, LOCKS_UNSAFE_FOR_BINLOG, diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 7223e176c56..ba802bba7e2 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -236,7 +236,11 @@ wsrep_view_handler_cb (void* app_ctx, wsrep_cluster_size, wsrep_local_index, view->proto_ver); /* Proceed further only if view is PRIMARY */ - if (WSREP_VIEW_PRIMARY != view->status) { + if (WSREP_VIEW_PRIMARY != view->status) + { + // query cache must be initialised by now + query_cache.flush(); + wsrep_ready_set(FALSE); new_status= WSREP_MEMBER_UNDEFINED; /* Always record local_uuid and local_seqno in non-prim since this From 5589509353bfc3222799cc66881117e95d82d68c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 17 Sep 2014 14:39:43 -0400 Subject: [PATCH 190/294] MDEV-6447: addendum, moving QC code within HAVE_QUERY_CACHE. --- sql/wsrep_mysqld.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index ba802bba7e2..60ced03a8b1 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -238,8 +238,10 @@ wsrep_view_handler_cb (void* app_ctx, /* 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); new_status= WSREP_MEMBER_UNDEFINED; From 851e428e4e94e22d14fab4694b3135011026f418 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 23 Sep 2014 14:03:13 -0400 Subject: [PATCH 191/294] Updated config files: - Removed QC restriction - Added bind-address Fixed file permissions for wsrep_sst_rsync.sh. --- debian/additions/my.cnf | 2 +- scripts/wsrep_sst_rsync.sh | 0 support-files/rpm/server.cnf | 2 +- support-files/wsrep.cnf.sh | 7 ------- 4 files changed, 2 insertions(+), 9 deletions(-) mode change 100755 => 100644 scripts/wsrep_sst_rsync.sh diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index eed29b90a2b..1e0b97bf0b7 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -162,7 +162,7 @@ innodb_flush_method = O_DIRECT #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 -#query_cache_size=0 +#bind-address=0.0.0.0 # # Optional setting #innodb_flush_log_at_trx_commit=0 diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh old mode 100755 new mode 100644 diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index 173abefa7e6..1fef0ed1f33 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -22,7 +22,7 @@ #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 -#query_cache_size=0 +#bind-address=0.0.0.0 # # Optional setting #innodb_flush_log_at_trx_commit=0 diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh index 756d4f6783b..a5390855ca1 100644 --- a/support-files/wsrep.cnf.sh +++ b/support-files/wsrep.cnf.sh @@ -21,13 +21,6 @@ default-storage-engine=innodb # to avoid issues with 'bulk mode inserts' using autoinc innodb_autoinc_lock_mode=2 -# This is a must for paralell applying -innodb_locks_unsafe_for_binlog=1 - -# Query Cache is not supported with wsrep -query_cache_size=0 -query_cache_type=0 - # Override bind-address # In some systems bind-address defaults to 127.0.0.1, and with mysqldump SST # it will have (most likely) disastrous consequences on donor node From 59277a7d83374bc293cd58f8be509a81792d829e Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 24 Sep 2014 12:16:09 -0400 Subject: [PATCH 192/294] Moved wsrep_slave_threads to optional settings. --- debian/additions/my.cnf | 2 +- support-files/rpm/server.cnf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index 1e0b97bf0b7..1f8bc0209eb 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -158,13 +158,13 @@ innodb_flush_method = O_DIRECT # Mandatory settings #wsrep_provider= #wsrep_cluster_address= -#wsrep_slave_threads=1 #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 #bind-address=0.0.0.0 # # Optional setting +#wsrep_slave_threads=1 #innodb_flush_log_at_trx_commit=0 [mysqldump] diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index 1fef0ed1f33..ee66a3149e9 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -18,13 +18,13 @@ # Mandatory settings #wsrep_provider= #wsrep_cluster_address= -#wsrep_slave_threads=1 #binlog_format=row #default_storage_engine=InnoDB #innodb_autoinc_lock_mode=2 #bind-address=0.0.0.0 # # Optional setting +#wsrep_slave_threads=1 #innodb_flush_log_at_trx_commit=0 # this is only for embedded server From 542968cf0a68070d7b45859a3148a602e2089a35 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 9 Oct 2014 18:28:14 -0400 Subject: [PATCH 193/294] bzr merge -r4015..4026 codership/5.5 --- CMakeLists.txt | 3 ++- cmake/wsrep.cmake | 4 ++-- mysql-test/include/mtr_warnings.sql | 23 ++++++++++++++----- sql/mysqld.cc | 25 +++++++++++++++++++++ sql/wsrep_applier.cc | 5 +++-- sql/wsrep_mysqld.cc | 13 ++++++++--- sql/wsrep_mysqld.h | 2 +- sql/wsrep_var.cc | 34 ++++++++++++++++++----------- 8 files changed, 82 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56b0de885c7..8fd966d1728 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,7 @@ INCLUDE(cpack_rpm) INCLUDE(cpack_deb) # Add macros +INCLUDE(wsrep) INCLUDE(character_sets) INCLUDE(zlib) INCLUDE(ssl) @@ -165,7 +166,6 @@ INCLUDE(ctest) INCLUDE(plugin) INCLUDE(install_macros) INCLUDE(mysql_add_executable) -INCLUDE(wsrep) # Handle options OPTION(DISABLE_SHARED @@ -286,6 +286,7 @@ MARK_AS_ADVANCED(WITH_FAST_MUTEXES) OPTION(WITH_INNODB_DISALLOW_WRITES "InnoDB freeze writes patch from Google" ${WITH_WSREP}) IF (WITH_INNODB_DISALLOW_WRITES) + MESSAGE(STATUS "INNODB_DISALLOW_WRITES") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") ENDIF() diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 97eb47fc587..50698b7bb8f 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -18,12 +18,12 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "10") +SET(WSREP_PATCH_VERSION "11") # MariaDB addition: Revision number of the last revision merged from # codership branch visible in @@visible_comment. # Branch : codership-mysql/5.5 -SET(WSREP_PATCH_REVNO "4014") # Should be updated on every merge. +SET(WSREP_PATCH_REVNO "4026") # Should be updated on every merge. # MariaDB: Obtain patch revision number: # Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set. diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index ed60568077c..5ef85411e79 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -227,12 +227,25 @@ INSERT INTO global_suppressions VALUES ("Slave I/O: Notifying master by SET @master_binlog_checksum= @@global.binlog_checksum failed with error.*"), /* - Galera-related warnings. + Galera suppressions */ - ("WSREP: Could not open saved state file for reading: .*"), - ("WSREP: last inactive check more than .* skipping check"), - ("WSREP: Gap in state sequence. Need state transfer."), - ("WSREP: Failed to prepare for incremental state transfer: .*"), + ("WSREP:.*down context.*"), + ("WSREP: Failed to send state UUID:.*"), + ("WSREP: wsrep_sst_receive_address is set to '127.0.0.1"), + ("WSREP: option --wsrep-casual-reads is deprecated"), + ("WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0"), + ("WSREP: Could not open saved state file for reading: "), + ("WSREP: access file\\(gvwstate\\.dat\\) failed\\(No such file or directory\\)"), + ("WSREP: Gap in state sequence\\. Need state transfer\\."), + ("WSREP: Failed to prepare for incremental state transfer: Local state UUID \\(00000000-0000-0000-0000-000000000000\\) does not match group state UUID"), + ("WSREP: No existing UUID has been found, so we assume that this is the first time that this server has been started\\. Generating a new UUID: "), + ("WSREP: last inactive check more than"), + ("WSREP: binlog cache not empty \\(0 bytes\\) at connection close"), + ("WSREP: Failed to guess base node address"), + ("WSREP: Guessing address for incoming client connections failed"), + ("WSREP: Failed to read output of: '/sbin/ifconfig"), + ("WSREP: SQL statement was ineffective"), + ("THE_LAST_SUPPRESSION")|| diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6437827a175..6304b903737 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8745,6 +8745,31 @@ static int get_options(int *argc_ptr, char ***argv_ptr) else global_system_variables.option_bits&= ~OPTION_BIG_SELECTS; +#ifdef WITH_WSREP + if (global_system_variables.wsrep_causal_reads) { + WSREP_WARN("option --wsrep-casual-reads is deprecated"); + if (!(global_system_variables.wsrep_sync_wait & + WSREP_SYNC_WAIT_BEFORE_READ)) { + WSREP_WARN("--wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=%u. " + "WSREP_SYNC_WAIT_BEFORE_READ is on", + global_system_variables.wsrep_sync_wait); + global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ; + } else { + // they are both turned on. + } + } else { + if (global_system_variables.wsrep_sync_wait & + WSREP_SYNC_WAIT_BEFORE_READ) { + WSREP_WARN("--wsrep-sync-wait=%u takes precedence over --wsrep-causal-reads=OFF. " + "WSREP_SYNC_WAIT_BEFORE_READ is on", + global_system_variables.wsrep_sync_wait); + global_system_variables.wsrep_causal_reads = 1; + } else { + // they are both turned off. + } + } +#endif // WITH_WSREP + // Synchronize @@global.autocommit on --autocommit const ulonglong turn_bit_on= opt_autocommit ? OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT; diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 6701d3fd28a..cb700448ee5 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -74,9 +74,10 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, int rcode= 0; int event= 1; - DBUG_ENTER("wsrep_apply_rbr"); + DBUG_ENTER("wsrep_apply_events"); - if (thd->killed == KILL_CONNECTION) + if (thd->killed == KILL_CONNECTION && + thd->wsrep_conflict_state != REPLAYING) { WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", (long long) wsrep_thd_trx_seqno(thd)); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 60ced03a8b1..d93c5a3a02d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -289,9 +289,16 @@ wsrep_view_handler_cb (void* app_ctx, wsrep_ready_set(FALSE); /* Close client connections to ensure that they don't interfere - * with SST */ - WSREP_DEBUG("[debug]: closing client connections for PRIM"); - wsrep_close_client_connections(TRUE); + * with SST. Necessary only if storage engines are initialized + * before SST. + * TODO: Just killing all ongoing transactions should be enough + * since wsrep_ready is OFF and no new transactions can start. + */ + if (!wsrep_before_SE()) + { + WSREP_DEBUG("[debug]: closing client connections for PRIM"); + wsrep_close_client_connections(TRUE); + } ssize_t const req_len= wsrep_sst_prepare (sst_req); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 28643af3718..dd47d4dc1a4 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -194,7 +194,7 @@ extern wsrep_seqno_t wsrep_locked_seqno; (global_system_variables.wsrep_on) #define WSREP(thd) \ - (WSREP_ON && (thd && thd->variables.wsrep_on)) + (WSREP_ON && wsrep && (thd && thd->variables.wsrep_on)) #define WSREP_CLIENT(thd) \ (WSREP(thd) && thd->wsrep_client_thread) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3aa2ac66073..687c9e1fd31 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -62,26 +62,34 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type) 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; + // wsrep_sync_wait should also be updated. + if (var_type == OPT_GLOBAL) { + if (global_system_variables.wsrep_causal_reads) { + global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ; + } else { + global_system_variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ; + } } else { - thd->variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ; + if (thd->variables.wsrep_causal_reads) { + thd->variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ; + } else { + thd->variables.wsrep_sync_wait &= ~WSREP_SYNC_WAIT_BEFORE_READ; + } } + return false; } 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 & - WSREP_SYNC_WAIT_BEFORE_READ; + // wsrep_causal_reads should also be updated. + if (var_type == OPT_GLOBAL) { + global_system_variables.wsrep_causal_reads= + global_system_variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ; + } else { + thd->variables.wsrep_causal_reads= + thd->variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ; + } return false; } From cc9d1bd8dc55ddc451cd2a255958fac313fe79d0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 14 Oct 2014 18:04:04 -0400 Subject: [PATCH 194/294] empty patch From c68e73b53fa2e1d6c60930f5f85f0ac52dabc825 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 17 Nov 2014 09:55:53 -0500 Subject: [PATCH 195/294] MDEV-6924 : Server crashed on CREATE TABLE ... SELECT Do not allow server to start if binlog_format is set to a format other than ROW. Also restrict the change of GLOBAL/SESSION binlog_format value at runtime. --- mysql-test/suite/galera/r/create.result | 23 +++++++++++ mysql-test/suite/galera/t/create.test | 26 +++++++++++++ mysql-test/suite/wsrep/r/binlog_format.result | 16 ++++++++ mysql-test/suite/wsrep/t/binlog_format.test | 13 +++++++ mysql-test/suite/wsrep/t/pool_of_threads.test | 1 + sql/mysqld.cc | 9 +++++ sql/sql_class.cc | 10 +++++ sql/sys_vars.cc | 38 +++++++++---------- 8 files changed, 116 insertions(+), 20 deletions(-) create mode 100644 mysql-test/suite/galera/r/create.result create mode 100644 mysql-test/suite/galera/t/create.test diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result new file mode 100644 index 00000000000..4dffe96d719 --- /dev/null +++ b/mysql-test/suite/galera/r/create.result @@ -0,0 +1,23 @@ +# +# MDEV-6924 : Server crashed on CREATE TABLE ... SELECT +# +SET @wsrep_forced_binlog_format_saved=@@GLOBAL.wsrep_forced_binlog_format; +SET @@GLOBAL.wsrep_forced_binlog_format=STATEMENT; +SHOW VARIABLES LIKE '%log%bin%'; +Variable_name Value +log_bin OFF +log_bin_trust_function_creators ON +sql_log_bin ON +USE test; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +CREATE TEMPORARY TABLE `t1_temp` AS SELECT * FROM `t1` WHERE i = 1; +SELECT * FROM t1; +i +1 +SELECT * FROM t1_temp; +i +1 +DROP TABLE t1; +SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; +# End of tests diff --git a/mysql-test/suite/galera/t/create.test b/mysql-test/suite/galera/t/create.test new file mode 100644 index 00000000000..b56a841fb65 --- /dev/null +++ b/mysql-test/suite/galera/t/create.test @@ -0,0 +1,26 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-6924 : Server crashed on CREATE TABLE ... SELECT +--echo # + +SET @wsrep_forced_binlog_format_saved=@@GLOBAL.wsrep_forced_binlog_format; +SET @@GLOBAL.wsrep_forced_binlog_format=STATEMENT; + +# @@log_bin must be OFF +SHOW VARIABLES LIKE '%log%bin%'; + +USE test; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +CREATE TEMPORARY TABLE `t1_temp` AS SELECT * FROM `t1` WHERE i = 1; +SELECT * FROM t1; +SELECT * FROM t1_temp; + +# Cleanup +DROP TABLE t1; +SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; + +--echo # End of tests + diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index 5b8da51f829..2ce3d0b49c5 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -1,5 +1,6 @@ call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); +call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW @@ -33,3 +34,18 @@ CREATE TABLE IF NOT EXISTS test.t3 AS SELECT * FROM information_schema.routines DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +SET @@GLOBAL.binlog_format=STATEMENT; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +SET @@GLOBAL.binlog_format=MIXED; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +SET @@GLOBAL.binlog_format=ROW; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW +# End of test. diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index d2035b28550..561e4d77ea9 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -5,6 +5,7 @@ # call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); +call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); SHOW VARIABLES LIKE 'binlog_format'; -- error ER_WRONG_VALUE_FOR_VAR @@ -25,3 +26,15 @@ DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +-- error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.binlog_format=STATEMENT; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; + +-- error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.binlog_format=MIXED; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; + +SET @@GLOBAL.binlog_format=ROW; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; + +--echo # End of test. diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.test b/mysql-test/suite/wsrep/t/pool_of_threads.test index f4fffaf4f9a..dbf429e3f01 100644 --- a/mysql-test/suite/wsrep/t/pool_of_threads.test +++ b/mysql-test/suite/wsrep/t/pool_of_threads.test @@ -1,4 +1,5 @@ --source include/have_wsrep.inc +--source include/have_binlog_format_row.inc --echo --echo # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6304b903737..63091da6133 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8746,6 +8746,15 @@ static int get_options(int *argc_ptr, char ***argv_ptr) global_system_variables.option_bits&= ~OPTION_BIG_SELECTS; #ifdef WITH_WSREP + if (!opt_bootstrap && WSREP_PROVIDER_EXISTS && + global_system_variables.binlog_format != BINLOG_FORMAT_ROW) { + + WSREP_ERROR ("Only binlog_format = 'ROW' is currently supported. " + "Configured value: '%s'. Please adjust your configuration.", + binlog_format_names[global_system_variables.binlog_format]); + return 1; + } + if (global_system_variables.wsrep_causal_reads) { WSREP_WARN("option --wsrep-casual-reads is deprecated"); if (!(global_system_variables.wsrep_sync_wait & diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 14821f0e027..c28966bcbcf 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5885,6 +5885,16 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, The MYSQL_LOG::write() function will set the STMT_END_F flag and flush the pending rows event if necessary. */ +#ifdef WITH_WSREP + /* + Even though wsrep only supports ROW binary log format, a user can set + binlog format to STATEMENT (wsrep_forced_binlog_format). In which case + the control might reach here even when binary logging (--log-bin) is + not enabled. This is possible because wsrep patch partially enables + binary logging by setting wsrep_emulate_binlog. + */ + if (mysql_bin_log.is_open()) +#endif /* WITH_WSREP */ { Query_log_event qinfo(this, query_arg, query_len, is_trans, direct, suppress_use, errcode); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 578d24a17e8..f55edd31320 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -280,6 +280,24 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) if (check_has_super(self, thd, var)) return true; +#ifdef WITH_WSREP + /* + MariaDB Galera does not support STATEMENT or MIXED binlog format currently. + */ + if (WSREP(thd) && + var->save_result.ulonglong_value != BINLOG_FORMAT_ROW) + { + WSREP_ERROR("MariaDB Galera does not support binlog format: %s", + binlog_format_names[var->save_result.ulonglong_value]); + + // Also push a warning because error message is general. + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "MariaDB Galera does not support binlog format: %s", + binlog_format_names[var->save_result.ulonglong_value]); + return true; + } +#endif + if (var->type == OPT_GLOBAL) return false; @@ -308,26 +326,6 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT)) return true; -#ifdef WITH_WSREP - /* MariaDB Galera does not support STATEMENT or MIXED binlog - format currently */ - if (WSREP(thd) && - (var->save_result.ulonglong_value == BINLOG_FORMAT_STMT || - var->save_result.ulonglong_value == BINLOG_FORMAT_MIXED)) - { - WSREP_DEBUG("MariaDB Galera does not support binlog format : %s", - var->save_result.ulonglong_value == BINLOG_FORMAT_STMT ? - "STATEMENT" : "MIXED"); - /* Push also warning, because error message is general */ - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_UNKNOWN_ERROR, - "MariaDB Galera does not support binlog format: %s", - var->save_result.ulonglong_value == BINLOG_FORMAT_STMT ? - "STATEMENT" : "MIXED"); - return true; - } -#endif - return false; } From 86d7512f428393a54251624072702549804f2a75 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 9 Dec 2014 10:27:49 -0500 Subject: [PATCH 196/294] MDEV-7204: mariadb-galera-server el7 rpms packaging issue, no mariadb-server in provides MDEV-7233: Fix issue with missing dependency socat when installing MariaDB-galera-server on RedhatEL/OracleEL/(Others?) RPM based * Added mariadb-server to "provides" for MariaDB Galera server package. (rpm) * Removed "socat" from MariaDB Galera server's mandatory dependency list. (rpm) * Moved "socat" from mandatory to optional dependency. (deb) --- cmake/cpack_rpm.cmake | 4 +++- debian/dist/Debian/control | 4 ++-- debian/dist/Ubuntu/control | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 8ee87840798..61c12a9d0f1 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -121,12 +121,14 @@ SETA(CPACK_RPM_server_PACKAGE_OBSOLETES SETA(CPACK_RPM_server_PACKAGE_PROVIDES "MariaDB" "MySQL" + "MariaDB-server" + "mariadb-server" "MySQL-server" "msqlormysql" "mysql-server") SETA(CPACK_RPM_server_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" - "MariaDB-client" "galera" "rsync" "lsof" "socat" "grep" "gawk" "iproute" + "MariaDB-client" "galera" "rsync" "lsof" "grep" "gawk" "iproute" "coreutils" "findutils") SETA(CPACK_RPM_shared_PACKAGE_OBSOLETES diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 3e1e9f6bef8..5fe19dbd0f5 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -36,14 +36,14 @@ Description: MariaDB database regression test suite Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd +Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd, socat Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), - rsync, lsof, socat, grep, gawk, iproute, coreutils, findutils + rsync, lsof, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index c93b3c39fb9..02df9e4a5f5 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -36,14 +36,14 @@ Description: MariaDB database regression test suite Package: mariadb-galera-server-5.5 Architecture: any -Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd +Suggests: tinyca, mailx, mariadb-galera-test, netcat-openbsd, socat Recommends: libhtml-template-perl Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), - rsync, lsof, socat, grep, gawk, iproute, coreutils, findutils + rsync, lsof, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), mysql-server-4.1, mysql-server-5.0, mysql-server-5.1, mysql-server-5.5, From 64714ae2c1f8036ca18cefa0c2dc8270d12e522c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 12 Dec 2014 10:45:32 -0500 Subject: [PATCH 197/294] MDEV-6891: Update company name --- scripts/mysql_install_db.sh | 4 ++-- win/packaging/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index fcf264262fd..8da092289e9 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -512,8 +512,8 @@ then echo "The latest information about MariaDB is available at http://mariadb.org/." echo "You can find additional information about the MySQL part at:" echo "http://dev.mysql.com" - echo "Support MariaDB development by buying support/new features from" - echo "SkySQL Ab. You can contact us about this at sales@skysql.com". + echo "Support MariaDB development by buying support/new features from MariaDB" + echo "Corporation Ab. You can contact us about this at sales@mariadb.com." echo "Alternatively consider joining our community based development effort:" echo "http://mariadb.com/kb/en/contributing-to-the-mariadb-project/" echo diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 0b5e2f98f16..95547ac9f3a 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -17,7 +17,7 @@ IF(NOT WIN32) RETURN() ENDIF() -SET(MANUFACTURER "Monty Program AB") +SET(MANUFACTURER "MariaDB Corporation Ab") FIND_PATH(WIX_DIR heat.exe $ENV{WIX_DIR}/bin $ENV{ProgramFiles}/wix/bin From 920bc0aff10b87a8524939c31029653afb94470c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 12 Dec 2014 17:14:06 -0500 Subject: [PATCH 198/294] MDEV-6891: Addendum, update company name in copyright notice --- include/welcome_copyright_notice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index 875770edb89..956a9f1c17a 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -25,6 +25,6 @@ */ #define ORACLE_WELCOME_COPYRIGHT_NOTICE(first_year) \ "Copyright (c) " first_year ", " COPYRIGHT_NOTICE_CURRENT_YEAR \ - ", Oracle, Monty Program Ab and others.\n" + ", Oracle, MariaDB Corporation Ab and others.\n" #endif /* _welcome_copyright_notice_h_ */ From cb47155c68f38c6931fd539a8615373199b4ee64 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 20 Dec 2014 19:49:04 -0500 Subject: [PATCH 199/294] MDEV-7319 : Galera bootstrap (/etc/init.d/mysql bootstrap) returns code 0 on failure Modified init script to return with proper exit status for bootstrap command. [Based on Kenny Rasschaert's suggestion] --- support-files/mysql.server.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 19f07dcf2fc..1600cb0f86a 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -447,8 +447,9 @@ case "$mode" in 'bootstrap') # Bootstrap the cluster, start the first node # that initiate the cluster - echo $echo_n "Bootstrapping the cluster" + echo $echo_n "Bootstrapping the cluster.. " $0 start $other_args --wsrep-new-cluster + exit $? ;; *) # usage From 952b575272d47a48a1c55e83d3ff9a548857e564 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 31 Dec 2014 19:28:20 -0500 Subject: [PATCH 200/294] MDEV-6832: ER_LOCK_WAIT_TIMEOUT on SHOW STATUS Synchronous read view should not be needed for SHOW commands. --- mysql-test/suite/wsrep/r/mdev_6832.result | 11 +++++++++++ mysql-test/suite/wsrep/r/variables.result | 1 - mysql-test/suite/wsrep/t/mdev_6832.opt | 1 + mysql-test/suite/wsrep/t/mdev_6832.test | 15 +++++++++++++++ mysql-test/suite/wsrep/t/variables.test | 1 - sql/sql_parse.cc | 3 --- sql/wsrep_var.cc | 7 +++++++ 7 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/mdev_6832.result create mode 100644 mysql-test/suite/wsrep/t/mdev_6832.opt create mode 100644 mysql-test/suite/wsrep/t/mdev_6832.test diff --git a/mysql-test/suite/wsrep/r/mdev_6832.result b/mysql-test/suite/wsrep/r/mdev_6832.result new file mode 100644 index 00000000000..43894a6ec49 --- /dev/null +++ b/mysql-test/suite/wsrep/r/mdev_6832.result @@ -0,0 +1,11 @@ +# +# MDEV-6832: ER_LOCK_WAIT_TIMEOUT on SHOW STATUS +# +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready ON +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SET @@global.wsrep_cluster_address='gcomm://'; +# End of test. diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index bbd969c735a..675cdf724cc 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -16,7 +16,6 @@ SET GLOBAL wsrep_provider=none; # # MDEV#6206: wsrep_slave_threads subtracts from max_connections # -call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); call mtr.add_suppression("WSREP: Failed to get provider options"); SELECT @@global.wsrep_provider; @@global.wsrep_provider diff --git a/mysql-test/suite/wsrep/t/mdev_6832.opt b/mysql-test/suite/wsrep/t/mdev_6832.opt new file mode 100644 index 00000000000..61f3f1bee5b --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_6832.opt @@ -0,0 +1 @@ +--wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --wsrep-on=1 --wsrep_causal_reads=ON diff --git a/mysql-test/suite/wsrep/t/mdev_6832.test b/mysql-test/suite/wsrep/t/mdev_6832.test new file mode 100644 index 00000000000..9efccface57 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_6832.test @@ -0,0 +1,15 @@ +--source include/have_wsrep_provider.inc +--source include/have_binlog_format_row.inc + +--echo # +--echo # MDEV-6832: ER_LOCK_WAIT_TIMEOUT on SHOW STATUS +--echo # + +SHOW STATUS LIKE 'wsrep_ready'; +--disable_query_log +eval SET @@global.wsrep_provider='$WSREP_PROVIDER'; +--enable_query_log +SHOW STATUS LIKE 'wsrep_ready'; +SET @@global.wsrep_cluster_address='gcomm://'; + +--echo # End of test. diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index f71735f64c4..2ae610d0e33 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -31,7 +31,6 @@ SET GLOBAL wsrep_provider=none; --echo # --echo # MDEV#6206: wsrep_slave_threads subtracts from max_connections --echo # -call mtr.add_suppression("safe_mutex: Found wrong usage of mutex 'LOCK_wsrep_slave_threads' and 'LOCK_global_system_variables'"); call mtr.add_suppression("WSREP: Failed to get provider options"); --disable_query_log diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cde856b7ff3..0926e22cc72 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2485,9 +2485,6 @@ mysql_execute_command(THD *thd) break; case SQLCOM_SHOW_STATUS: { -#ifdef WITH_WSREP - if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; -#endif /* WITH_WSREP */ execute_show_status(thd, all_tables); #ifdef WITH_WSREP if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 687c9e1fd31..ba92c6a4773 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -365,7 +365,14 @@ 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()) { From 743a28ea5714459fe09782dab9a4a7a0b0ff6673 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 7 Jan 2015 17:22:53 -0500 Subject: [PATCH 201/294] MDEV-7129 : Galera duplicate error on autoincrement field primary key Merged fix for https://github.com/codership/mysql-wsrep/issues/18. --- sql/wsrep_hton.cc | 3 ++- storage/innobase/handler/ha_innodb.cc | 25 +++++++++++++++++++++++-- storage/xtradb/handler/ha_innodb.cc | 25 +++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 84034ec776e..0572230b18b 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -484,7 +484,8 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) case WSREP_BF_ABORT: DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); case WSREP_TRX_FAIL: - WSREP_DEBUG("commit failed for reason: %d", rcode); + WSREP_DEBUG("commit failed for reason: %d %lu %s", rcode, thd->thread_id, + thd->query()); DBUG_PRINT("wsrep", ("replicating commit fail")); thd->wsrep_query_state= QUERY_EXEC; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f509238c1e9..8b30334d198 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5901,6 +5901,14 @@ no_commit: #ifdef WITH_WSREP /* workaround for LP bug #355000, retrying the insert */ case SQLCOM_INSERT: + + WSREP_DEBUG("DUPKEY error for autoinc\n" + "THD %ld, value %llu, off %llu inc %llu", + wsrep_thd_thread_id(current_thd), + auto_inc, + prebuilt->autoinc_offset, + prebuilt->autoinc_increment); + if (wsrep_on(current_thd) && auto_inc_inserted && wsrep_drupal_282555_workaround && @@ -7400,10 +7408,10 @@ wsrep_append_key( DBUG_ENTER("wsrep_append_key"); bool const copy = true; #ifdef WSREP_DEBUG_PRINT - fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ", (shared) ? "Shared" : "Exclusive", wsrep_thd_thread_id(thd), trx->id, key_len, - table_share->table_name.str); + table_share->table_name.str, wsrep_thd_query(thd)); for (int i=0; iautoinc_increment > increment) { +#ifdef WITH_WSREP + WSREP_DEBUG("autoinc decrease: %llu -> %llu\n" + "THD: %ld, current: %llu, autoinc: %llu", + prebuilt->autoinc_increment, + increment, + wsrep_thd_thread_id(ha_thd()), + current, autoinc); + if (!wsrep_on(ha_thd())) + { +#endif /* WITH_WSREP */ current = autoinc - prebuilt->autoinc_increment; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ current = innobase_next_autoinc( current, 1, increment, 1, col_max_value); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4136f8d50a6..8c881a07123 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6871,6 +6871,14 @@ no_commit: #ifdef WITH_WSREP /* workaround for LP bug #355000, retrying the insert */ case SQLCOM_INSERT: + + WSREP_DEBUG("DUPKEY error for autoinc\n" + "THD %ld, value %llu, off %llu inc %llu", + wsrep_thd_thread_id(current_thd), + auto_inc, + prebuilt->autoinc_offset, + prebuilt->autoinc_increment); + if (wsrep_on(current_thd) && auto_inc_inserted && wsrep_drupal_282555_workaround && @@ -8443,10 +8451,10 @@ wsrep_append_key( DBUG_ENTER("wsrep_append_key"); bool const copy = true; #ifdef WSREP_DEBUG_PRINT - fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ", (shared) ? "Shared" : "Exclusive", wsrep_thd_thread_id(thd), trx->id, key_len, - table_share->table_name.str); + table_share->table_name.str, wsrep_thd_query(thd)); for (int i=0; iautoinc_increment > increment) { +#ifdef WITH_WSREP + WSREP_DEBUG("autoinc decrease: %llu -> %llu\n" + "THD: %ld, current: %llu, autoinc: %llu", + prebuilt->autoinc_increment, + increment, + wsrep_thd_thread_id(ha_thd()), + current, autoinc); + if (!wsrep_on(ha_thd())) + { +#endif /* WITH_WSREP */ current = autoinc - prebuilt->autoinc_increment; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ current = innobase_next_autoinc( current, 1, increment, 1, col_max_value); From 33b4fab8679a2e34a97e167a2a88dc5ea0a5686a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 13 Jan 2015 13:10:07 -0500 Subject: [PATCH 202/294] MDEV-6771 : Incorrect Size for Transfer Reported to pv xargs may split the input and execute them in batches for large number of files. As a result xtrabackup sst script may feed incorrect size to pv. Fixed by piping the files to du directly (du --files0-from=-). [Based on suggestions from Brad Jorgensen] --- scripts/wsrep_sst_xtrabackup-v2.sh | 2 +- scripts/wsrep_sst_xtrabackup.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 865547ad9d8..90892f9574f 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -240,7 +240,7 @@ parse_cnf() get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | xargs -0 du --block-size=1 -c | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 6b33eabee23..dd4060e6961 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -205,7 +205,7 @@ parse_cnf() get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | xargs -0 du --block-size=1 -c | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. From bb93d46241d4c563844ffd7455ac2336a28bd66f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 16 Jan 2015 13:52:30 -0500 Subject: [PATCH 203/294] Test changes (backported from 10.1). --- mysql-test/lib/My/ConfigFactory.pm | 3 -- mysql-test/lib/mtr_cases.pm | 3 -- mysql-test/mysql-test-run.pl | 52 ++------------------ mysql-test/suite/galera/galera_2nodes.cnf | 26 ++++++---- mysql-test/suite/galera/suite.pm | 41 +++++++++++++++ mysql-test/suite/wsrep/my.cnf | 7 +-- mysql-test/suite/wsrep/r/variables.result | 9 ++-- mysql-test/suite/wsrep/suite.pm | 29 +++++++++++ mysql-test/suite/wsrep/t/binlog_format.opt | 2 +- mysql-test/suite/wsrep/t/mdev_6832.opt | 2 +- mysql-test/suite/wsrep/t/pool_of_threads.opt | 2 +- mysql-test/suite/wsrep/t/variables.test | 22 +++------ 12 files changed, 111 insertions(+), 87 deletions(-) create mode 100644 mysql-test/suite/galera/suite.pm create mode 100644 mysql-test/suite/wsrep/suite.pm diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 367f69ca86d..e79d97e045e 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -238,9 +238,6 @@ my @mysqld_rules= { 'pid-file' => \&fix_pidfile }, { '#host' => \&fix_host }, { 'port' => \&fix_port }, - # galera base_port and port used during SST - { '#galera_port' => \&fix_port }, - { '#sst_port' => \&fix_port }, { 'socket' => \&fix_socket }, { '#log-error' => \&fix_log_error }, { 'general-log' => 1 }, diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 3434b70bb3c..870df115f58 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -856,8 +856,6 @@ sub collect_one_test_case { # Suite has no config, autodetect which one to use if ($tinfo->{rpl_test}) { $config= "suite/rpl/my.cnf"; - } elsif ($tinfo->{galera_test}) { - $config= "suite/galera/my.cnf"; } else { $config= "include/default_my.cnf"; } @@ -978,7 +976,6 @@ my $tags_map= {'big_test' => ['big_test', 1], 'master-slave' => ['rpl_test', 1], 'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1], 'long_test' => ['long_test', 1], - 'galera_init' => ['galera_test', 1], }; my $tags_regex_string= join('|', keys %$tags_map); my $tags_regex= qr:include/($tags_regex_string)\.inc:o; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 338508dd2fa..88c052e1d5c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -136,6 +136,8 @@ my $opt_start_dirty; my $opt_start_exit; my $start_only; +our @global_suppressions; + END { if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) { @@ -186,6 +188,8 @@ my @DEFAULT_SUITES= qw( sys_vars- unit- vcol- + wsrep- + galera- ); my $opt_suites; @@ -416,7 +420,6 @@ sub main { check_ndbcluster_support(); check_ssl_support(); check_debug_support(); - check_wsrep_support(); mtr_report("Collecting tests..."); my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases, \@opt_skip_test_list); @@ -3168,47 +3171,6 @@ sub ndbcluster_start ($) { return 0; } -sub have_wsrep() { - my $wsrep_on= $mysqld_variables{'wsrep-on'}; - return defined $wsrep_on -} - -sub check_wsrep_support() { - if (have_wsrep()) - { - mtr_report(" - binaries built with wsrep patch"); - - # Add galera test suites - mtr_report(" - adding wsrep, galera to default test suites"); - push @DEFAULT_SUITES, qw(wsrep galera); - - # Check whether WSREP_PROVIDER environment variable is set. - if (defined $ENV{'WSREP_PROVIDER'}) { - if ((mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") && - ($ENV{'WSREP_PROVIDER'} ne "none")) { - mtr_error("WSREP_PROVIDER env set to an invalid path"); - } - # WSREP_PROVIDER is valid; set to a valid path or "none"). - mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); - } else { - # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider - # library. - my $file_wsrep_provider= - mtr_file_exists("/usr/lib/galera/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so"); - - if ($file_wsrep_provider ne "") { - # wsrep provider library found ! - mtr_verbose("wsrep provider library found : $file_wsrep_provider"); - $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; - } else { - mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); - $ENV{'WSREP_PROVIDER'}= "none"; - } - } - } -} - sub mysql_server_start($) { my ($mysqld, $tinfo) = @_; @@ -4803,6 +4765,7 @@ sub extract_warning_lines ($$) { # Perl code. my @antipatterns = ( + @global_suppressions, qr/error .*connecting to master/, qr/Plugin 'ndbcluster' will be forced to shutdown/, qr/InnoDB: Error: in ALTER TABLE `test`.`t[12]`/, @@ -4855,11 +4818,6 @@ sub extract_warning_lines ($$) { qr|Plugin 'FEEDBACK' registration as a INFORMATION SCHEMA failed|, qr|Failed to setup SSL|, qr|SSL error: Failed to set ciphers to use|, - - # Galera-related warnings. - qr|WSREP:.*down context.*|, - qr|WSREP: Failed to send state UUID:.*|, - qr|WSREP: wsrep_sst_receive_address.*|, ); my $matched_lines= []; diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index c0d5b3add3f..e4ae2e0d49c 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -1,23 +1,31 @@ # Use default setting for mysqld processes !include include/default_mysqld.cnf -[mysqld.1] +[mysqld] binlog-format=row -wsrep_provider=@ENV.WSREP_PROVIDER -wsrep_cluster_address='gcomm://' +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb + +wsrep-cluster-address=gcomm:// +wsrep-provider=@ENV.WSREP_PROVIDER +# enforce read-committed characteristics across the cluster +wsrep-causal-reads=ON +wsrep-sync-wait=7 + +[mysqld.1] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port wsrep_provider_options='base_port=@mysqld.1.#galera_port' wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep_causal_reads=ON [mysqld.2] -binlog-format=row -wsrep_provider=@ENV.WSREP_PROVIDER +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.2.#galera_port' wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep_causal_reads=ON [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm new file mode 100644 index 00000000000..0335e13f54a --- /dev/null +++ b/mysql-test/suite/galera/suite.pm @@ -0,0 +1,41 @@ +package My::Suite::GALERA; +use File::Basename; +use My::Find; + +@ISA = qw(My::Suite); + +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/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"; + +return "No wsrep provider library" unless -f $provider; + +$ENV{WSREP_PROVIDER} = $provider; + +my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; +return "No SST scripts" unless $spath; + +my ($epath) = grep { -f "$_/my_print_defaults"; } "$::bindir/extra", $::path_client_bindir; +return "No my_print_defaults" unless $epath; + +push @::global_suppressions, + ( + qr(WSREP:.*down context.*), + qr(WSREP: Failed to send state UUID:.*), + qr(WSREP: wsrep_sst_receive_address.*), + qr(WSREP: Could not open saved state file for reading: .*), + qr(WSREP: last inactive check more than .* skipping check), + qr(WSREP: Gap in state sequence. Need state transfer.), + qr(WSREP: Failed to prepare for incremental state transfer: .*), + ); + + +$ENV{PATH}="$epath:$ENV{PATH}"; +$ENV{PATH}="$spath:$ENV{PATH}" unless $epath eq $spath; + +bless { }; + diff --git a/mysql-test/suite/wsrep/my.cnf b/mysql-test/suite/wsrep/my.cnf index fc314fbfb40..e6ff7d89751 100644 --- a/mysql-test/suite/wsrep/my.cnf +++ b/mysql-test/suite/wsrep/my.cnf @@ -2,7 +2,8 @@ !include include/default_mysqld.cnf [mysqld.1] - -[ENV] -GALERA_BASE_PORT=@mysqld.1.#galera_port +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_provider_options='base_port=@mysqld.1.#galera_port' diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index 675cdf724cc..5117dd1b048 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -1,3 +1,4 @@ +SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; # MDEV#5534: mysql_tzinfo_to_sql generates wrong query # @@ -72,10 +73,6 @@ Threads_connected 1 SHOW STATUS LIKE 'wsrep_thread_count'; Variable_name Value wsrep_thread_count 11 -SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; -SET GLOBAL wsrep_provider= none; -SET GLOBAL wsrep_cluster_address= ''; -SET GLOBAL wsrep_provider_options= ''; # # MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash # @@ -93,4 +90,8 @@ SELECT @@global.wsrep_sst_auth; @@global.wsrep_sst_auth NULL SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; +SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_provider= none; +SET GLOBAL wsrep_cluster_address= ''; +SET GLOBAL wsrep_provider_options= @wsrep_provider_options_saved; # End of test. diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm new file mode 100644 index 00000000000..369ebb0abeb --- /dev/null +++ b/mysql-test/suite/wsrep/suite.pm @@ -0,0 +1,29 @@ +package My::Suite::WSREP; +use File::Basename; +use My::Find; + +@ISA = qw(My::Suite); + +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/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"; + +return "No wsrep provider library" unless -f $provider; + +$ENV{WSREP_PROVIDER} = $provider; + +my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; +return "No SST scripts" unless $spath; + +my ($epath) = grep { -f "$_/my_print_defaults"; } "$::bindir/extra", $::path_client_bindir; +return "No my_print_defaults" unless $epath; + +$ENV{PATH}="$epath:$ENV{PATH}"; +$ENV{PATH}="$spath:$ENV{PATH}" unless $epath eq $spath; + +bless { }; + diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt index 1b8937b91f3..e3f2470c6e5 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.opt +++ b/mysql-test/suite/wsrep/t/binlog_format.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --wsrep-on=1 --log-bin +--innodb_autoinc_lock_mode=2 --wsrep-provider=$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 index 61f3f1bee5b..459a9702707 100644 --- a/mysql-test/suite/wsrep/t/mdev_6832.opt +++ b/mysql-test/suite/wsrep/t/mdev_6832.opt @@ -1 +1 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --wsrep-on=1 --wsrep_causal_reads=ON +--wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --wsrep_causal_reads=ON diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.opt b/mysql-test/suite/wsrep/t/pool_of_threads.opt index 5ee38531a4a..814417e5b0f 100644 --- a/mysql-test/suite/wsrep/t/pool_of_threads.opt +++ b/mysql-test/suite/wsrep/t/pool_of_threads.opt @@ -1 +1 @@ ---binlog-format=row --innodb_autoinc_lock_mode=2 --innodb_locks_unsafe_for_binlog=1 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep_provider_options='base_port=$GALERA_BASE_PORT' --thread_handling=pool-of-threads +--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/variables.test b/mysql-test/suite/wsrep/t/variables.test index 2ae610d0e33..3093d8ba942 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -1,20 +1,12 @@ --source include/have_wsrep.inc -# Set galera's base_port so that test can run in parallel with other galera -# tests. ---disable_query_log -eval SET GLOBAL wsrep_provider_options='base_port=$GALERA_BASE_PORT'; ---enable_query_log +SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; --echo --echo # MDEV#5534: mysql_tzinfo_to_sql generates wrong query --echo # --echo # Testing wsrep_replicate_myisam variable. ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---enable_query_log - --error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@session.wsrep_replicate_myisam; SELECT @@global.wsrep_replicate_myisam; @@ -76,12 +68,6 @@ sleep 3; SHOW STATUS LIKE 'threads_connected'; SHOW STATUS LIKE 'wsrep_thread_count'; -# reset (for mtr internal checks) -SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; -SET GLOBAL wsrep_provider= none; -SET GLOBAL wsrep_cluster_address= ''; -SET GLOBAL wsrep_provider_options= ''; - --echo # --echo # MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash --echo # @@ -94,5 +80,11 @@ SET @@global.wsrep_sst_auth= NULL; SELECT @@global.wsrep_sst_auth; SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; +# Reset (for mtr internal checks) +SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; +SET GLOBAL wsrep_provider= none; +SET GLOBAL wsrep_cluster_address= ''; +SET GLOBAL wsrep_provider_options= @wsrep_provider_options_saved; + --echo # End of test. From fffc9f585ddaed46dc3d157ebde3c1aeeb8a8c8c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 24 Jan 2015 18:39:21 -0500 Subject: [PATCH 204/294] MDEV-7374 : Losing connection to MySQL while running ALTER TABLE Backport from 10.1. --- .../suite/wsrep/r/alter_table_innodb.result | 8 +++ .../suite/wsrep/t/alter_table_innodb.opt | 1 + .../suite/wsrep/t/alter_table_innodb.test | 10 ++++ storage/innobase/handler/ha_innodb.cc | 51 ++++++++++--------- storage/xtradb/handler/ha_innodb.cc | 51 ++++++++++--------- 5 files changed, 75 insertions(+), 46 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/alter_table_innodb.result create mode 100644 mysql-test/suite/wsrep/t/alter_table_innodb.opt create mode 100644 mysql-test/suite/wsrep/t/alter_table_innodb.test diff --git a/mysql-test/suite/wsrep/r/alter_table_innodb.result b/mysql-test/suite/wsrep/r/alter_table_innodb.result new file mode 100644 index 00000000000..85017cec6e0 --- /dev/null +++ b/mysql-test/suite/wsrep/r/alter_table_innodb.result @@ -0,0 +1,8 @@ +# +# MDEV-7374 : Losing connection to MySQL while running ALTER TABLE +# +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e; +ALTER TABLE t1 MODIFY i FLOAT; +DROP TABLE t1; diff --git a/mysql-test/suite/wsrep/t/alter_table_innodb.opt b/mysql-test/suite/wsrep/t/alter_table_innodb.opt new file mode 100644 index 00000000000..1e84570d7f6 --- /dev/null +++ b/mysql-test/suite/wsrep/t/alter_table_innodb.opt @@ -0,0 +1 @@ +--wsrep-on=0 diff --git a/mysql-test/suite/wsrep/t/alter_table_innodb.test b/mysql-test/suite/wsrep/t/alter_table_innodb.test new file mode 100644 index 00000000000..ca06be02a85 --- /dev/null +++ b/mysql-test/suite/wsrep/t/alter_table_innodb.test @@ -0,0 +1,10 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-7374 : Losing connection to MySQL while running ALTER TABLE +--echo # +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e; +ALTER TABLE t1 MODIFY i FLOAT; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8b30334d198..268887e9fc2 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5747,19 +5747,21 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) - { - case WSREP_TRX_OK: - break; - case WSREP_TRX_SIZE_EXCEEDED: - case WSREP_TRX_CERT_FAIL: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); - } + if (wsrep_on(user_thd)) { + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } - if (binlog_hton->commit(binlog_hton, user_thd, 1)) - DBUG_RETURN(1); - wsrep_post_commit(user_thd, TRUE); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); + } #endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -5772,18 +5774,21 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) - { - case WSREP_TRX_OK: - break; - case WSREP_TRX_SIZE_EXCEEDED: - case WSREP_TRX_CERT_FAIL: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); + if (wsrep_on(user_thd)) { + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); } - if (binlog_hton->commit(binlog_hton, user_thd, 1)) - DBUG_RETURN(1); - wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 8c881a07123..9dcabeccce8 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6711,19 +6711,21 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) - { - case WSREP_TRX_OK: - break; - case WSREP_TRX_SIZE_EXCEEDED: - case WSREP_TRX_CERT_FAIL: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); - } + if (wsrep_on(user_thd)) { + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } - if (binlog_hton->commit(binlog_hton, user_thd, 1)) - DBUG_RETURN(1); - wsrep_post_commit(user_thd, TRUE); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); + } #endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -6736,18 +6738,21 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) - { - case WSREP_TRX_OK: - break; - case WSREP_TRX_SIZE_EXCEEDED: - case WSREP_TRX_CERT_FAIL: - case WSREP_TRX_ERROR: - DBUG_RETURN(1); + if (wsrep_on(user_thd)) { + switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) + { + case WSREP_TRX_OK: + break; + case WSREP_TRX_SIZE_EXCEEDED: + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + DBUG_RETURN(1); + } + + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); } - if (binlog_hton->commit(binlog_hton, user_thd, 1)) - DBUG_RETURN(1); - wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ From f9e7f82d153e568c0d795b8f8a1d911fa4dbc9ab Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 26 Jan 2015 11:44:39 -0500 Subject: [PATCH 205/294] Backported changes done in wsrep_guess_ip() from 10.1. --- sql/wsrep_utils.cc | 83 ++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index f90d65da8cf..e6e58a433e7 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -34,6 +34,10 @@ #include #include // getaddrinfo() +#ifdef HAVE_GETIFADDRS +#include +#endif + extern char** environ; // environment variables static wsp::string wsrep_PATH; @@ -361,20 +365,23 @@ unsigned int wsrep_check_ip (const char* const addr) return ret; } -extern const char* my_bind_addr_str; -extern uint mysqld_port; +extern char* my_bind_addr_str; size_t wsrep_guess_ip (char* buf, size_t buf_len) { size_t ip_len = 0; - if (my_bind_addr_str && strlen(my_bind_addr_str)) + if (my_bind_addr_str && my_bind_addr_str[0] != '\0') { unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str); if (INADDR_NONE == ip_type) { - WSREP_ERROR("Node IP address not obtained from bind_address, trying alternate methods"); - } else if (INADDR_ANY != ip_type) { + WSREP_ERROR("Networking not configured, cannot receive state " + "transfer."); + return 0; + } + + if (INADDR_ANY != ip_type) { strncpy (buf, my_bind_addr_str, buf_len); return strlen(buf); } @@ -399,53 +406,29 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) return ip_len; } - // try to find the address of the first one -#if (TARGET_OS_LINUX == 1) - const char cmd[] = "ip addr show | grep -E '^[[:space:]]*inet' | grep -m1 global |" - " awk '{ print $2 }' | sed -e 's/\\/.*//'"; -#elif defined(__sun__) - const char cmd[] = "/sbin/ifconfig -a | " - "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; -#elif defined(__APPLE__) || defined(__FreeBSD__) - const char cmd[] = "/sbin/route -nv get 8.8.8.8 | tail -n1 | awk '{print $(NF)}'"; -#else - char *cmd; -#error "OS not supported" +#if HAVE_GETIFADDRS + struct ifaddrs *ifaddr, *ifa; + if (getifaddrs(&ifaddr) == 0) + { + for (ifa= ifaddr; ifa != NULL; ifa = ifa->ifa_next) + { + if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) // TODO AF_INET6 + continue; + + if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST)) + continue; + + if (strcmp(buf, "127.0.0.1") == 0) // lame + continue; + + freeifaddrs(ifaddr); + return strlen(buf); + } + freeifaddrs(ifaddr); + } #endif - wsp::process proc (cmd, "r"); - if (NULL != proc.pipe()) { - char* ret; - - ret = fgets (buf, buf_len, proc.pipe()); - - if (proc.wait()) return 0; - - if (NULL == ret) { - WSREP_ERROR("Failed to read output of: '%s'", cmd); - return 0; - } - } - else { - WSREP_ERROR("Failed to execute: '%s'", cmd); - return 0; - } - - // clear possible \n at the end of ip string left by fgets() - ip_len = strlen (buf); - if (ip_len > 0 && '\n' == buf[ip_len - 1]) { - ip_len--; - buf[ip_len] = '\0'; - } - - if (INADDR_NONE == inet_addr(buf)) { - if (strlen(buf) != 0) { - WSREP_WARN("Shell command returned invalid address: '%s'", buf); - } - return 0; - } - - return ip_len; + return 0; } size_t wsrep_guess_address(char* buf, size_t buf_len) From 248c662cd7b7421f0a87c21a3903395c99c04939 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 26 Jan 2015 22:43:46 -0500 Subject: [PATCH 206/294] Minor test modifications. --- mysql-test/include/check-testcase.test | 2 ++ mysql-test/include/mtr_warnings.sql | 21 --------------------- mysql-test/suite/galera/suite.pm | 15 +++++++++------ mysql-test/suite/wsrep/suite.pm | 9 +++++++++ 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index 858a89f706c..38559fc9898 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -1,3 +1,5 @@ +--source include/wait_until_ready.inc + # ==== Purpose ==== # # This test is executed twice for each test case. Before every diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 5ef85411e79..f24edcfb996 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -225,27 +225,6 @@ INSERT INTO global_suppressions VALUES ("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum on master.*"), ("Slave I/O: Get master BINLOG_CHECKSUM failed with error.*"), ("Slave I/O: Notifying master by SET @master_binlog_checksum= @@global.binlog_checksum failed with error.*"), - - /* - Galera suppressions - */ - ("WSREP:.*down context.*"), - ("WSREP: Failed to send state UUID:.*"), - ("WSREP: wsrep_sst_receive_address is set to '127.0.0.1"), - ("WSREP: option --wsrep-casual-reads is deprecated"), - ("WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0"), - ("WSREP: Could not open saved state file for reading: "), - ("WSREP: access file\\(gvwstate\\.dat\\) failed\\(No such file or directory\\)"), - ("WSREP: Gap in state sequence\\. Need state transfer\\."), - ("WSREP: Failed to prepare for incremental state transfer: Local state UUID \\(00000000-0000-0000-0000-000000000000\\) does not match group state UUID"), - ("WSREP: No existing UUID has been found, so we assume that this is the first time that this server has been started\\. Generating a new UUID: "), - ("WSREP: last inactive check more than"), - ("WSREP: binlog cache not empty \\(0 bytes\\) at connection close"), - ("WSREP: Failed to guess base node address"), - ("WSREP: Guessing address for incoming client connections failed"), - ("WSREP: Failed to read output of: '/sbin/ifconfig"), - ("WSREP: SQL statement was ineffective"), - ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 0335e13f54a..e21207b659a 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -24,13 +24,16 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( - qr(WSREP:.*down context.*), - qr(WSREP: Failed to send state UUID:.*), - qr(WSREP: wsrep_sst_receive_address.*), - qr(WSREP: Could not open saved state file for reading: .*), - qr(WSREP: last inactive check more than .* skipping check), + qr(WSREP: Failed to guess base node address), + qr(WSREP: Guessing address for incoming client connections failed), + qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), + qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: Gap in state sequence. Need state transfer.), - qr(WSREP: Failed to prepare for incremental state transfer: .*), + qr(WSREP: Failed to prepare for incremental state transfer:), + qr(WSREP:.*down context.*), + qr(WSREP: Failed to send state UUID:), + qr(WSREP: last inactive check more than .* skipping check), + qr(WSREP: SQL statement was ineffective), ); diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 369ebb0abeb..7b3b2db6836 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -22,6 +22,15 @@ return "No SST scripts" unless $spath; my ($epath) = grep { -f "$_/my_print_defaults"; } "$::bindir/extra", $::path_client_bindir; return "No my_print_defaults" unless $epath; +push @::global_suppressions, + ( + qr(WSREP: Failed to guess base node address), + qr(WSREP: Guessing address for incoming client connections failed), + qr(WSREP: Could not open saved state file for reading: ), + qr(WSREP: option --wsrep-casual-reads is deprecated), + qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), + ); + $ENV{PATH}="$epath:$ENV{PATH}"; $ENV{PATH}="$spath:$ENV{PATH}" unless $epath eq $spath; From 5b6f637caafba84457b91e08ce9c4f3fc6e8202f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 14:17:40 -0500 Subject: [PATCH 207/294] MDEV-7322: Option to allow setting the binlog_format with Galera At session scope, allow binlog_format to be changed to values other than ROW with a warning. --- mysql-test/suite/wsrep/r/binlog_format.result | 26 +++++++++++++------ mysql-test/suite/wsrep/t/binlog_format.test | 21 ++++++++++----- sql/sys_vars.cc | 13 ++++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index 2ce3d0b49c5..d996371c056 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -1,28 +1,30 @@ -call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); -call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); +# +# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT +# SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW SET binlog_format=STATEMENT; -ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT SHOW WARNINGS; Level Code Message Warning 1105 MariaDB Galera does not support binlog format: STATEMENT -Error 1231 Variable 'binlog_format' can't be set to the value of 'STATEMENT' SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value -binlog_format ROW +binlog_format STATEMENT CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=MIXED; -ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED SHOW WARNINGS; Level Code Message Warning 1105 MariaDB Galera does not support binlog format: MIXED -Error 1231 Variable 'binlog_format' can't be set to the value of 'MIXED' SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value -binlog_format ROW +binlog_format MIXED CREATE TABLE IF NOT EXISTS test.t2 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=ROW; SHOW WARNINGS; @@ -34,6 +36,9 @@ CREATE TABLE IF NOT EXISTS test.t3 AS SELECT * FROM information_schema.routines DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +# +# MDEV-7322: Option to allow setting the binlog_format with Galera +# SET @@GLOBAL.binlog_format=STATEMENT; ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' SHOW GLOBAL VARIABLES LIKE 'binlog_format'; @@ -44,6 +49,11 @@ ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' SHOW GLOBAL VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW +SET @@GLOBAL.binlog_format=DEFAULT; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'DEFAULT' +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW SET @@GLOBAL.binlog_format=ROW; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; Variable_name Value diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 561e4d77ea9..a2dc8542322 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,19 +1,18 @@ --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc -# -# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT -# -call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); -call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); + call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); + +--echo # +--echo # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT +--echo # SHOW VARIABLES LIKE 'binlog_format'; --- error ER_WRONG_VALUE_FOR_VAR SET binlog_format=STATEMENT; SHOW WARNINGS; SHOW VARIABLES LIKE 'binlog_format'; CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; --- error ER_WRONG_VALUE_FOR_VAR SET binlog_format=MIXED; SHOW WARNINGS; SHOW VARIABLES LIKE 'binlog_format'; @@ -26,6 +25,10 @@ DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +--echo # +--echo # MDEV-7322: Option to allow setting the binlog_format with Galera +--echo # + -- error ER_WRONG_VALUE_FOR_VAR SET @@GLOBAL.binlog_format=STATEMENT; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; @@ -34,6 +37,10 @@ SHOW GLOBAL VARIABLES LIKE 'binlog_format'; SET @@GLOBAL.binlog_format=MIXED; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +-- error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.binlog_format=DEFAULT; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; + SET @@GLOBAL.binlog_format=ROW; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index b8c750061a6..b796b1445e4 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -287,14 +287,17 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) if (WSREP(thd) && var->save_result.ulonglong_value != BINLOG_FORMAT_ROW) { - WSREP_ERROR("MariaDB Galera does not support binlog format: %s", - binlog_format_names[var->save_result.ulonglong_value]); - - // Also push a warning because error message is general. + // Push a warning to the error log. push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, "MariaDB Galera does not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); - return true; + + if (var->type == OPT_GLOBAL) + { + WSREP_ERROR("MariaDB Galera does not support binlog format: %s", + binlog_format_names[var->save_result.ulonglong_value]); + return true; + } } #endif From 9b7e3801f4d3b241d525c7f2d6f0e2aedb35e3cc Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 16:22:29 -0500 Subject: [PATCH 208/294] MDEV-7476: Allow SELECT to succeed even when node is not ready Added a SESSION-only system variable "wsrep_dirty_reads" to allow SELECT queries to pass even when the node is not prepared to accept queries (wsrep_ready=OFF). Added a test case. --- .../galera/r/galera_var_dirty_reads.result | 25 ++++++++++ mysql-test/suite/galera/suite.pm | 1 + .../galera/t/galera_var_dirty_reads.test | 46 +++++++++++++++++++ .../sys_vars/r/wsrep_dirty_reads_basic.result | 35 ++++++++++++++ .../sys_vars/t/wsrep_dirty_reads_basic.test | 35 ++++++++++++++ sql/sql_class.h | 1 + sql/sql_parse.cc | 8 ++-- sql/sys_vars.cc | 6 +++ 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_var_dirty_reads.result create mode 100644 mysql-test/suite/galera/t/galera_var_dirty_reads.test create mode 100644 mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result create mode 100644 mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result new file mode 100644 index 00000000000..6d703c8cf95 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -0,0 +1,25 @@ +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +i +1 +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SELECT * FROM t1; +ERROR 08S01: WSREP has not yet prepared node for application use +SET @@session.wsrep_dirty_reads=ON; +SELECT * FROM t1; +i +1 +SELECT * FROM t1; +i +1 +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index e21207b659a..7642b937e05 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -34,6 +34,7 @@ push @::global_suppressions, qr(WSREP: Failed to send state UUID:), qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), + qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), ); diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test new file mode 100644 index 00000000000..855f4abdbf0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -0,0 +1,46 @@ +# +# Check the handling of @@wsrep_dirty_reads +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_2 +--let $wsrep_cluster_address_saved = `SELECT @@global.wsrep_cluster_address` + +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; + +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; + +# Set wsrep_sync_wait to avoid ER_LOCK_WAIT_TIMEOUT (MDEV-6832). +SET SESSION wsrep_sync_wait=0; + +# Must return 'OFF' +SHOW STATUS LIKE 'wsrep_ready'; + +# Must return 'Non-primary' +SHOW STATUS LIKE 'wsrep_cluster_status'; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM t1; + +SET @@session.wsrep_dirty_reads=ON; + +SELECT * FROM t1; + +--disable_query_log +--eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' +--enable_query_log +--source include/wait_until_connected_again.inc + +--connection node_1 +SELECT * FROM t1; +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test + diff --git a/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result new file mode 100644 index 00000000000..d2a62d6136f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result @@ -0,0 +1,35 @@ +# +# wsrep_dirty_reads +# +# save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; +# default +SELECT @@global.wsrep_dirty_reads; +ERROR HY000: Variable 'wsrep_dirty_reads' is a SESSION variable +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +1 +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# invalid values +SET @@session.wsrep_dirty_reads=NULL; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'NULL' +SET @@session.wsrep_dirty_reads='junk'; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'junk' + +# restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test new file mode 100644 index 00000000000..a47524fcfe3 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test @@ -0,0 +1,35 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_dirty_reads +--echo # + +--echo # save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; + +--echo # default +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@global.wsrep_dirty_reads; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads='junk'; + +--echo +--echo # restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; + +--echo # End of test diff --git a/sql/sql_class.h b/sql/sql_class.h index cca9d1d63bd..6207c29fa8e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -594,6 +594,7 @@ typedef struct system_variables #ifdef WITH_WSREP my_bool wsrep_on; my_bool wsrep_causal_reads; + my_bool wsrep_dirty_reads; uint wsrep_sync_wait; ulong wsrep_retry_autocommit; #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0926e22cc72..a3dd8c886e3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2392,11 +2392,13 @@ mysql_execute_command(THD *thd) } /* - * bail out if DB snapshot has not been installed. We however, - * allow SET and SHOW queries - */ + Bail out if DB snapshot has not been installed. We however, + allow SET and SHOW queries. + */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && + !(thd->variables.wsrep_dirty_reads && + lex->sql_command == SQLCOM_SELECT) && !wsrep_is_show_query(lex->sql_command)) { #if DIRTY_HACK diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index b796b1445e4..88760e2d602 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3951,6 +3951,12 @@ static Sys_var_mybool Sys_wsrep_slave_UK_checks( static Sys_var_mybool Sys_wsrep_restart_slave( "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_dirty_reads( + "wsrep_dirty_reads", "Do not reject SELECT queries even when the node " + "is not ready.", SESSION_ONLY(wsrep_dirty_reads), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + #endif /* WITH_WSREP */ static Sys_var_charptr Sys_ignore_db_dirs( From 950d69610aff4b2ee2cfe83113d339eac1ba0668 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 16:25:18 -0500 Subject: [PATCH 209/294] MDEV-7322: Option to allow setting the binlog_format with Galera At session scope, allow binlog_format to be changed to values other than ROW with a warning. --- mysql-test/suite/wsrep/r/binlog_format.result | 26 +++++++++++++------ mysql-test/suite/wsrep/t/binlog_format.test | 21 ++++++++++----- sql/sys_vars.cc | 13 ++++++---- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index 2ce3d0b49c5..d996371c056 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -1,28 +1,30 @@ -call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); -call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); +# +# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT +# SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW SET binlog_format=STATEMENT; -ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT SHOW WARNINGS; Level Code Message Warning 1105 MariaDB Galera does not support binlog format: STATEMENT -Error 1231 Variable 'binlog_format' can't be set to the value of 'STATEMENT' SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value -binlog_format ROW +binlog_format STATEMENT CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=MIXED; -ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED SHOW WARNINGS; Level Code Message Warning 1105 MariaDB Galera does not support binlog format: MIXED -Error 1231 Variable 'binlog_format' can't be set to the value of 'MIXED' SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value -binlog_format ROW +binlog_format MIXED CREATE TABLE IF NOT EXISTS test.t2 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=ROW; SHOW WARNINGS; @@ -34,6 +36,9 @@ CREATE TABLE IF NOT EXISTS test.t3 AS SELECT * FROM information_schema.routines DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +# +# MDEV-7322: Option to allow setting the binlog_format with Galera +# SET @@GLOBAL.binlog_format=STATEMENT; ERROR 42000: Variable 'binlog_format' can't be set to the value of 'STATEMENT' SHOW GLOBAL VARIABLES LIKE 'binlog_format'; @@ -44,6 +49,11 @@ ERROR 42000: Variable 'binlog_format' can't be set to the value of 'MIXED' SHOW GLOBAL VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format ROW +SET @@GLOBAL.binlog_format=DEFAULT; +ERROR 42000: Variable 'binlog_format' can't be set to the value of 'DEFAULT' +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +Variable_name Value +binlog_format ROW SET @@GLOBAL.binlog_format=ROW; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; Variable_name Value diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 561e4d77ea9..a2dc8542322 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,19 +1,18 @@ --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc -# -# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT -# -call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); -call mtr.add_suppression("WSREP: Could not open saved state file for reading:.*"); + call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID"); + +--echo # +--echo # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT +--echo # SHOW VARIABLES LIKE 'binlog_format'; --- error ER_WRONG_VALUE_FOR_VAR SET binlog_format=STATEMENT; SHOW WARNINGS; SHOW VARIABLES LIKE 'binlog_format'; CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; --- error ER_WRONG_VALUE_FOR_VAR SET binlog_format=MIXED; SHOW WARNINGS; SHOW VARIABLES LIKE 'binlog_format'; @@ -26,6 +25,10 @@ DROP TABLE IF EXISTS test.t1; DROP TABLE IF EXISTS test.t2; DROP TABLE IF EXISTS test.t3; +--echo # +--echo # MDEV-7322: Option to allow setting the binlog_format with Galera +--echo # + -- error ER_WRONG_VALUE_FOR_VAR SET @@GLOBAL.binlog_format=STATEMENT; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; @@ -34,6 +37,10 @@ SHOW GLOBAL VARIABLES LIKE 'binlog_format'; SET @@GLOBAL.binlog_format=MIXED; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; +-- error ER_WRONG_VALUE_FOR_VAR +SET @@GLOBAL.binlog_format=DEFAULT; +SHOW GLOBAL VARIABLES LIKE 'binlog_format'; + SET @@GLOBAL.binlog_format=ROW; SHOW GLOBAL VARIABLES LIKE 'binlog_format'; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 561e3afcd54..f2592a3fd58 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -444,14 +444,17 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) if (WSREP(thd) && var->save_result.ulonglong_value != BINLOG_FORMAT_ROW) { - WSREP_ERROR("MariaDB Galera does not support binlog format: %s", - binlog_format_names[var->save_result.ulonglong_value]); - - // Also push a warning because error message is general. + // Push a warning to the error log. push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, "MariaDB Galera does not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); - return true; + + if (var->type == OPT_GLOBAL) + { + WSREP_ERROR("MariaDB Galera does not support binlog format: %s", + binlog_format_names[var->save_result.ulonglong_value]); + return true; + } } #endif From 47d8001c672a161eaa9e498889a365c5601850e7 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 16:54:24 -0500 Subject: [PATCH 210/294] MDEV-7476: Allow SELECT to succeed even when node is not ready Added a SESSION-only system variable "wsrep_dirty_reads" to allow SELECT queries to pass even when the node is not prepared to accept queries (wsrep_ready=OFF). Added a test case. --- .../galera/r/galera_var_dirty_reads.result | 25 ++++++++++ mysql-test/suite/galera/suite.pm | 1 + .../galera/t/galera_var_dirty_reads.test | 46 +++++++++++++++++++ .../sys_vars/r/wsrep_dirty_reads_basic.result | 35 ++++++++++++++ .../sys_vars/t/wsrep_dirty_reads_basic.test | 35 ++++++++++++++ sql/sql_class.h | 1 + sql/sql_parse.cc | 8 ++-- sql/sys_vars.cc | 6 +++ 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_var_dirty_reads.result create mode 100644 mysql-test/suite/galera/t/galera_var_dirty_reads.test create mode 100644 mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result create mode 100644 mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result new file mode 100644 index 00000000000..6d703c8cf95 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -0,0 +1,25 @@ +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +i +1 +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SELECT * FROM t1; +ERROR 08S01: WSREP has not yet prepared node for application use +SET @@session.wsrep_dirty_reads=ON; +SELECT * FROM t1; +i +1 +SELECT * FROM t1; +i +1 +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index e21207b659a..7642b937e05 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -34,6 +34,7 @@ push @::global_suppressions, qr(WSREP: Failed to send state UUID:), qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), + qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), ); diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test new file mode 100644 index 00000000000..855f4abdbf0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -0,0 +1,46 @@ +# +# Check the handling of @@wsrep_dirty_reads +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_2 +--let $wsrep_cluster_address_saved = `SELECT @@global.wsrep_cluster_address` + +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; + +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; + +# Set wsrep_sync_wait to avoid ER_LOCK_WAIT_TIMEOUT (MDEV-6832). +SET SESSION wsrep_sync_wait=0; + +# Must return 'OFF' +SHOW STATUS LIKE 'wsrep_ready'; + +# Must return 'Non-primary' +SHOW STATUS LIKE 'wsrep_cluster_status'; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM t1; + +SET @@session.wsrep_dirty_reads=ON; + +SELECT * FROM t1; + +--disable_query_log +--eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' +--enable_query_log +--source include/wait_until_connected_again.inc + +--connection node_1 +SELECT * FROM t1; +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test + diff --git a/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result new file mode 100644 index 00000000000..d2a62d6136f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result @@ -0,0 +1,35 @@ +# +# wsrep_dirty_reads +# +# save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; +# default +SELECT @@global.wsrep_dirty_reads; +ERROR HY000: Variable 'wsrep_dirty_reads' is a SESSION variable +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +1 +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# invalid values +SET @@session.wsrep_dirty_reads=NULL; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'NULL' +SET @@session.wsrep_dirty_reads='junk'; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'junk' + +# restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test new file mode 100644 index 00000000000..a47524fcfe3 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test @@ -0,0 +1,35 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_dirty_reads +--echo # + +--echo # save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; + +--echo # default +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@global.wsrep_dirty_reads; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads='junk'; + +--echo +--echo # restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; + +--echo # End of test diff --git a/sql/sql_class.h b/sql/sql_class.h index 5ab03388f01..9dbf85f2dca 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -654,6 +654,7 @@ typedef struct system_variables #ifdef WITH_WSREP my_bool wsrep_on; my_bool wsrep_causal_reads; + my_bool wsrep_dirty_reads; uint wsrep_sync_wait; ulong wsrep_retry_autocommit; #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 87810a65b0f..730adfe94ed 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2615,11 +2615,13 @@ mysql_execute_command(THD *thd) } /* - * bail out if DB snapshot has not been installed. We however, - * allow SET and SHOW queries - */ + Bail out if DB snapshot has not been installed. We however, + allow SET and SHOW queries. + */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && + !(thd->variables.wsrep_dirty_reads && + lex->sql_command == SQLCOM_SELECT) && !wsrep_is_show_query(lex->sql_command)) { #if DIRTY_HACK diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index f2592a3fd58..fe7e0135fe1 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4743,6 +4743,12 @@ static Sys_var_mybool Sys_wsrep_slave_UK_checks( static Sys_var_mybool Sys_wsrep_restart_slave( "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_dirty_reads( + "wsrep_dirty_reads", "Do not reject SELECT queries even when the node " + "is not ready.", SESSION_ONLY(wsrep_dirty_reads), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + #endif /* WITH_WSREP */ static bool fix_host_cache_size(sys_var *, THD *, enum_var_type) From d8ee54c63321e81ef99465bbadc8e4fb45fe7569 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 20:02:43 -0500 Subject: [PATCH 211/294] Add cmake check for getifaddrs. --- cmake/os/WindowsCache.cmake | 1 + config.h.cmake | 1 + configure.cmake | 1 + 3 files changed, 3 insertions(+) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index c75f2e45bf6..8f8d8df6b10 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -76,6 +76,7 @@ SET(HAVE_FSYNC CACHE INTERNAL "") SET(HAVE_FTIME 1 CACHE INTERNAL "") SET(HAVE_FTRUNCATE CACHE INTERNAL "") SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "") +SET(HAVE_GETIFADDRS CACHE INTERNAL "") SET(HAVE_GETCWD 1 CACHE INTERNAL "") SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "") SET(HAVE_GETHRTIME CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 34f77dba050..32f49db1313 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -164,6 +164,7 @@ #cmakedefine HAVE_FSYNC 1 #cmakedefine HAVE_FTIME 1 #cmakedefine HAVE_GETADDRINFO 1 +#cmakedefine HAVE_GETIFADDRS 1 #cmakedefine HAVE_GETCWD 1 #cmakedefine HAVE_GETHOSTBYADDR_R 1 #cmakedefine HAVE_GETHRTIME 1 diff --git a/configure.cmake b/configure.cmake index 1e64e058670..c88a6cc4767 100644 --- a/configure.cmake +++ b/configure.cmake @@ -368,6 +368,7 @@ CHECK_FUNCTION_EXISTS (getpassphrase HAVE_GETPASSPHRASE) CHECK_FUNCTION_EXISTS (getpwnam HAVE_GETPWNAM) CHECK_FUNCTION_EXISTS (getpwuid HAVE_GETPWUID) CHECK_FUNCTION_EXISTS (getrlimit HAVE_GETRLIMIT) +CHECK_FUNCTION_EXISTS (getifaddrs HAVE_GETIFADDRS) CHECK_FUNCTION_EXISTS (getrusage HAVE_GETRUSAGE) CHECK_FUNCTION_EXISTS (getwd HAVE_GETWD) CHECK_FUNCTION_EXISTS (gmtime_r HAVE_GMTIME_R) From cd187ecf90e9988e5a729a1a4db7239e3baa2e6c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 27 Jan 2015 20:22:06 -0500 Subject: [PATCH 212/294] Add cmake check for getifaddrs. --- cmake/os/WindowsCache.cmake | 1 + config.h.cmake | 1 + configure.cmake | 1 + 3 files changed, 3 insertions(+) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index c75f2e45bf6..8f8d8df6b10 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -76,6 +76,7 @@ SET(HAVE_FSYNC CACHE INTERNAL "") SET(HAVE_FTIME 1 CACHE INTERNAL "") SET(HAVE_FTRUNCATE CACHE INTERNAL "") SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "") +SET(HAVE_GETIFADDRS CACHE INTERNAL "") SET(HAVE_GETCWD 1 CACHE INTERNAL "") SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "") SET(HAVE_GETHRTIME CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 6a0527719f9..e5b82fd7259 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -163,6 +163,7 @@ #cmakedefine HAVE_FSYNC 1 #cmakedefine HAVE_FTIME 1 #cmakedefine HAVE_GETADDRINFO 1 +#cmakedefine HAVE_GETIFADDRS 1 #cmakedefine HAVE_GETCWD 1 #cmakedefine HAVE_GETHOSTBYADDR_R 1 #cmakedefine HAVE_GETHRTIME 1 diff --git a/configure.cmake b/configure.cmake index 215b0dc32b4..95f7ad0ef6b 100644 --- a/configure.cmake +++ b/configure.cmake @@ -360,6 +360,7 @@ CHECK_FUNCTION_EXISTS (getpassphrase HAVE_GETPASSPHRASE) CHECK_FUNCTION_EXISTS (getpwnam HAVE_GETPWNAM) CHECK_FUNCTION_EXISTS (getpwuid HAVE_GETPWUID) CHECK_FUNCTION_EXISTS (getrlimit HAVE_GETRLIMIT) +CHECK_FUNCTION_EXISTS (getifaddrs HAVE_GETIFADDRS) CHECK_FUNCTION_EXISTS (getrusage HAVE_GETRUSAGE) CHECK_FUNCTION_EXISTS (getwd HAVE_GETWD) CHECK_FUNCTION_EXISTS (gmtime_r HAVE_GMTIME_R) From a518cc4470124854482467de92abdfff69f83baf Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 18 Feb 2015 18:59:01 -0500 Subject: [PATCH 213/294] MDEV-7544: Update global_suppressions to include warning related to "gvwstate.dat" --- mysql-test/suite/galera/suite.pm | 1 + mysql-test/suite/wsrep/suite.pm | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 7642b937e05..9c48ad1982d 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -35,6 +35,7 @@ push @::global_suppressions, qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), + qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, ); diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 7b3b2db6836..f6c8409f6a8 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -29,6 +29,7 @@ push @::global_suppressions, qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: option --wsrep-casual-reads is deprecated), qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), + qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, ); $ENV{PATH}="$epath:$ENV{PATH}"; From fcc6e12d69e371e160735bcd4fb324f7a382eda3 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 18 Feb 2015 19:02:00 -0500 Subject: [PATCH 214/294] MDEV-7544: Update global_suppressions to include warning related to "gvwstate.dat" --- mysql-test/suite/galera/suite.pm | 1 + mysql-test/suite/wsrep/suite.pm | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 7642b937e05..9c48ad1982d 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -35,6 +35,7 @@ push @::global_suppressions, qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), + qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, ); diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 7b3b2db6836..f6c8409f6a8 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -29,6 +29,7 @@ push @::global_suppressions, qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: option --wsrep-casual-reads is deprecated), qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), + qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, ); $ENV{PATH}="$epath:$ENV{PATH}"; From 1e6f46d78f61dbf5cbb13a862ddc0bb6fcaaf41b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 19 Feb 2015 17:28:18 -0500 Subject: [PATCH 215/294] cleanup: remove unused THD::COND_wsrep_thd --- mysql-test/suite/perfschema/r/all_instances.result | 1 - sql/mysqld.cc | 3 +-- sql/mysqld.h | 1 - sql/sql_class.cc | 1 - sql/sql_class.h | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/mysql-test/suite/perfschema/r/all_instances.result b/mysql-test/suite/perfschema/r/all_instances.result index bfe50b881da..3b0b4db4541 100644 --- a/mysql-test/suite/perfschema/r/all_instances.result +++ b/mysql-test/suite/perfschema/r/all_instances.result @@ -152,7 +152,6 @@ wait/synch/cond/sql/Relay_log_info::sleep_cond wait/synch/cond/sql/Relay_log_info::start_cond wait/synch/cond/sql/Relay_log_info::stop_cond wait/synch/cond/sql/THD::COND_wakeup_ready -wait/synch/cond/sql/THD::COND_wsrep_thd select event_name from file_instances group by event_name; event_name wait/io/file/aria/control diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 63091da6133..857317a927c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -916,7 +916,7 @@ PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, key_BINLOG_COND_queue_busy; #ifdef WITH_WSREP -PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd, +PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread; #endif /* WITH_WSREP */ @@ -967,7 +967,6 @@ static PSI_cond_info all_server_conds[]= { &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}, #endif { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL} diff --git a/sql/mysqld.h b/sql/mysqld.h index f70f3af8387..a4f9abc6b4e 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -222,7 +222,6 @@ extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, #endif /* HAVE_MMAP */ #ifdef WITH_WSREP extern PSI_mutex_key key_LOCK_wsrep_thd; -extern PSI_cond_key key_COND_wsrep_thd; #endif /* HAVE_WSREP */ #ifdef HAVE_OPENSSL diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c28966bcbcf..9fa508cdc97 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1103,7 +1103,6 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_ws_handle.opaque = NULL; wsrep_retry_counter = 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 6207c29fa8e..477be6e8004 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2366,7 +2366,6 @@ public: enum wsrep_query_state wsrep_query_state; enum wsrep_conflict_state wsrep_conflict_state; mysql_mutex_t LOCK_wsrep_thd; - mysql_cond_t COND_wsrep_thd; // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 // wsrep_seqno_t wsrep_trx_seqno; wsrep_trx_meta_t wsrep_trx_meta; From a174aaed754b96cefe4a9dd2bb2865f81bad1471 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 19 Feb 2015 17:28:18 -0500 Subject: [PATCH 216/294] cleanup: remove unused THD::COND_wsrep_thd Conflicts: mysql-test/suite/perfschema/r/all_instances.result sql/mysqld.h --- sql/mysqld.cc | 3 +-- sql/mysqld.h | 1 - sql/sql_class.cc | 1 - sql/sql_class.h | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 19f067f582f..138d542bc97 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1050,7 +1050,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, key_BINLOG_COND_queue_busy; #ifdef WITH_WSREP -PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd, +PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread; #endif /* WITH_WSREP */ @@ -1109,7 +1109,6 @@ static PSI_cond_info all_server_conds[]= { &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}, #endif { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL}, diff --git a/sql/mysqld.h b/sql/mysqld.h index a9eb4fd1ca5..1d7649daf5d 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -247,7 +247,6 @@ extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, #ifdef WITH_WSREP extern PSI_mutex_key key_LOCK_wsrep_thd; -extern PSI_cond_key key_COND_wsrep_thd; #endif /* WITH_WSREP */ #ifdef HAVE_OPENSSL diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c10eff73962..01871494d5b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1193,7 +1193,6 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_ws_handle.opaque = NULL; wsrep_retry_counter = 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9dbf85f2dca..2119312c71a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2773,7 +2773,6 @@ public: enum wsrep_query_state wsrep_query_state; enum wsrep_conflict_state wsrep_conflict_state; mysql_mutex_t LOCK_wsrep_thd; - mysql_cond_t COND_wsrep_thd; // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 // wsrep_seqno_t wsrep_trx_seqno; wsrep_trx_meta_t wsrep_trx_meta; From 69e5f0f42395d0028e75760685cdd7588854f1df Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 19 Feb 2015 17:48:23 -0500 Subject: [PATCH 217/294] cleanup: remove duplicate declaration --- sql/wsrep_binlog.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index a3d8ec6ec2c..a7b680f616b 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -53,7 +53,4 @@ 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); -/* Dump replication buffer to disk without intermediate buffer */ -void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache); - #endif /* WSREP_BINLOG_H */ From c6e62acb9e78d28179f922f2c212ae82d390c138 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 20 Feb 2015 17:21:15 -0500 Subject: [PATCH 218/294] Fix for build failures on Power8 --- sql/wsrep_sst.cc | 33 ++++++++++++++++----------------- wsrep/wsrep_loader.c | 21 +++++++++------------ 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 1d17d8b8c8e..4167740236f 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -411,11 +411,10 @@ static ssize_t sst_prepare_other (const char* method, const char* addr_in, const char** addr_out) { - ssize_t cmd_len= 1024; - char cmd_str[cmd_len]; + char cmd_str[1024]; const char* sst_dir= mysql_real_data_home; - int ret= snprintf (cmd_str, cmd_len, + int ret= snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_%s " WSREP_SST_OPT_ROLE" 'joiner' " WSREP_SST_OPT_ADDR" '%s' " @@ -426,7 +425,7 @@ static ssize_t sst_prepare_other (const char* method, method, addr_in, (sst_auth_real) ? sst_auth_real : "", sst_dir, wsrep_defaults_file, (int)getpid()); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || ret >= (int)sizeof(cmd_str)) { WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); @@ -678,7 +677,7 @@ static int sst_donate_mysqldump (const char* addr, host_len = strlen (addr) + 1; } - char host[host_len]; + char *host= (char *) alloca(host_len); strncpy (host, addr, host_len - 1); host[host_len - 1] = '\0'; @@ -698,7 +697,7 @@ static int sst_donate_mysqldump (const char* addr, user_len = (auth) ? strlen (auth) + 1 : 1; } - char user[user_len]; + char *user= (char *) alloca(user_len); strncpy (user, (auth) ? auth : "", user_len - 1); user[user_len - 1] = '\0'; @@ -706,12 +705,11 @@ static int sst_donate_mysqldump (const char* addr, int ret = sst_mysqldump_check_addr (user, pswd, host, port); if (!ret) { - size_t cmd_len= 1024; - char cmd_str[cmd_len]; + char cmd_str[1024]; if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); - snprintf (cmd_str, cmd_len, + snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_mysqldump " WSREP_SST_OPT_USER" '%s' " WSREP_SST_OPT_PSWD" '%s' " @@ -808,11 +806,13 @@ static int sst_flush_tables(THD* thd) { WSREP_INFO("Tables flushed."); const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; - char real_name[full_len]; - sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); - char tmp_name[full_len + 4]; - sprintf(tmp_name, "%s.tmp", real_name); + char *real_name= (char *) alloca(full_len); + snprintf(real_name, (size_t) full_len, "%s/%s", mysql_real_data_home, + base_name); + char *tmp_name= (char *) alloca(full_len + 4); + snprintf(tmp_name, (size_t) full_len + 4, "%s.tmp", real_name); FILE* file= fopen(tmp_name, "w+"); if (0 == file) @@ -970,10 +970,9 @@ static int sst_donate_other (const char* method, wsrep_seqno_t seqno, bool bypass) { - ssize_t cmd_len = 4096; - char cmd_str[cmd_len]; + char cmd_str[4096]; - int ret= snprintf (cmd_str, cmd_len, + int ret= snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_%s " WSREP_SST_OPT_ROLE" 'donor' " WSREP_SST_OPT_ADDR" '%s' " @@ -988,7 +987,7 @@ static int sst_donate_other (const char* method, uuid, (long long) seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || ret >= (int) sizeof(cmd_str)) { WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c index 8ae6ea962ec..0825d7e9ecf 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep/wsrep_loader.c @@ -39,11 +39,10 @@ static wsrep_log_cb_t logger = default_logger; static int verify(const wsrep_t *wh, const char *iface_ver) { - const size_t msg_len = 128; - char msg[msg_len]; + char msg[128]; #define VERIFY(_p) if (!(_p)) { \ - snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ + snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \ logger (WSREP_LOG_ERROR, msg); \ return EINVAL; \ } @@ -52,7 +51,7 @@ static int verify(const wsrep_t *wh, const char *iface_ver) VERIFY(wh->version); if (strcmp(wh->version, iface_ver)) { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "provider interface version mismatch: need '%s', found '%s'", iface_ver, wh->version); logger (WSREP_LOG_ERROR, msg); @@ -115,9 +114,7 @@ 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; - const size_t msg_len = 1024; - char msg[msg_len + 1]; - msg[msg_len] = 0; + char msg[1024]; if (NULL != log_cb) logger = log_cb; @@ -125,7 +122,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) if (!(spec && hptr)) return EINVAL; - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): loading provider library '%s'", spec); logger (WSREP_LOG_INFO, msg); @@ -143,7 +140,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) { - snprintf(msg, msg_len, "wsrep_load(): dlopen(): %s", dlerror()); + snprintf(msg, sizeof(msg), "wsrep_load(): dlopen(): %s", dlerror()); logger (WSREP_LOG_ERROR, msg); ret = EINVAL; goto out; @@ -155,14 +152,14 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if ((ret = (*dlfun)(*hptr)) != 0) { - snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", + snprintf(msg, sizeof(msg), "wsrep_load(): loader failed: %s", strerror(ret)); logger (WSREP_LOG_ERROR, msg); goto out; } if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): interface version mismatch: my version %s, " "provider version %s", WSREP_INTERFACE_VERSION, (*hptr)->version); @@ -178,7 +175,7 @@ out: free(*hptr); *hptr = NULL; } else { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): %s %s by %s loaded successfully.", (*hptr)->provider_name, (*hptr)->provider_version, (*hptr)->provider_vendor); From 360ff3b0da557dc9fdbf3178ccaf084e6cb36cd0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 20 Feb 2015 17:29:03 -0500 Subject: [PATCH 219/294] Fix for build failures on Power8 --- sql/events.cc | 2 +- sql/wsrep_sst.cc | 33 +++++++++++++-------------- storage/innobase/handler/ha_innodb.cc | 27 +++++++++++----------- wsrep/wsrep_loader.c | 21 ++++++++--------- 4 files changed, 39 insertions(+), 44 deletions(-) diff --git a/sql/events.cc b/sql/events.cc index b675dafe01f..357695cdced 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1132,7 +1132,7 @@ Events::load_events_from_db(THD *thd) #ifdef WITH_WSREP // when SST from master node who initials event, the event status is ENABLED // this is problematic because there are two nodes with same events and both enabled. - if (et->originator != thd->variables.server_id) + if (et->originator != (longlong) thd->variables.server_id) { store_record(table, record[1]); table->field[ET_FIELD_STATUS]-> diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index c122d88f7cc..69f6b019d6b 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -440,8 +440,7 @@ static ssize_t sst_prepare_other (const char* method, const char* addr_in, const char** addr_out) { - ssize_t cmd_len= 1024; - char cmd_str[cmd_len]; + char cmd_str[1024]; const char* sst_dir= mysql_real_data_home; const char* binlog_opt= ""; char* binlog_opt_val= NULL; @@ -456,7 +455,7 @@ static ssize_t sst_prepare_other (const char* method, if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; - ret= snprintf (cmd_str, cmd_len, + ret= snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_%s " WSREP_SST_OPT_ROLE" 'joiner' " WSREP_SST_OPT_ADDR" '%s' " @@ -470,7 +469,7 @@ static ssize_t sst_prepare_other (const char* method, binlog_opt, binlog_opt_val); my_free(binlog_opt_val); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || ret >= (int)sizeof(cmd_str)) { WSREP_ERROR("sst_prepare_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); @@ -721,7 +720,7 @@ static int sst_donate_mysqldump (const char* addr, host_len = strlen (addr) + 1; } - char host[host_len]; + char *host= (char *) alloca(host_len); strncpy (host, addr, host_len - 1); host[host_len - 1] = '\0'; @@ -741,7 +740,7 @@ static int sst_donate_mysqldump (const char* addr, user_len = (auth) ? strlen (auth) + 1 : 1; } - char user[user_len]; + char *user= (char *) alloca(user_len); strncpy (user, (auth) ? auth : "", user_len - 1); user[user_len - 1] = '\0'; @@ -749,12 +748,11 @@ static int sst_donate_mysqldump (const char* addr, int ret = sst_mysqldump_check_addr (user, pswd, host, port); if (!ret) { - size_t cmd_len= 1024; - char cmd_str[cmd_len]; + char cmd_str[1024]; if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); - snprintf (cmd_str, cmd_len, + snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_mysqldump " WSREP_SST_OPT_USER" '%s' " WSREP_SST_OPT_PSWD" '%s' " @@ -850,11 +848,13 @@ static int sst_flush_tables(THD* thd) { WSREP_INFO("Tables flushed."); const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; - char real_name[full_len]; - sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); - char tmp_name[full_len + 4]; - sprintf(tmp_name, "%s.tmp", real_name); + char *real_name= (char *) alloca(full_len); + snprintf(real_name, (size_t) full_len, "%s/%s", mysql_real_data_home, + base_name); + char *tmp_name= (char *) alloca(full_len + 4); + snprintf(tmp_name, (size_t) full_len + 4, "%s.tmp", real_name); FILE* file= fopen(tmp_name, "w+"); if (0 == file) @@ -1014,8 +1014,7 @@ static int sst_donate_other (const char* method, wsrep_seqno_t seqno, bool bypass) { - ssize_t cmd_len = 4096; - char cmd_str[cmd_len]; + char cmd_str[4096]; const char* binlog_opt= ""; char* binlog_opt_val= NULL; @@ -1027,7 +1026,7 @@ static int sst_donate_other (const char* method, } if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; - ret= snprintf (cmd_str, cmd_len, + ret= snprintf (cmd_str, sizeof(cmd_str), "wsrep_sst_%s " WSREP_SST_OPT_ROLE" 'donor' " WSREP_SST_OPT_ADDR" '%s' " @@ -1045,7 +1044,7 @@ static int sst_donate_other (const char* method, bypass ? " "WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); - if (ret < 0 || ret >= cmd_len) + if (ret < 0 || ret >= (int) sizeof(cmd_str)) { WSREP_ERROR("sst_donate_other(): snprintf() failed: %d", ret); return (ret < 0 ? ret : -EMSGSIZE); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ecd51fcb3a2..b55d13c7d8b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -9782,7 +9782,6 @@ ha_innobase::wsrep_append_keys( uint len; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char *key = &keyval[0]; - KEY *key_info = table->key_info; ibool is_null; len = wsrep_store_key_val_for_row( @@ -17251,18 +17250,18 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, if (!thd) { DBUG_PRINT("wsrep", ("no thd for conflicting lock")); - WSREP_WARN("no THD for trx: %llu", victim_trx->id); + WSREP_WARN("no THD for trx: %lu", victim_trx->id); DBUG_RETURN(1); } if (!bf_thd) { DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); - WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0); + WSREP_WARN("no BF THD for trx: %lu", (bf_trx) ? bf_trx->id : 0); DBUG_RETURN(1); } WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); - WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %lu", signal, (long long)bf_seqno, wsrep_thd_thread_id(thd), victim_trx->id); @@ -17273,12 +17272,12 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, wsrep_thd_LOCK(thd); if (wsrep_thd_query_state(thd) == QUERY_EXITING) { - WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id); + WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id); wsrep_thd_UNLOCK(thd); DBUG_RETURN(0); } if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { - WSREP_DEBUG("withdraw for BF trx: %llu, state: %d", + WSREP_DEBUG("withdraw for BF trx: %lu, state: %d", victim_trx->id, wsrep_thd_conflict_state(thd)); } @@ -17288,7 +17287,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, wsrep_thd_set_conflict_state(thd, MUST_ABORT); break; case MUST_ABORT: - WSREP_DEBUG("victim %llu in MUST ABORT state", + WSREP_DEBUG("victim %lu in MUST ABORT state", victim_trx->id); wsrep_thd_UNLOCK(thd); wsrep_thd_awake(thd, signal); @@ -17297,7 +17296,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, case ABORTED: case ABORTING: // fall through default: - WSREP_DEBUG("victim %llu in state %d", + WSREP_DEBUG("victim %lu in state %d", victim_trx->id, wsrep_thd_conflict_state(thd)); wsrep_thd_UNLOCK(thd); DBUG_RETURN(0); @@ -17310,7 +17309,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, WSREP_DEBUG("kill query for: %ld", wsrep_thd_thread_id(thd)); - WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", + WSREP_DEBUG("kill trx QUERY_COMMITTING for %lu", victim_trx->id); if (wsrep_thd_exec_mode(thd) == REPL_RECV) { @@ -17324,7 +17323,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, switch (rcode) { case WSREP_WARNING: - WSREP_DEBUG("cancel commit warning: %llu", + WSREP_DEBUG("cancel commit warning: %lu", victim_trx->id); wsrep_thd_UNLOCK(thd); wsrep_thd_awake(thd, signal); @@ -17334,8 +17333,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, break; default: WSREP_ERROR( - "cancel commit bad exit: %d %llu", - rcode, + "cancel commit bad exit: %d %lu", + rcode, victim_trx->id); /* unable to interrupt, must abort */ /* note: kill_mysql() will block, if we cannot. @@ -17352,7 +17351,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, /* 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 %llu", victim_trx->id); + WSREP_DEBUG("kill trx QUERY_EXEC for %lu", victim_trx->id); victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; if (victim_trx->lock.wait_lock) { @@ -17390,7 +17389,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, bool skip_abort= false; wsrep_aborting_thd_t abortees; - WSREP_DEBUG("kill IDLE for %llu", victim_trx->id); + WSREP_DEBUG("kill IDLE for %lu", victim_trx->id); if (wsrep_thd_exec_mode(thd) == REPL_RECV) { WSREP_DEBUG("kill BF IDLE, seqno: %lld", diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c index 8ae6ea962ec..0825d7e9ecf 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep/wsrep_loader.c @@ -39,11 +39,10 @@ static wsrep_log_cb_t logger = default_logger; static int verify(const wsrep_t *wh, const char *iface_ver) { - const size_t msg_len = 128; - char msg[msg_len]; + char msg[128]; #define VERIFY(_p) if (!(_p)) { \ - snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ + snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \ logger (WSREP_LOG_ERROR, msg); \ return EINVAL; \ } @@ -52,7 +51,7 @@ static int verify(const wsrep_t *wh, const char *iface_ver) VERIFY(wh->version); if (strcmp(wh->version, iface_ver)) { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "provider interface version mismatch: need '%s', found '%s'", iface_ver, wh->version); logger (WSREP_LOG_ERROR, msg); @@ -115,9 +114,7 @@ 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; - const size_t msg_len = 1024; - char msg[msg_len + 1]; - msg[msg_len] = 0; + char msg[1024]; if (NULL != log_cb) logger = log_cb; @@ -125,7 +122,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) if (!(spec && hptr)) return EINVAL; - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): loading provider library '%s'", spec); logger (WSREP_LOG_INFO, msg); @@ -143,7 +140,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) { - snprintf(msg, msg_len, "wsrep_load(): dlopen(): %s", dlerror()); + snprintf(msg, sizeof(msg), "wsrep_load(): dlopen(): %s", dlerror()); logger (WSREP_LOG_ERROR, msg); ret = EINVAL; goto out; @@ -155,14 +152,14 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if ((ret = (*dlfun)(*hptr)) != 0) { - snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", + snprintf(msg, sizeof(msg), "wsrep_load(): loader failed: %s", strerror(ret)); logger (WSREP_LOG_ERROR, msg); goto out; } if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): interface version mismatch: my version %s, " "provider version %s", WSREP_INTERFACE_VERSION, (*hptr)->version); @@ -178,7 +175,7 @@ out: free(*hptr); *hptr = NULL; } else { - snprintf (msg, msg_len, + snprintf (msg, sizeof(msg), "wsrep_load(): %s %s by %s loaded successfully.", (*hptr)->provider_name, (*hptr)->provider_version, (*hptr)->provider_vendor); From f68ce6860454379f65131046dbba8cd4e65acda1 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 20 Feb 2015 17:51:33 -0500 Subject: [PATCH 220/294] MDEV-7615: Remove --galera-sst-mode option from mysqldump Removed 'galera-sst-mode' option from mysqldump and added logic in wsrep_sst_mysqldump script to retrieve gtid_binlog_state from donor node and send it to the joiner node. --- client/mysqldump.c | 49 ------------------------------- mysql-test/t/galera_sst_mode.test | 43 --------------------------- scripts/wsrep_sst_mysqldump.sh | 49 +++++++++++++++++-------------- 3 files changed, 27 insertions(+), 114 deletions(-) delete mode 100644 mysql-test/t/galera_sst_mode.test diff --git a/client/mysqldump.c b/client/mysqldump.c index 3adbe87a8bb..e1181985499 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -114,7 +114,6 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_slave_apply= 0, opt_include_master_host_port= 0, opt_events= 0, opt_comments_used= 0, - opt_galera_sst_mode= 0, opt_alltspcs=0, opt_notspcs= 0; static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; @@ -351,14 +350,6 @@ static struct my_option my_long_options[] = {"force", 'f', "Continue even if we get an SQL error.", &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"galera-sst-mode", OPT_GALERA_SST_MODE, - "This mode should normally be used in mysqldump snapshot state transfer " - "(SST) in a Galera cluster. If enabled, mysqldump additionally dumps " - "commands to turn off binary logging and SET global gtid_binlog_state " - "with the current value. Note: RESET MASTER needs to be executed on the " - "server receiving the resulting dump.", - &opt_galera_sst_mode, &opt_galera_sst_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, - 0, 0, 0}, {"gtid", OPT_USE_GTID, "Used together with --master-data=1 or --dump-slave=1." "When enabled, the output from those options will set the GTID position " "instead of the binlog file and offset; the file/offset will appear only as " @@ -4903,43 +4894,6 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } /* dump_selected_tables */ -/** - Add the following statements to the generated dump: - a) SET @@session.sql_log_bin=OFF; - b) SET @@global.gtid_binlog_state='[N-N-N,...]' -*/ -static int wsrep_set_sst_cmds(MYSQL *mysql) { - MYSQL_RES *res; - MYSQL_ROW row; - - if (mysql_get_server_version(mysql) < 100005) { - /* @@gtid_binlog_state does not exist. */ - return 0; - } - - if (mysql_query_with_error_report(mysql, &res, "SELECT " - "@@global.gtid_binlog_state")) - return 1; - - if (mysql_num_rows(res) != 1) - /* No entry for @@global.gtid_binlog_state, nothing needs to be done. */ - return 0; - - if (!(row= mysql_fetch_row(res)) || !(char *)row[0]) - return 1; - - /* first, add a command to turn off binary logging, */ - fprintf(md_result_file, "SET @@session.sql_log_bin=OFF;\n"); - - /* followed by, a command to set global gtid_binlog_state. */ - fprintf(md_result_file, "SET @@global.gtid_binlog_state='%s';\n", - (char*)row[0]); - - mysql_free_result(res); - return 0; -} - - static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos, int have_mariadb_gtid, int use_gtid) { @@ -5936,9 +5890,6 @@ int main(int argc, char **argv) if (opt_slave_apply && add_stop_slave()) goto err; - if (opt_galera_sst_mode && wsrep_set_sst_cmds(mysql)) - goto err; - if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos, have_mariadb_gtid, opt_use_gtid)) goto err; diff --git a/mysql-test/t/galera_sst_mode.test b/mysql-test/t/galera_sst_mode.test deleted file mode 100644 index dd8f9531c9d..00000000000 --- a/mysql-test/t/galera_sst_mode.test +++ /dev/null @@ -1,43 +0,0 @@ -# Embedded server doesn't support external clients ---source include/not_embedded.inc -# Binlog is required ---source include/have_log_bin.inc - ---echo # ---echo # Test for mysqldump's galera-sst-mode option ---echo # - ---echo # ---echo # MDEV-6490: mysqldump unknown option --galera-sst-mode ---echo # -CREATE DATABASE bug6490; -USE bug6490; -CREATE TABLE t1(c1 INT); -INSERT INTO t1 values (1); -INSERT INTO t1 values (2); - ---echo # Save the current gtid_binlog_state. ---let $before= `SELECT @@global.gtid_binlog_state` - ---echo # Take a dump of bug6490 database ---exec $MYSQL_DUMP --galera-sst-mode bug6490 > $MYSQLTEST_VARDIR/tmp/bug6490.sql -DROP TABLE t1; - ---echo # Load the dump -RESET MASTER; ---exec $MYSQL -uroot bug6490 < $MYSQLTEST_VARDIR/tmp/bug6490.sql - -SELECT * from t1; - ---echo # Compare the two gtid_binlog_state's ---let $after= `SELECT @@global.gtid_binlog_state` -if (`SELECT STRCMP($before, $after)`) -{ - --die ERROR: The two gtid_binlog_state's did not match. -} - ---echo # Cleanup ---remove_file $MYSQLTEST_VARDIR/tmp/bug6490.sql -DROP DATABASE bug6490; - ---echo # End of test diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 3f4ada39a9d..df6f816132c 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -22,13 +22,12 @@ WSREP_SST_OPT_CONF="" . $(dirname $0)/wsrep_sst_common +PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin EINVAL=22 local_ip() { - PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin - [ "$1" = "127.0.0.1" ] && return 0 [ "$1" = "localhost" ] && return 0 [ "$1" = "$(hostname -s)" ] && return 0 @@ -97,33 +96,39 @@ DROP PREPARE stmt;" SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" +# Retrieve the donor's @@global.gtid_binlog_state. +GTID_BINLOG_STATE=$(echo "SHOW GLOBAL VARIABLES LIKE 'gtid_binlog_state'" |\ +mysql $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeout=10 |\ +tail -1 | awk -F ' ' '{ print $2 }') + MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ "--disable-reconnect --connect_timeout=10" -RESET_MASTER="" -OPT_GALERA_SST_MODE="" # Check if binary logging is enabled on the joiner node. # Note: SELECT cannot be used at this point. -LOG_BIN=$(echo "SHOW VARIABLES LIKE 'log_bin'" | $MYSQL) -LOG_BIN=$(echo $LOG_BIN | awk -F ' ' '{ print $4 }') +LOG_BIN=$(echo "SHOW VARIABLES LIKE 'log_bin'" | $MYSQL |\ +tail -1 | awk -F ' ' '{ print $2 }') # Check the joiner node's server version. -SERVER_VERSION=$(echo "SHOW VARIABLES LIKE 'version'" | $MYSQL) -SERVER_VERSION=$(echo $SERVER_VERSION | awk -F ' ' '{ print $4 }') +SERVER_VERSION=$(echo "SHOW VARIABLES LIKE 'version'" | $MYSQL |\ +tail -1 | awk -F ' ' '{ print $2 }') + +RESET_MASTER="" +SET_GTID_BINLOG_STATE="" +SQL_LOG_BIN_OFF="" # Safety check if echo $SERVER_VERSION | grep '^10.0' > /dev/null then - # Check if binary logging is enabled on the Joiner node. If it is enabled, - # RESET MASTER needs to be executed on the Joiner node. Also, mysqldump - # should be executed with additional 'galera-sst-mode' option so that it - # adds a command to set gtid_binlog_state with that of Donor node in the - # dump, to be executed on the Joiner. + # If binary logging is enabled on the joiner node, we need to copy donor's + # gtid_binlog_state to joiner. In order to do that, a RESET MASTER must be + # executed to erase binary logs (if any). Binary logging should also be + # 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 for 10.0 to clear gtid state. RESET_MASTER="RESET MASTER;" - # Set the galera-sst-mode option for mysqldump. - OPT_GALERA_SST_MODE="--galera-sst-mode" + SET_GTID_BINLOG_STATE="SET @@global.gtid_binlog_state='$GTID_BINLOG_STATE';" + SQL_LOG_BIN_OFF="SET @@session.sql_log_bin=OFF;" fi fi @@ -131,7 +136,7 @@ fi MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ --add-drop-database --add-drop-table --skip-add-locks --create-options \ --disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ ---skip-comments --flush-privileges --all-databases $OPT_GALERA_SST_MODE" +--skip-comments --flush-privileges --all-databases" # need to disable logging when loading the dump # reason is that dump contains ALTER TABLE for log tables, and @@ -148,11 +153,11 @@ RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then - (echo $STOP_WSREP && echo $RESET_MASTER) | $MYSQL || true - (echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX \ - && echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG \ - && echo $SET_START_POSITION \ - || echo "SST failed to complete;") | $MYSQL + (echo $STOP_WSREP && echo $RESET_MASTER && \ + echo $SET_GTID_BINLOG_STATE && echo $SQL_LOG_BIN_OFF && \ + echo $STOP_WSREP && $MYSQLDUMP && echo $CSV_TABLES_FIX && \ + echo $RESTORE_GENERAL_LOG && echo $RESTORE_SLOW_QUERY_LOG && \ + echo $SET_START_POSITION || echo "SST failed to complete;") | $MYSQL else wsrep_log_info "Bypassing state dump." echo $SET_START_POSITION | $MYSQL From f02fdb6b55a2b29595cb7e4eed48a51755e967fb Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 20 Feb 2015 22:11:45 -0500 Subject: [PATCH 221/294] MDEV-7615: remove galera_sst_mode.result file --- mysql-test/r/galera_sst_mode.result | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 mysql-test/r/galera_sst_mode.result diff --git a/mysql-test/r/galera_sst_mode.result b/mysql-test/r/galera_sst_mode.result deleted file mode 100644 index ea25b322449..00000000000 --- a/mysql-test/r/galera_sst_mode.result +++ /dev/null @@ -1,24 +0,0 @@ -# -# Test for mysqldump's galera-sst-mode option -# -# -# MDEV-6490: mysqldump unknown option --galera-sst-mode -# -CREATE DATABASE bug6490; -USE bug6490; -CREATE TABLE t1(c1 INT); -INSERT INTO t1 values (1); -INSERT INTO t1 values (2); -# Save the current gtid_binlog_state. -# Take a dump of bug6490 database -DROP TABLE t1; -# Load the dump -RESET MASTER; -SELECT * from t1; -c1 -1 -2 -# Compare the two gtid_binlog_state's -# Cleanup -DROP DATABASE bug6490; -# End of test From 4fb2f6690748833775b888a49501a7057e827be6 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 24 Feb 2015 21:55:22 -0500 Subject: [PATCH 222/294] Changes in wsrep_guess_ip() * Changed loopback detection to be done via ifa->ifa_flags * Removed unused function wsrep_guess_address() --- mysql-test/suite/galera/suite.pm | 2 -- mysql-test/suite/wsrep/suite.pm | 2 -- sql/wsrep_utils.cc | 29 +++++++++++++---------------- sql/wsrep_utils.h | 1 - 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 9c48ad1982d..03bb2e85e81 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -24,8 +24,6 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( - qr(WSREP: Failed to guess base node address), - qr(WSREP: Guessing address for incoming client connections failed), qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: Gap in state sequence. Need state transfer.), diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index f6c8409f6a8..33744a60ad8 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -24,8 +24,6 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( - qr(WSREP: Failed to guess base node address), - qr(WSREP: Guessing address for incoming client connections failed), qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: option --wsrep-casual-reads is deprecated), qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index e6e58a433e7..099e6403dd6 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -35,8 +35,9 @@ #include // getaddrinfo() #ifdef HAVE_GETIFADDRS +#include #include -#endif +#endif /* HAVE_GETIFADDRS */ extern char** environ; // environment variables @@ -406,6 +407,13 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) return ip_len; } + /* + getifaddrs() is avaiable at least on Linux since glib 2.3, FreeBSD, + MAC OSX, OpenSolaris, Solaris. + + On platforms which do not support getifaddrs() this function returns + a failure and user is prompted to do manual configuration. + */ #if HAVE_GETIFADDRS struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == 0) @@ -415,10 +423,11 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) // TODO AF_INET6 continue; - if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST)) + // Skip loopback interfaces (like lo:127.0.0.1) + if (ifa->ifa_flags & IFF_LOOPBACK) continue; - if (strcmp(buf, "127.0.0.1") == 0) // lame + if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST)) continue; freeifaddrs(ifaddr); @@ -426,23 +435,11 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) } freeifaddrs(ifaddr); } -#endif +#endif /* HAVE_GETIFADDRS */ return 0; } -size_t wsrep_guess_address(char* buf, size_t buf_len) -{ - size_t addr_len = wsrep_guess_ip (buf, buf_len); - - if (addr_len && addr_len < buf_len) { - addr_len += snprintf (buf + addr_len, buf_len - addr_len, - ":%u", mysqld_port); - } - - return addr_len; -} - /* * WSREPXid */ diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 337678238f8..dfb68bcd1b7 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -20,7 +20,6 @@ unsigned int wsrep_check_ip (const char* addr); size_t wsrep_guess_ip (char* buf, size_t buf_len); -size_t wsrep_guess_address(char* buf, size_t buf_len); namespace wsp { class node_status From 8ee5668033ed9f4c59cd5bf0b995dd77d326fe36 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 24 Feb 2015 21:55:22 -0500 Subject: [PATCH 223/294] Changes in wsrep_guess_ip() * Changed loopback detection to be done via ifa->ifa_flags * Removed unused function wsrep_guess_address() --- mysql-test/suite/galera/suite.pm | 2 -- mysql-test/suite/wsrep/suite.pm | 2 -- sql/wsrep_utils.cc | 29 +++++++++++++---------------- sql/wsrep_utils.h | 1 - 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 9c48ad1982d..03bb2e85e81 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -24,8 +24,6 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( - qr(WSREP: Failed to guess base node address), - qr(WSREP: Guessing address for incoming client connections failed), qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: Gap in state sequence. Need state transfer.), diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index f6c8409f6a8..33744a60ad8 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -24,8 +24,6 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( - qr(WSREP: Failed to guess base node address), - qr(WSREP: Guessing address for incoming client connections failed), qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: option --wsrep-casual-reads is deprecated), qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 545870f1c07..f30b3dcf702 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -35,8 +35,9 @@ #include // getaddrinfo() #ifdef HAVE_GETIFADDRS +#include #include -#endif +#endif /* HAVE_GETIFADDRS */ extern char** environ; // environment variables @@ -406,6 +407,13 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) return ip_len; } + /* + getifaddrs() is avaiable at least on Linux since glib 2.3, FreeBSD, + MAC OSX, OpenSolaris, Solaris. + + On platforms which do not support getifaddrs() this function returns + a failure and user is prompted to do manual configuration. + */ #if HAVE_GETIFADDRS struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == 0) @@ -415,10 +423,11 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) // TODO AF_INET6 continue; - if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST)) + // Skip loopback interfaces (like lo:127.0.0.1) + if (ifa->ifa_flags & IFF_LOOPBACK) continue; - if (strcmp(buf, "127.0.0.1") == 0) // lame + if (vio_getnameinfo(ifa->ifa_addr, buf, buf_len, NULL, 0, NI_NUMERICHOST)) continue; freeifaddrs(ifaddr); @@ -426,23 +435,11 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) } freeifaddrs(ifaddr); } -#endif +#endif /* HAVE_GETIFADDRS */ return 0; } -size_t wsrep_guess_address(char* buf, size_t buf_len) -{ - size_t addr_len = wsrep_guess_ip (buf, buf_len); - - if (addr_len && addr_len < buf_len) { - addr_len += snprintf (buf + addr_len, buf_len - addr_len, - ":%u", mysqld_port); - } - - return addr_len; -} - /* * WSREPXid */ diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 337678238f8..dfb68bcd1b7 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -20,7 +20,6 @@ unsigned int wsrep_check_ip (const char* addr); size_t wsrep_guess_ip (char* buf, size_t buf_len); -size_t wsrep_guess_address(char* buf, size_t buf_len); namespace wsp { class node_status From aa2904a7f4014cd4790086a2512dc39b533b2a8a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 27 Feb 2015 22:13:37 -0500 Subject: [PATCH 224/294] MDEV-7560: wsrep* tests depend on the version of galera library Added an include file to check galera library version. --- .../wsrep/include/check_galera_version.inc | 24 +++++++++++++++++++ mysql-test/suite/wsrep/t/variables.test | 2 ++ 2 files changed, 26 insertions(+) create mode 100644 mysql-test/suite/wsrep/include/check_galera_version.inc diff --git a/mysql-test/suite/wsrep/include/check_galera_version.inc b/mysql-test/suite/wsrep/include/check_galera_version.inc new file mode 100644 index 00000000000..38b4ada98b9 --- /dev/null +++ b/mysql-test/suite/wsrep/include/check_galera_version.inc @@ -0,0 +1,24 @@ +# ==== Purpose ==== +# Enable tests to check the galera library version. +# +# ==== Usage ==== +# --let $galera_version=25.3.6 +# source include/check_galera_lib_version.inc; +# +# Parameters: +# $galera_version +# Version of the galera library required by the test. +# + +--disable_query_log + +eval SET @GALERA_VERSION=(SELECT CONCAT('$galera_version', '%')); + +if (!`SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE + VARIABLE_NAME LIKE 'wsrep_provider_version' AND + VARIABLE_VALUE LIKE @GALERA_VERSION`) +{ + skip Test requires Galera library version $galera_version; +} + +--enable_query_log diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 63678a2cf34..ec405969eba 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -28,6 +28,8 @@ CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*") --disable_query_log eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; +--let $galera_version=25.3.5 +source include/check_galera_version.inc; --enable_query_log --replace_column 2 # From e52a58a5cc338a82a9de446785f81c8f45064fa5 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 4 Mar 2015 19:49:17 -0500 Subject: [PATCH 225/294] Update galera package name --- debian/dist/Debian/control | 2 +- debian/dist/Ubuntu/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 5fe19dbd0f5..5472ce86b28 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -42,7 +42,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, - libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + libmariadbclient18 (>= ${binary:Version}), galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 02df9e4a5f5..ce58ed94914 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -42,7 +42,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-5.5 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, - libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + libmariadbclient18 (>= ${binary:Version}), galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, findutils Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server, virtual-mysql-server, mariadb-galera-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), mariadb-galera-server (<< ${source:Version}), From 73a143ab34be0007cc0fc17cf5fda00fef063c1c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 4 Mar 2015 19:52:15 -0500 Subject: [PATCH 226/294] Update galera package name --- debian/dist/Debian/control | 2 +- debian/dist/Ubuntu/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index c653b7e3ed1..47a53ed8801 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -44,7 +44,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, - libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + libmariadbclient18 (>= ${binary:Version}), galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, findutils, tar Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server-core-10.0, mariadb-server, mysql-server, diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 84027e39cc6..8dc2551be2b 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -44,7 +44,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-10.0 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), bsdutils, - libmariadbclient18 (>= ${binary:Version}), galera (>=25.2), + libmariadbclient18 (>= ${binary:Version}), galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, findutils, tar Provides: mysql-server-core, mysql-server-core-5.1, mysql-server-core-5.5, mysql-server-core-10.0, mariadb-server, mysql-server, From 9af42db6138a555454b7631761b81f8d259f014e Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 5 Mar 2015 14:14:00 -0500 Subject: [PATCH 227/294] MDEV-7192: binlog_annotate_row_events not completely compatible with galera Annotate_rows event needs to be preserved until the last Rows event has been applied because after it has been applied thd->query points to the query stored inside this event. --- .../suite/galera/r/rpl_row_annotate.result | 66 +++++++++++++++++++ .../suite/galera/t/rpl_row_annotate.cnf | 6 ++ .../suite/galera/t/rpl_row_annotate.test | 42 ++++++++++++ sql/wsrep_applier.cc | 8 ++- sql/wsrep_thd.cc | 11 +++- 5 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera/r/rpl_row_annotate.result create mode 100644 mysql-test/suite/galera/t/rpl_row_annotate.cnf create mode 100644 mysql-test/suite/galera/t/rpl_row_annotate.test diff --git a/mysql-test/suite/galera/r/rpl_row_annotate.result b/mysql-test/suite/galera/r/rpl_row_annotate.result new file mode 100644 index 00000000000..ff8d49702ac --- /dev/null +++ b/mysql-test/suite/galera/r/rpl_row_annotate.result @@ -0,0 +1,66 @@ +# On node_2 +RESET MASTER; +# On node_1 +RESET MASTER; +CREATE TABLE t1(i INT)ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +DELETE FROM t1 WHERE i = 1; +# On node_2 +INSERT INTO t1 VALUES(2); +DELETE FROM t1 WHERE i = 2; +# On node_1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM ; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 # Gtid_list 1 # [] +mysqld-bin.000001 # Binlog_checkpoint 1 # mysqld-bin.000001 +mysqld-bin.000001 # Gtid 1 # GTID 0-1-1 +mysqld-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(i INT)ENGINE=INNODB +mysqld-bin.000001 # Gtid 1 # BEGIN GTID 0-1-2 +mysqld-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES(1) +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 1 # BEGIN GTID 0-1-3 +mysqld-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE i = 1 +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 2 # BEGIN GTID 0-2-4 +mysqld-bin.000001 # Annotate_rows 2 # INSERT INTO t1 VALUES(2) +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows_v1 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 2 # BEGIN GTID 0-2-5 +mysqld-bin.000001 # Annotate_rows 2 # DELETE FROM t1 WHERE i = 2 +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= */ +# On node_2 +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM ; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 # Gtid_list 2 # [] +mysqld-bin.000001 # Binlog_checkpoint 2 # mysqld-bin.000001 +mysqld-bin.000001 # Gtid 1 # GTID 0-1-1 +mysqld-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(i INT)ENGINE=INNODB +mysqld-bin.000001 # Gtid 1 # BEGIN GTID 0-1-2 +mysqld-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES(1) +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 1 # BEGIN GTID 0-1-3 +mysqld-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE i = 1 +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 2 # BEGIN GTID 0-2-4 +mysqld-bin.000001 # Annotate_rows 2 # INSERT INTO t1 VALUES(2) +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows_v1 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +mysqld-bin.000001 # Gtid 2 # BEGIN GTID 0-2-5 +mysqld-bin.000001 # Annotate_rows 2 # DELETE FROM t1 WHERE i = 2 +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; +# End of test diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.cnf b/mysql-test/suite/galera/t/rpl_row_annotate.cnf new file mode 100644 index 00000000000..1f1d83dfa0b --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_row_annotate.cnf @@ -0,0 +1,6 @@ +!include ../galera_2nodes.cnf + +[mysqld] +log-bin +log-slave-updates +binlog-annotate-row-events=ON diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.test b/mysql-test/suite/galera/t/rpl_row_annotate.test new file mode 100644 index 00000000000..b1cfdb36639 --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_row_annotate.test @@ -0,0 +1,42 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # On node_2 +--connection node_2 +RESET MASTER; + +--echo # On node_1 +--connection node_1 +RESET MASTER; +CREATE TABLE t1(i INT)ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +DELETE FROM t1 WHERE i = 1; + +--echo # On node_2 +--connection node_2 +INSERT INTO t1 VALUES(2); +DELETE FROM t1 WHERE i = 2; + +--echo # On node_1 +--connection node_1 +--source include/binlog_start_pos.inc +let $start_pos= `select @binlog_start_pos`; +--replace_column 2 # 5 # +--replace_result $start_pos +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM $start_pos + +--echo # On node_2 +--connection node_2 +--source include/binlog_start_pos.inc +let $start_pos= `select @binlog_start_pos`; +--replace_column 2 # 5 # +--replace_result $start_pos +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM $start_pos + +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 03d356aa046..6f1ead89158 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -92,6 +92,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, char *buf= (char *)events_buf; int rcode= 0; int event= 1; + Log_event_type typ; DBUG_ENTER("wsrep_apply_events"); @@ -126,7 +127,9 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, goto error; } - switch (ev->get_type_code()) { + typ= ev->get_type_code(); + + switch (typ) { case FORMAT_DESCRIPTION_EVENT: wsrep_set_apply_format(thd, (Format_description_log_event*)ev); continue; @@ -160,7 +163,6 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, } ev->thd = thd; - //exec_res = ev->apply_event(thd->wsrep_rli); exec_res = ev->apply_event(thd->wsrep_rgi); DBUG_PRINT("info", ("exec_event result: %d", exec_res)); @@ -192,7 +194,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, DBUG_RETURN(WSREP_CB_FAILURE); } - delete ev; + delete_or_keep_event_post_apply(thd->wsrep_rgi, typ, ev); } error: diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index b01737d1d5c..81999d11296 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -121,10 +121,13 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname) */ rli->mi = new Master_info(&connection_name, false); - rli->sql_driver_thd= current_thd; - struct rpl_group_info *rgi= new rpl_group_info(rli); - rgi->thd= current_thd; + 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; } @@ -172,6 +175,8 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) 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; } From 6f9e33ecb020bcf3e6db246bc04a9be153c63dc4 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 26 Dec 2014 23:38:45 +0400 Subject: [PATCH 228/294] MDEV-7273 - 10.1 fails to start up during tc_log initializations on PPC64 log-tc-size is 24K by default. Page size is 64K on PPC64. But log-tc- size must be at least 3 x page size. This is enforced by TC_LOG_MMAP::open() with a comment: to guarantee non-empty pool. This all makes server not startable in default configuration on PPC64. Autosize log-tc-size, so that it's min value= page size * 3, default value= page size * 6, block size= page size. Conflicts: mysql-test/suite/sys_vars/inc/sysvars_server.inc mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result mysql-test/t/mysqld--help.test sql/mysqld.cc sql/sys_vars.cc --- mysql-test/r/mysqld--help.result | 1 - mysql-test/suite/sys_vars/r/log_tc_size_basic.result | 4 ++++ mysql-test/suite/sys_vars/t/log_tc_size_basic.test | 5 +++++ mysql-test/t/mysqld--help.test | 2 +- sql/log.cc | 11 +++++------ sql/log.h | 3 +-- sql/mysqld.cc | 6 ------ sql/sys_vars.cc | 10 ++++++++++ 8 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/log_tc_size_basic.result create mode 100644 mysql-test/suite/sys_vars/t/log_tc_size_basic.test diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index e4db1fa2aba..44b3d8df0f9 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1248,7 +1248,6 @@ log-slow-rate-limit 1 log-slow-slave-statements FALSE log-slow-verbosity log-tc tc.log -log-tc-size 24576 log-warnings 1 long-query-time 10 low-priority-updates FALSE diff --git a/mysql-test/suite/sys_vars/r/log_tc_size_basic.result b/mysql-test/suite/sys_vars/r/log_tc_size_basic.result new file mode 100644 index 00000000000..8097fcf61bd --- /dev/null +++ b/mysql-test/suite/sys_vars/r/log_tc_size_basic.result @@ -0,0 +1,4 @@ +SET GLOBAL log_tc_size=1; +ERROR HY000: Variable 'log_tc_size' is a read only variable +SET SESSION log_tc_size=1; +ERROR HY000: Variable 'log_tc_size' is a read only variable diff --git a/mysql-test/suite/sys_vars/t/log_tc_size_basic.test b/mysql-test/suite/sys_vars/t/log_tc_size_basic.test new file mode 100644 index 00000000000..221338d0304 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/log_tc_size_basic.test @@ -0,0 +1,5 @@ +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET GLOBAL log_tc_size=1; + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET SESSION log_tc_size=1; diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 96bbfccb568..0f46300a440 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -22,7 +22,7 @@ perl; log-slow-queries pid-file slow-query-log-file log-basename datadir slave-load-tmpdir tmpdir socket thread-pool-size large-files-support lower-case-file-system system-time-zone - wsrep-node-name wsrep-data-home-dir version.*/; + wsrep-node-name wsrep-data-home-dir log-tc-size version.*/; # Plugins which may or may not be there: @plugins=qw/innodb ndb archive blackhole federated partition ndbcluster diff --git a/sql/log.cc b/sql/log.cc index 69e0ed34b01..37e19dac564 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8432,7 +8432,7 @@ ulong tc_log_page_waits= 0; static const uchar tc_log_magic[]={(uchar) 254, 0x23, 0x05, 0x74}; -ulong opt_tc_log_size= TC_LOG_MIN_SIZE; +ulong opt_tc_log_size; ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0; int TC_LOG_MMAP::open(const char *opt_name) @@ -8445,7 +8445,6 @@ int TC_LOG_MMAP::open(const char *opt_name) DBUG_ASSERT(opt_name && opt_name[0]); tc_log_page_size= my_getpagesize(); - DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0); fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME); if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0) @@ -8784,6 +8783,7 @@ mmap_do_checkpoint_callback(void *data) int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid) { pending_cookies *full_buffer= NULL; + uint32 ncookies= tc_log_page_size / sizeof(my_xid); DBUG_ASSERT(*(my_xid *)(data+cookie) == xid); /* @@ -8797,7 +8797,7 @@ int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid) mysql_mutex_lock(&LOCK_pending_checkpoint); if (pending_checkpoint == NULL) { - uint32 size= sizeof(*pending_checkpoint); + uint32 size= sizeof(*pending_checkpoint) + sizeof(ulong) * (ncookies - 1); if (!(pending_checkpoint= (pending_cookies *)my_malloc(size, MYF(MY_ZEROFILL)))) { @@ -8808,8 +8808,7 @@ int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid) } pending_checkpoint->cookies[pending_checkpoint->count++]= cookie; - if (pending_checkpoint->count == sizeof(pending_checkpoint->cookies) / - sizeof(pending_checkpoint->cookies[0])) + if (pending_checkpoint->count == ncookies) { full_buffer= pending_checkpoint; pending_checkpoint= NULL; @@ -8843,7 +8842,7 @@ TC_LOG_MMAP::commit_checkpoint_notify(void *cookie) if (count == 0) { uint i; - for (i= 0; i < sizeof(pending->cookies)/sizeof(pending->cookies[0]); ++i) + for (i= 0; i < tc_log_page_size / sizeof(my_xid); ++i) delete_entry(pending->cookies[i]); my_free(pending); } diff --git a/sql/log.h b/sql/log.h index bda6e55e0c9..3d0413530e8 100644 --- a/sql/log.h +++ b/sql/log.h @@ -114,7 +114,6 @@ public: }; #define TC_LOG_PAGE_SIZE 8192 -#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE) #ifdef HAVE_MMAP class TC_LOG_MMAP: public TC_LOG @@ -129,7 +128,7 @@ class TC_LOG_MMAP: public TC_LOG struct pending_cookies { uint count; uint pending_count; - ulong cookies[TC_LOG_PAGE_SIZE/sizeof(my_xid)]; + ulong cookies[1]; }; private: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 138d542bc97..6faa52abb7a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7698,12 +7698,6 @@ struct my_option my_long_options[]= "more than one storage engine, when binary log is disabled).", &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_MMAP - {"log-tc-size", 0, "Size of transaction coordinator log.", - &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG, - REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0, - TC_LOG_PAGE_SIZE, 0}, -#endif {"master-info-file", 0, "The location and name of the file that remembers the master and where " "the I/O replication thread is in the master's binlogs. Defaults to " diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fe7e0135fe1..55a7cfc5a4a 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5107,3 +5107,13 @@ static Sys_var_mybool Sys_pseudo_slave_mode( SESSION_ONLY(pseudo_slave_mode), NO_CMD_LINE, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_pseudo_slave_mode)); +#ifdef HAVE_MMAP +static Sys_var_ulong Sys_log_tc_size( + "log_tc_size", + "Size of transaction coordinator log.", + READ_ONLY GLOBAL_VAR(opt_tc_log_size), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(my_getpagesize() * 3, ULONG_MAX), + DEFAULT(my_getpagesize() * 6), + BLOCK_SIZE(my_getpagesize())); +#endif From c6acdf7c281f91026cfac549d718511b9ed083aa Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 6 Mar 2015 13:19:49 -0500 Subject: [PATCH 229/294] MDEV-7203: replicate_events_marked_for_skip didn't work on Galera cluster OPTION_SKIP_REPLICATION flag needs to be preserved for events received on non-originating nodes. --- sql/wsrep_applier.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 6f1ead89158..f8e82f6b805 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -149,8 +149,9 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, break; } - thd->set_server_id(ev->server_id); // use the original server id for logging - thd->set_time(); // time the query + /* Use the original server id for logging. */ + thd->set_server_id(ev->server_id); + thd->set_time(); // time the query wsrep_xid_init(&thd->transaction.xid_state.xid, &thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); @@ -162,6 +163,10 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, ev->when_sec_part= hrtime_sec_part(hrtime); } + thd->variables.option_bits= + (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); DBUG_PRINT("info", ("exec_event result: %d", exec_res)); From d146605124a3d326f3769fd162e0af0a124266a9 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 6 Mar 2015 13:22:15 -0500 Subject: [PATCH 230/294] MDEV-7673: CREATE TABLE SELECT fails on Galera cluster Enable execution of CREATE TABLE SELECT in total order isolation. Added a test case. Contributed by : Andrew W Elble --- mysql-test/suite/galera/r/create.result | 5 +++++ mysql-test/suite/galera/t/create.test | 8 ++++++++ sql/sql_parse.cc | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index 4dffe96d719..2c31ed76d1e 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -20,4 +20,9 @@ i 1 DROP TABLE t1; SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; +# +# MDEV-7673: CREATE TABLE SELECT fails on Galera cluster +# +CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; +DROP TABLE t1; # End of tests diff --git a/mysql-test/suite/galera/t/create.test b/mysql-test/suite/galera/t/create.test index b56a841fb65..38c793e33b6 100644 --- a/mysql-test/suite/galera/t/create.test +++ b/mysql-test/suite/galera/t/create.test @@ -22,5 +22,13 @@ SELECT * FROM t1_temp; DROP TABLE t1; SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; +--echo # +--echo # MDEV-7673: CREATE TABLE SELECT fails on Galera cluster +--echo # +CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; + +# Cleanup +DROP TABLE t1; + --echo # End of tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 280c2202d90..9b7ea777335 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3284,6 +3284,14 @@ case SQLCOM_PREPARE: /* Store reference to table in case of LOCK TABLES */ create_info.table= create_table->table; +#ifdef WITH_WSREP + if (WSREP(thd) && + (!thd->is_current_stmt_binlog_format_row() || + !(create_info.tmp_table()))) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, + NULL) +#endif + /* select_create is currently not re-execution friendly and needs to be created for every execution of a PS/SP. From 6c19f51a5fe6bd0dbecf3cb8fd4f88e4f8da477e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 6 Mar 2015 11:19:23 +0200 Subject: [PATCH 231/294] MDEV-7672: Crash creating an InnoDB table with foreign keys Analysis: after a red-black-tree lookup we use node withouth checking did lookup succeed or not. This lead to situation where NULL-pointer was used. Fix: Add additional check that found node from red-back-tree is valid. --- mysql-test/suite/innodb/r/innodb-fk.result | 32 +++++++++++++++++ mysql-test/suite/innodb/t/innodb-fk.test | 40 ++++++++++++++++++++++ storage/innobase/dict/dict0dict.c | 18 ++++++---- storage/xtradb/dict/dict0dict.c | 18 ++++++---- 4 files changed, 96 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result index cf883d83874..3c557534dbd 100644 --- a/mysql-test/suite/innodb/r/innodb-fk.result +++ b/mysql-test/suite/innodb/r/innodb-fk.result @@ -33,3 +33,35 @@ select * from fk_29; f1 29 drop table t1; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +f1 int(11) DEFAULT NULL, +PRIMARY KEY (id), +CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +f2 int(11) NOT NULL, +f3 int(11) NOT NULL, +PRIMARY KEY (`id`), +CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE, +CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE +) ENGINE=InnoDB; +ERROR HY000: Can't create table 'test.t2' (errno: 150) +show warnings; +Level Code Message +Error 1005 Can't create table 'test.t2' (errno: 150) +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +f2 int(11) NOT NULL, +f3 int(11) NOT NULL, +PRIMARY KEY (`id`), +CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE +) ENGINE=InnoDB; +ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE; +ERROR HY000: Can't create table '#sql-temporary' (errno: 150) +show warnings; +Level Code Message +Error 1005 Can't create table '#sql-temporary' (errno: 150) +drop table t2; +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test index 9839cd2d084..9bfd16b88e9 100644 --- a/mysql-test/suite/innodb/t/innodb-fk.test +++ b/mysql-test/suite/innodb/t/innodb-fk.test @@ -84,3 +84,43 @@ while ($i) drop table t1; +# +# MDEV-7672: Crash creating an InnoDB table with foreign keys +# + +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + f1 int(11) DEFAULT NULL, + PRIMARY KEY (id), + CONSTRAINT fk1 FOREIGN KEY (f1) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; + +--error 1005 +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + f2 int(11) NOT NULL, + f3 int(11) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE, + CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE +) ENGINE=InnoDB; + +show warnings; + +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + f2 int(11) NOT NULL, + f3 int(11) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT fk2 FOREIGN KEY (f2) REFERENCES t1 (`id`) ON DELETE CASCADE +) ENGINE=InnoDB; + +--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/ +--error 1005 +ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE; + +--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/ +show warnings; + +drop table t2; +drop table t1; diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 15426b18c6d..cf0d4c12274 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -2533,10 +2533,13 @@ dict_foreign_remove_from_cache( if (rbt != NULL && foreign->id != NULL) { const ib_rbt_node_t* node = rbt_lookup(rbt, foreign->id); - dict_foreign_t* val = *(dict_foreign_t**) node->value; - if (val == foreign) { - rbt_delete(rbt, foreign->id); + if (node) { + dict_foreign_t* val = *(dict_foreign_t**) node->value; + + if (val == foreign) { + rbt_delete(rbt, foreign->id); + } } } } @@ -2552,10 +2555,13 @@ dict_foreign_remove_from_cache( if (rbt != NULL && foreign->id != NULL) { const ib_rbt_node_t* node = rbt_lookup(rbt, foreign->id); - dict_foreign_t* val = *(dict_foreign_t**) node->value; + if (node) { - if (val == foreign) { - rbt_delete(rbt, foreign->id); + dict_foreign_t* val = *(dict_foreign_t**) node->value; + + if (val == foreign) { + rbt_delete(rbt, foreign->id); + } } } } diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 0addc419715..a67ca850c3a 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -2666,10 +2666,13 @@ dict_foreign_remove_from_cache( if (rbt != NULL && foreign->id != NULL) { const ib_rbt_node_t* node = rbt_lookup(rbt, foreign->id); - dict_foreign_t* val = *(dict_foreign_t**) node->value; - if (val == foreign) { - rbt_delete(rbt, foreign->id); + if (node) { + dict_foreign_t* val = *(dict_foreign_t**) node->value; + + if (val == foreign) { + rbt_delete(rbt, foreign->id); + } } } } @@ -2685,10 +2688,13 @@ dict_foreign_remove_from_cache( if (rbt != NULL && foreign->id != NULL) { const ib_rbt_node_t* node = rbt_lookup(rbt, foreign->id); - dict_foreign_t* val = *(dict_foreign_t**) node->value; - if (val == foreign) { - rbt_delete(rbt, foreign->id); + if (node) { + dict_foreign_t* val = *(dict_foreign_t**) node->value; + + if (val == foreign) { + rbt_delete(rbt, foreign->id); + } } } } From 07ff90e99b40f86511651415d13a3299a45a01d4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 9 Mar 2015 22:55:54 -0400 Subject: [PATCH 232/294] Reduce gcache size to cut down disk usage --- mysql-test/suite/galera/galera_2nodes.cnf | 4 ++-- mysql-test/suite/wsrep/my.cnf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index e4ae2e0d49c..91f9861a12a 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -16,7 +16,7 @@ wsrep-sync-wait=7 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep_provider_options='base_port=@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' [mysqld.2] @@ -24,7 +24,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.2.#galera_port' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [ENV] diff --git a/mysql-test/suite/wsrep/my.cnf b/mysql-test/suite/wsrep/my.cnf index e6ff7d89751..0b5144b774e 100644 --- a/mysql-test/suite/wsrep/my.cnf +++ b/mysql-test/suite/wsrep/my.cnf @@ -5,5 +5,5 @@ #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep_provider_options='base_port=@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' From 7a6cad5221b19ed5d54eaca83c16655089734a0e Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 11 Mar 2015 12:36:00 -0400 Subject: [PATCH 233/294] Backport fix for MDEV-7673, MDEV-7203 and MDEV-7192 from 10.0-galera --- mysql-test/suite/galera/r/create.result | 5 ++ .../suite/galera/r/rpl_row_annotate.result | 60 +++++++++++++++++++ mysql-test/suite/galera/t/create.test | 8 +++ .../suite/galera/t/rpl_row_annotate.cnf | 6 ++ .../suite/galera/t/rpl_row_annotate.test | 42 +++++++++++++ sql/rpl_rli.cc | 41 +++++++++++++ sql/rpl_rli.h | 3 +- sql/slave.cc | 36 +---------- sql/sql_parse.cc | 8 +++ sql/wsrep_applier.cc | 19 ++++-- sql/wsrep_thd.cc | 10 ++++ 11 files changed, 198 insertions(+), 40 deletions(-) create mode 100644 mysql-test/suite/galera/r/rpl_row_annotate.result create mode 100644 mysql-test/suite/galera/t/rpl_row_annotate.cnf create mode 100644 mysql-test/suite/galera/t/rpl_row_annotate.test diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index 4dffe96d719..2c31ed76d1e 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -20,4 +20,9 @@ i 1 DROP TABLE t1; SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; +# +# MDEV-7673: CREATE TABLE SELECT fails on Galera cluster +# +CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; +DROP TABLE t1; # End of tests diff --git a/mysql-test/suite/galera/r/rpl_row_annotate.result b/mysql-test/suite/galera/r/rpl_row_annotate.result new file mode 100644 index 00000000000..267b48551f2 --- /dev/null +++ b/mysql-test/suite/galera/r/rpl_row_annotate.result @@ -0,0 +1,60 @@ +# On node_2 +RESET MASTER; +# On node_1 +RESET MASTER; +CREATE TABLE t1(i INT)ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +DELETE FROM t1 WHERE i = 1; +# On node_2 +INSERT INTO t1 VALUES(2); +DELETE FROM t1 WHERE i = 2; +# On node_1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM ; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(i INT)ENGINE=INNODB +mysqld-bin.000001 # Query 1 # BEGIN +mysqld-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES(1) +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 1 # BEGIN +mysqld-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE i = 1 +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 2 # BEGIN +mysqld-bin.000001 # Annotate_rows 2 # INSERT INTO t1 VALUES(2) +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 2 # BEGIN +mysqld-bin.000001 # Annotate_rows 2 # DELETE FROM t1 WHERE i = 2 +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +# On node_2 +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM ; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(i INT)ENGINE=INNODB +mysqld-bin.000001 # Query 1 # BEGIN +mysqld-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES(1) +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 1 # BEGIN +mysqld-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE i = 1 +mysqld-bin.000001 # Table_map 1 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 1 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 2 # BEGIN +mysqld-bin.000001 # Annotate_rows 2 # INSERT INTO t1 VALUES(2) +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Write_rows 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +mysqld-bin.000001 # Query 2 # BEGIN +mysqld-bin.000001 # Annotate_rows 2 # DELETE FROM t1 WHERE i = 2 +mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) +mysqld-bin.000001 # Delete_rows 2 # table_id: # flags: STMT_END_F +mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/t/create.test b/mysql-test/suite/galera/t/create.test index b56a841fb65..38c793e33b6 100644 --- a/mysql-test/suite/galera/t/create.test +++ b/mysql-test/suite/galera/t/create.test @@ -22,5 +22,13 @@ SELECT * FROM t1_temp; DROP TABLE t1; SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; +--echo # +--echo # MDEV-7673: CREATE TABLE SELECT fails on Galera cluster +--echo # +CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; + +# Cleanup +DROP TABLE t1; + --echo # End of tests diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.cnf b/mysql-test/suite/galera/t/rpl_row_annotate.cnf new file mode 100644 index 00000000000..1f1d83dfa0b --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_row_annotate.cnf @@ -0,0 +1,6 @@ +!include ../galera_2nodes.cnf + +[mysqld] +log-bin +log-slave-updates +binlog-annotate-row-events=ON diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.test b/mysql-test/suite/galera/t/rpl_row_annotate.test new file mode 100644 index 00000000000..b1cfdb36639 --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_row_annotate.test @@ -0,0 +1,42 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # On node_2 +--connection node_2 +RESET MASTER; + +--echo # On node_1 +--connection node_1 +RESET MASTER; +CREATE TABLE t1(i INT)ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +DELETE FROM t1 WHERE i = 1; + +--echo # On node_2 +--connection node_2 +INSERT INTO t1 VALUES(2); +DELETE FROM t1 WHERE i = 2; + +--echo # On node_1 +--connection node_1 +--source include/binlog_start_pos.inc +let $start_pos= `select @binlog_start_pos`; +--replace_column 2 # 5 # +--replace_result $start_pos +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM $start_pos + +--echo # On node_2 +--connection node_2 +--source include/binlog_start_pos.inc +let $start_pos= `select @binlog_start_pos`; +--replace_column 2 # 5 # +--replace_result $start_pos +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM $start_pos + +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index b01f74408a6..5007b8e1237 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1218,6 +1218,47 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) + +void +delete_or_keep_event_post_apply(Relay_log_info *rli, + Log_event_type typ, Log_event *ev) +{ + switch (typ) { + case FORMAT_DESCRIPTION_EVENT: + /* + Format_description_log_event should not be deleted because it + will be used to read info about the relay log's format; + it will be deleted when the SQL thread does not need it, + i.e. when this thread terminates. + */ + break; + case ANNOTATE_ROWS_EVENT: + /* + Annotate_rows event should not be deleted because after it has + been applied, thd->query points to the string inside this event. + The thd->query will be used to generate new Annotate_rows event + during applying the subsequent Rows events. + */ + rli->set_annotate_event((Annotate_rows_log_event*) ev); + break; + case DELETE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case WRITE_ROWS_EVENT: + /* + After the last Rows event has been applied, the saved Annotate_rows + event (if any) is not needed anymore and can be deleted. + */ + if (((Rows_log_event*)ev)->get_flags(Rows_log_event::STMT_END_F)) + rli->free_annotate_event(); + /* fall through */ + default: + DBUG_PRINT("info", ("Deleting the event after it has been executed")); + if (!rli->is_deferred_event(ev)) + delete ev; + break; + } +} + void Relay_log_info::cleanup_context(THD *thd, bool error) { DBUG_ENTER("Relay_log_info::cleanup_context"); diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index b989283deb4..5f15d2f1fd8 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -580,6 +580,7 @@ private: // Defined in rpl_rli.cc int init_relay_log_info(Relay_log_info* rli, const char* info_fname); - +void delete_or_keep_event_post_apply(Relay_log_info *rli, + Log_event_type typ, Log_event *ev); #endif /* RPL_RLI_H */ diff --git a/sql/slave.cc b/sql/slave.cc index ce11f1bea0e..ab9bd7f337f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2820,41 +2820,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) exec_res= apply_event_and_update_pos(ev, thd, rli); - switch (ev->get_type_code()) { - case FORMAT_DESCRIPTION_EVENT: - /* - Format_description_log_event should not be deleted because it - will be used to read info about the relay log's format; - it will be deleted when the SQL thread does not need it, - i.e. when this thread terminates. - */ - break; - case ANNOTATE_ROWS_EVENT: - /* - Annotate_rows event should not be deleted because after it has - been applied, thd->query points to the string inside this event. - The thd->query will be used to generate new Annotate_rows event - during applying the subsequent Rows events. - */ - rli->set_annotate_event((Annotate_rows_log_event*) ev); - break; - case DELETE_ROWS_EVENT: - case UPDATE_ROWS_EVENT: - case WRITE_ROWS_EVENT: - /* - After the last Rows event has been applied, the saved Annotate_rows - event (if any) is not needed anymore and can be deleted. - */ - if (((Rows_log_event*)ev)->get_flags(Rows_log_event::STMT_END_F)) - rli->free_annotate_event(); - /* fall through */ - default: - DBUG_PRINT("info", ("Deleting the event after it has been executed")); - if (!rli->is_deferred_event(ev)) - delete ev; - break; - } - + delete_or_keep_event_post_apply(rli, ev->get_type_code(), ev); /* update_log_pos failed: this should not happen, so we don't diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a3dd8c886e3..991f960b2c4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2913,6 +2913,14 @@ case SQLCOM_PREPARE: if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->variables.option_bits|= OPTION_KEEP_LOG; +#ifdef WITH_WSREP + if (WSREP(thd) && + (!thd->is_current_stmt_binlog_format_row() || + !(create_info.options & HA_LEX_CREATE_TMP_TABLE))) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, + NULL) +#endif + /* select_create is currently not re-execution friendly and needs to be created for every execution of a PS/SP. diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index cb700448ee5..03f544a4444 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -73,6 +73,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, char *buf= (char *)events_buf; int rcode= 0; int event= 1; + Log_event_type typ; DBUG_ENTER("wsrep_apply_events"); @@ -106,7 +107,10 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, rcode= 1; goto error; } - switch (ev->get_type_code()) { + + typ= ev->get_type_code(); + + switch (typ) { case WRITE_ROWS_EVENT: case UPDATE_ROWS_EVENT: case DELETE_ROWS_EVENT: @@ -117,14 +121,20 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, break; } - thd->server_id = ev->server_id; // use the original server id for logging - thd->set_time(); // time the query + /* Use the original server id for logging. */ + thd->set_server_id(ev->server_id); + thd->set_time(); // time the query wsrep_xid_init(&thd->transaction.xid_state.xid, &thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); thd->lex->current_select= 0; if (!ev->when) ev->when = time(NULL); + + thd->variables.option_bits= + (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_rli); DBUG_PRINT("info", ("exec_event result: %d", exec_res)); @@ -172,7 +182,8 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, WSREP_ERROR("Error in %s event: commit of row events failed: %lld", ev->get_type_str(), (long long)wsrep_thd_trx_seqno(thd)); } - delete ev; + + delete_or_keep_event_post_apply(thd->wsrep_rli, typ, ev); } error: diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 5d5917ad3fc..53684935f99 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -94,6 +94,12 @@ static Relay_log_info* wsrep_relay_log_init(const char* log_fname) } rli->sql_thd= current_thd; + + if ((rli->deferred_events_collecting= rpl_filter->is_on())) + { + rli->deferred_events= new Deferred_log_events(rli); + } + return rli; } @@ -132,6 +138,10 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) thd->net.vio = shadow->vio; thd->variables.tx_isolation = shadow->tx_isolation; thd->reset_db(shadow->db, shadow->db_length); + + thd->wsrep_rli->cleanup_after_session(); + delete thd->wsrep_rli; + thd->wsrep_rli= NULL; } void wsrep_replay_transaction(THD *thd) From 6a204546ef91aa90dedb6b47353bbb568f0531b0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 24 Mar 2015 16:41:04 -0400 Subject: [PATCH 234/294] MDEV-7798: mysql.server init script can't stop mysqld when WSREP is turned off wsrep threads should be always be checked for existence & stopped on server shutdown. --- mysql-test/suite/wsrep/r/mdev_7798.result | 13 +++++++++++++ mysql-test/suite/wsrep/t/mdev_7798.opt | 1 + mysql-test/suite/wsrep/t/mdev_7798.test | 17 +++++++++++++++++ sql/mysqld.cc | 3 ++- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/wsrep/r/mdev_7798.result create mode 100644 mysql-test/suite/wsrep/t/mdev_7798.opt create mode 100644 mysql-test/suite/wsrep/t/mdev_7798.test diff --git a/mysql-test/suite/wsrep/r/mdev_7798.result b/mysql-test/suite/wsrep/r/mdev_7798.result new file mode 100644 index 00000000000..83a02f3a606 --- /dev/null +++ b/mysql-test/suite/wsrep/r/mdev_7798.result @@ -0,0 +1,13 @@ +# +# MDEV-7798: mysql.server init script can't stop mysqld when WSREP is +# turned off +# +SELECT @@GLOBAL.WSREP_ON; +@@GLOBAL.WSREP_ON +1 +SET GLOBAL WSREP_ON= 0; +Restart the node. +SELECT @@GLOBAL.WSREP_ON; +@@GLOBAL.WSREP_ON +1 +# End of test. diff --git a/mysql-test/suite/wsrep/t/mdev_7798.opt b/mysql-test/suite/wsrep/t/mdev_7798.opt new file mode 100644 index 00000000000..459a9702707 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_7798.opt @@ -0,0 +1 @@ +--wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --wsrep_causal_reads=ON diff --git a/mysql-test/suite/wsrep/t/mdev_7798.test b/mysql-test/suite/wsrep/t/mdev_7798.test new file mode 100644 index 00000000000..9dfff0959bc --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_7798.test @@ -0,0 +1,17 @@ +--source include/have_wsrep_provider.inc +--source include/have_binlog_format_row.inc + +--echo # +--echo # MDEV-7798: mysql.server init script can't stop mysqld when WSREP is +--echo # turned off +--echo # + +SELECT @@GLOBAL.WSREP_ON; +SET GLOBAL WSREP_ON= 0; + +--echo Restart the node. +--source include/restart_mysqld.inc + +SELECT @@GLOBAL.WSREP_ON; + +--echo # End of test. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 857317a927c..6b960c6db27 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1753,7 +1753,8 @@ static void __cdecl kill_server(int sig_ptr) } #endif #ifdef WITH_WSREP - if (WSREP_ON) wsrep_stop_replication(NULL); + /* Stop wsrep threads in case they are running. */ + wsrep_stop_replication(NULL); #endif close_connections(); From d7445ea6dfbd3be390792c636f755d3bb40d5fbf Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 27 Mar 2015 20:35:37 -0400 Subject: [PATCH 235/294] MDEV-7194: galera fails to replicate DDL queries when using binlog_checksum Restore fix for MDEV-4328 (revno: 3391) that got accidentally overwritten while merging : http://bazaar.launchpad.net/~codership/codership-mysql/5.5-23/revision/3900 Added a test case. --- .../suite/galera/r/binlog_checksum.result | 36 +++++++++++++++++++ .../suite/galera/t/binlog_checksum.test | 36 +++++++++++++++++++ sql/sql_class.cc | 1 + sql/sql_class.h | 1 + sql/wsrep_applier.cc | 28 +++++++++++++-- sql/wsrep_mysqld.cc | 10 +++--- 6 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/galera/r/binlog_checksum.result create mode 100644 mysql-test/suite/galera/t/binlog_checksum.test diff --git a/mysql-test/suite/galera/r/binlog_checksum.result b/mysql-test/suite/galera/r/binlog_checksum.result new file mode 100644 index 00000000000..5c1981fc17f --- /dev/null +++ b/mysql-test/suite/galera/r/binlog_checksum.result @@ -0,0 +1,36 @@ +# On node_1 +SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM; +SET @@GLOBAL.BINLOG_CHECKSUM=CRC32; +# On node_2 +SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM; +SET @@GLOBAL.BINLOG_CHECKSUM=CRC32; +USE test; +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +SELECT * FROM t1; +c1 +1 +2 +3 +4 +5 +SELECT * FROM test.t1; +c1 +1 +2 +3 +4 +5 + +# On node_2 +SELECT * FROM test.t1; +c1 +1 +2 +3 +4 +5 +DROP TABLE t1; +SET @@GLOBAL.BINLOG_CHECKSUM = @binlog_checksum_saved; +SET @@GLOBAL.BINLOG_CHECKSUM = @binlog_checksum_saved; +# End of test diff --git a/mysql-test/suite/galera/t/binlog_checksum.test b/mysql-test/suite/galera/t/binlog_checksum.test new file mode 100644 index 00000000000..5aab68a7746 --- /dev/null +++ b/mysql-test/suite/galera/t/binlog_checksum.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # On node_1 +--connection node_1 +SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM; +SET @@GLOBAL.BINLOG_CHECKSUM=CRC32; + +--echo # On node_2 +--connection node_2 +SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM; +SET @@GLOBAL.BINLOG_CHECKSUM=CRC32; + +USE test; +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +SELECT * FROM t1; +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + +--let $galera_diff_statement = SELECT * FROM t1 +--source include/galera_diff.inc + +# Cleanup +DROP TABLE t1; +--connection node_1 +SET @@GLOBAL.BINLOG_CHECKSUM = @binlog_checksum_saved; +--connection node_2 +SET @@GLOBAL.BINLOG_CHECKSUM = @binlog_checksum_saved; + +--source include/galera_end.inc +--echo # End of test diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9fa508cdc97..d40ca89a5ab 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1000,6 +1000,7 @@ THD::THD() wsrep_applier(is_applier), wsrep_applier_closing(FALSE), wsrep_client_thread(0), + wsrep_apply_format(0), wsrep_apply_toi(false), #endif m_parser_state(NULL), diff --git a/sql/sql_class.h b/sql/sql_class.h index 477be6e8004..3418e16f275 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2389,6 +2389,7 @@ public: const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; + void* wsrep_apply_format; bool wsrep_apply_toi; /* applier processing in TOI */ #endif /* WITH_WSREP */ /** diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 03f544a4444..3736431cd30 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -17,7 +17,6 @@ #include "wsrep_binlog.h" // wsrep_dump_rbr_buf() #include "log_event.h" // EVENT_LEN_OFFSET, etc. - #include "wsrep_applier.h" /* @@ -64,7 +63,25 @@ err: #include "rpl_rli.h" // class Relay_log_info; #include "sql_base.h" // close_temporary_table() -extern const Format_description_log_event *wsrep_format_desc; +static inline 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; + } + thd->wsrep_apply_format= ev; +} + +static inline Format_description_log_event* +wsrep_get_apply_format(THD* thd) +{ + if (thd->wsrep_apply_format) + { + return (Format_description_log_event*) thd->wsrep_apply_format; + } + return thd->wsrep_rli->relay_log.description_event_for_exec; +} static wsrep_cb_status_t wsrep_apply_events(THD* thd, const void* events_buf, @@ -98,7 +115,8 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, { int exec_res; int error = 0; - Log_event* ev= wsrep_read_log_event(&buf, &buf_len, wsrep_format_desc); + Log_event* ev= wsrep_read_log_event(&buf, &buf_len, + wsrep_get_apply_format(thd)); if (!ev) { @@ -111,6 +129,9 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, typ= ev->get_type_code(); switch (typ) { + case FORMAT_DESCRIPTION_EVENT: + wsrep_set_apply_format(thd, (Format_description_log_event*)ev); + continue; case WRITE_ROWS_EVENT: case UPDATE_ROWS_EVENT: case DELETE_ROWS_EVENT: @@ -339,6 +360,7 @@ wsrep_cb_status_t wsrep_commit_cb(void* const ctx, else rcode = wsrep_rollback(thd, meta->gtid.seqno); + wsrep_set_apply_format(thd, NULL); thd->mdl_context.release_transactional_locks(); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index d93c5a3a02d..a48e28b73f6 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -28,7 +28,6 @@ #include "log_event.h" #include -Format_description_log_event *wsrep_format_desc = NULL; wsrep_t *wsrep = NULL; my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface @@ -498,7 +497,6 @@ int wsrep_init() wsrep_ready_set(FALSE); assert(wsrep_provider); - wsrep_format_desc= new Format_description_log_event(4); wsrep_init_position(); if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) @@ -718,8 +716,6 @@ void wsrep_deinit(bool free_options) provider_version[0]= '\0'; provider_vendor[0]= '\0'; - delete wsrep_format_desc; - wsrep_format_desc= NULL; wsrep_inited= 0; if (free_options) @@ -1133,6 +1129,12 @@ int wsrep_to_buf_helper( return 1; int ret(0); + + Format_description_log_event *tmp_fd= new Format_description_log_event(4); + tmp_fd->checksum_alg= binlog_checksum_options; + tmp_fd->write(&tmp_io_cache); + delete tmp_fd; + /* if there is prepare query, add event for it */ if (thd->wsrep_TOI_pre_query) { From 0095697784a12cbb269238b354ac6f31800418fb Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 16 Apr 2015 16:29:02 -0400 Subject: [PATCH 236/294] MDEV-7996 : CURRENT_USER definer does not replicate for triggers THD's lex->definer initially holds "*current_user" for CURRENT_USER(). As a result when wsrep tries to create the trigger query, it incorrectly uses "*current_user". Fixed by calling get_current_user() to get the real current user. Merged galera_create_trigger.test from github.com/codership/mysql-wsrep. --- .../galera/r/galera_create_trigger.result | 42 ++++++++++++++++++ .../suite/galera/t/galera_create_trigger.test | 43 +++++++++++++++++++ sql/sql_trigger.cc | 8 +++- 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_create_trigger.result create mode 100644 mysql-test/suite/galera/t/galera_create_trigger.test diff --git a/mysql-test/suite/galera/r/galera_create_trigger.result b/mysql-test/suite/galera/r/galera_create_trigger.result new file mode 100644 index 00000000000..7e656081871 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_trigger.result @@ -0,0 +1,42 @@ +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; +CREATE TABLE definer_default (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB; +CREATE USER 'user1'; +CREATE DEFINER=root@localhost TRIGGER definer_root BEFORE INSERT ON definer_root FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE DEFINER=user1 TRIGGER definer_user BEFORE INSERT ON definer_user FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE DEFINER=current_user TRIGGER definer_current_user BEFORE INSERT ON definer_current_user FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE TRIGGER definer_default BEFORE INSERT ON definer_default FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +INSERT INTO definer_root (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_root'; +DEFINER = 'root@localhost' +1 +SELECT trigger_user = 'root@localhost' FROM definer_root; +trigger_user = 'root@localhost' +1 +INSERT INTO definer_user (f1) VALUES (1); +SELECT DEFINER = 'user1@%' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_user'; +DEFINER = 'user1@%' +1 +SELECT trigger_user = 'user1@%' FROM definer_user; +trigger_user = 'user1@%' +1 +INSERT INTO definer_current_user (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_current_user'; +DEFINER = 'root@localhost' +1 +SELECT trigger_user = 'root@localhost' FROM definer_current_user; +trigger_user = 'root@localhost' +1 +INSERT INTO definer_default (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_default'; +DEFINER = 'root@localhost' +1 +SELECT trigger_user = 'root@localhost' FROM definer_default; +trigger_user = 'root@localhost' +1 +DROP TABLE definer_current_user; +DROP TABLE definer_user; +DROP TABLE definer_root; +DROP TABLE definer_default; +DROP USER 'user1'; diff --git a/mysql-test/suite/galera/t/galera_create_trigger.test b/mysql-test/suite/galera/t/galera_create_trigger.test new file mode 100644 index 00000000000..6708e30bf0f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_trigger.test @@ -0,0 +1,43 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test CREATE TRIGGER, especially with different DEFINER +# + +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; +CREATE TABLE definer_default (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB; + +CREATE USER 'user1'; +CREATE DEFINER=root@localhost TRIGGER definer_root BEFORE INSERT ON definer_root FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE DEFINER=user1 TRIGGER definer_user BEFORE INSERT ON definer_user FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE DEFINER=current_user TRIGGER definer_current_user BEFORE INSERT ON definer_current_user FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); +CREATE TRIGGER definer_default BEFORE INSERT ON definer_default FOR EACH ROW SET NEW.trigger_user = CURRENT_USER(); + +--connection node_2 +INSERT INTO definer_root (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_root'; +SELECT trigger_user = 'root@localhost' FROM definer_root; + +INSERT INTO definer_user (f1) VALUES (1); +SELECT DEFINER = 'user1@%' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_user'; +SELECT trigger_user = 'user1@%' FROM definer_user; + +INSERT INTO definer_current_user (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_current_user'; +SELECT trigger_user = 'root@localhost' FROM definer_current_user; + +INSERT INTO definer_default (f1) VALUES (1); +SELECT DEFINER = 'root@localhost' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'definer_default'; +SELECT trigger_user = 'root@localhost' FROM definer_default; + +--connection node_1 +DROP TABLE definer_current_user; +DROP TABLE definer_user; +DROP TABLE definer_root; +DROP TABLE definer_default; + +DROP USER 'user1'; + diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index cf5b4a39b1f..a2b5f9a68c9 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2464,9 +2464,13 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) if (lex->definer) { /* SUID trigger. */ + LEX_USER *d= get_current_user(thd, lex->definer); - definer_user= lex->definer->user; - definer_host= lex->definer->host; + if (!d) + return 1; + + definer_user= d->user; + definer_host= d->host; } else { From 581b49dd3d3e2e253812bb24fa881148675320b4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 22 Apr 2015 18:13:30 -0400 Subject: [PATCH 237/294] MDEV-7995 : DMLs not getting replicated with log-bin=OFF & binlog-format != ROW This bug is a side-effect of fix for MDEV-6924, where we completely stopped a statement-based event from getting into the binlog cache when binary logging is not enabled (and thus, wsrep_emulate_binlog mode = 1). As a result, the SBR events were not replicated. Fixed by allowing the SBR events to be written into the binlog cache. Note: Only DMLs were affected as DDLs are replicated via TOI. Merged galera_create_trigger.test from github.com/codership/mysql-wsrep. --- mysql-test/suite/galera/r/galera_sbr.result | 14 +++++++++++ mysql-test/suite/galera/t/galera_sbr.test | 27 +++++++++++++++++++++ sql/log.cc | 18 +++++++++++++- sql/sql_class.cc | 10 -------- 4 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_sbr.result create mode 100644 mysql-test/suite/galera/t/galera_sbr.test diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result new file mode 100644 index 00000000000..0bf6cc7c9d3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sbr.result @@ -0,0 +1,14 @@ +SET SESSION binlog_format = 'STATEMENT'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION binlog_format = 'MIXED'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; +SET GLOBAL binlog_format = 'ROW'; diff --git a/mysql-test/suite/galera/t/galera_sbr.test b/mysql-test/suite/galera/t/galera_sbr.test new file mode 100644 index 00000000000..33f45c6b532 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sbr.test @@ -0,0 +1,27 @@ +# +# Test behavior if the user attempts to use statement-based replication +# +# SBR is not currently supported but we expect that no crashes or binlog-related assertions will be triggered. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--connection node_1 +#SET GLOBAL binlog_format = 'STATEMENT'; +SET SESSION binlog_format = 'STATEMENT'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION binlog_format = 'MIXED'; + +INSERT INTO t1 VALUES (2); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; + +--connection node_1 +SET GLOBAL binlog_format = 'ROW'; diff --git a/sql/log.cc b/sql/log.cc index d4403f4dfa4..8b2eb98c2e2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5167,7 +5167,19 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) binlog_cache_data *cache_data= 0; bool is_trans_cache= FALSE; bool using_trans= event_info->use_trans_cache(); - bool direct= event_info->use_direct_logging(); + bool direct; + +#ifdef WITH_WSREP + /* + When binary logging is not enabled (--log-bin=0), wsrep-patch partially + enables it without opening the binlog file (MSQL_BIN_LOG::open(). + So, avoid writing directly to binlog file. + */ + if (wsrep_emulate_bin_log) + direct= false; + else +#endif /* WITH_WSREP */ + direct= event_info->use_direct_logging(); if (thd->binlog_evt_union.do_union) { @@ -5948,6 +5960,10 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_to_binlog"); #ifdef WITH_WSREP + /* + Control should not be allowed beyond this point in wsrep_emulate_bin_log + mode. + */ if (wsrep_emulate_bin_log) DBUG_RETURN(0); #endif /* WITH_WSREP */ entry.thd= thd; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d40ca89a5ab..a55992bd0cf 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5885,16 +5885,6 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, The MYSQL_LOG::write() function will set the STMT_END_F flag and flush the pending rows event if necessary. */ -#ifdef WITH_WSREP - /* - Even though wsrep only supports ROW binary log format, a user can set - binlog format to STATEMENT (wsrep_forced_binlog_format). In which case - the control might reach here even when binary logging (--log-bin) is - not enabled. This is possible because wsrep patch partially enables - binary logging by setting wsrep_emulate_binlog. - */ - if (mysql_bin_log.is_open()) -#endif /* WITH_WSREP */ { Query_log_event qinfo(this, query_arg, query_len, is_trans, direct, suppress_use, errcode); From 44b44dd1d73c5da4e3b6ed7935c79ca88b61fdc8 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 22 Apr 2015 18:30:27 -0400 Subject: [PATCH 238/294] Comments for wsrep_exec_mode's. --- sql/wsrep_mysqld.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 14edf26c44f..4bd2489210a 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -28,10 +28,17 @@ class set_var; class THD; enum wsrep_exec_mode { - LOCAL_STATE, - REPL_RECV, - TOTAL_ORDER, - LOCAL_COMMIT + /* 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 { From 8aa84821b48c501afdfb46dbe5600dbe5b4bb5d0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 28 Apr 2015 18:59:11 -0400 Subject: [PATCH 239/294] MDEV-8057: Galera conflicts with InnoDB buffer pool dump Avoid creating innodb buffer pool dump/load thread if mysqld is started with wsrep recovery mode (--wsrep-recover). (Merged fix for lp:1305955 from lp:percona-xtradb-cluster) --- storage/innobase/srv/srv0start.cc | 17 ++++++++++++++++- storage/xtradb/srv/srv0start.cc | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index c56f90ff0a8..2038635fe86 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -168,6 +168,10 @@ UNIV_INTERN mysql_pfs_key_t srv_master_thread_key; UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key; #endif /* UNIV_PFS_THREAD */ +#ifdef WITH_WSREP +extern my_bool wsrep_recovery; +#endif /* WITH_WSREP */ + /*********************************************************************//** Convert a numeric string that optionally ends in G or M or K, to a number containing megabytes. @@ -2879,10 +2883,21 @@ files_checked: } if (!srv_read_only_mode) { +#ifdef WITH_WSREP + /* Create the dump/load thread only when not running with + --wsrep-recover */ + if (!wsrep_recovery) { +#endif /* WITH_WSREP */ /* Create the buffer pool dump/load thread */ buf_dump_thread_handle = os_thread_create(buf_dump_thread, NULL, NULL); buf_dump_thread_started = true; - +#ifdef WITH_WSREP + } else { + ib_logf(IB_LOG_LEVEL_WARN, + "Skipping buffer pool dump/restore during wsrep " + "recovery."); + } +#endif /* WITH_WSREP */ /* Create the dict stats gathering thread */ dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL); dict_stats_thread_started = true; diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index a53e22fa3f1..c10937cd120 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -186,6 +186,10 @@ UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key; UNIV_INTERN mysql_pfs_key_t srv_log_tracking_thread_key; #endif /* UNIV_PFS_THREAD */ +#ifdef WITH_WSREP +extern my_bool wsrep_recovery; +#endif /* WITH_WSREP */ + /*********************************************************************//** Convert a numeric string that optionally ends in G or M or K, to a number containing megabytes. @@ -2980,10 +2984,21 @@ files_checked: } if (!srv_read_only_mode) { +#ifdef WITH_WSREP + /* Create the dump/load thread only when not running with + --wsrep-recover */ + if (!wsrep_recovery) { +#endif /* WITH_WSREP */ /* Create the buffer pool dump/load thread */ buf_dump_thread_handle = os_thread_create(buf_dump_thread, NULL, NULL); buf_dump_thread_started = true; - +#ifdef WITH_WSREP + } else { + ib_logf(IB_LOG_LEVEL_WARN, + "Skipping buffer pool dump/restore during wsrep " + "recovery."); + } +#endif /* WITH_WSREP */ /* Create the dict stats gathering thread */ dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL); dict_stats_thread_started = true; From 51744b3f80a025a8c20c3aeb80741375a115d649 Mon Sep 17 00:00:00 2001 From: dirtysalt Date: Fri, 31 Oct 2014 15:55:18 +0800 Subject: [PATCH 240/294] Refs #8: [5.5] preserve gvwstate.dat for pc recovery feature --- scripts/wsrep_sst_xtrabackup-v2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 90892f9574f..d80af7454fb 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -282,7 +282,7 @@ read_cnf() progress=$(parse_cnf sst progress "") rebuild=$(parse_cnf sst rebuild 0) ttime=$(parse_cnf sst time 0) - cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*gvwstate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') incremental=$(parse_cnf sst incremental 0) ealgo=$(parse_cnf xtrabackup encrypt "") ekey=$(parse_cnf xtrabackup encrypt-key "") From 68fe3a39ac7f8c93b4c710b56403b9792b822c23 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Sun, 16 Nov 2014 16:26:36 +0200 Subject: [PATCH 241/294] refs #7 - handling lock queue granting in BF-BF conflict situation --- storage/innobase/lock/lock0lock.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 98cb239befc..b245e85ad1c 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -982,14 +982,15 @@ lock_rec_has_to_wait( } #ifdef WITH_WSREP - /* if BF thread is locking and has conflict with another BF + /* if BF thread has conflict with another BF thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); + fprintf(stderr, + "BF-BF lock conflict, locking: %d \n", + for_locking); lock_rec_print(stderr, lock2); } @@ -998,10 +999,17 @@ lock_rec_has_to_wait( (type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict\n"); - lock_rec_print(stderr, lock2); - abort(); + if (for_locking) { + /* exclusive lock conflicts are not + accepted */ + fprintf(stderr, + "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else if (wsrep_debug) { + fprintf(stderr, + "BF-BF X lock conflict\n"); + } } else { /* if lock2->index->n_uniq <= lock2->index->n_user_defined_cols From 2a6e1230e3a709ac91ac299ec81a18fb37538e4b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 30 Mar 2015 17:58:41 -0400 Subject: [PATCH 242/294] refs #7 - handling lock queue granting in BF-BF conflict situation Merge fix to xtradb. --- storage/xtradb/lock/lock0lock.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index d9a5768d94c..1ac39a6fb26 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -983,14 +983,15 @@ lock_rec_has_to_wait( } #ifdef WITH_WSREP - /* if BF thread is locking and has conflict with another BF + /* if BF thread has conflict with another BF thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); + fprintf(stderr, + "BF-BF lock conflict, locking: %d \n", + for_locking); lock_rec_print(stderr, lock2); } @@ -999,10 +1000,17 @@ lock_rec_has_to_wait( (type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict\n"); - lock_rec_print(stderr, lock2); - abort(); + if (for_locking) { + /* exclusive lock conflicts are not + accepted */ + fprintf(stderr, + "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else if (wsrep_debug) { + fprintf(stderr, + "BF-BF X lock conflict\n"); + } } else { /* if lock2->index->n_uniq <= lock2->index->n_user_defined_cols From 822c00536d461d56e81dd9c519ec5ec1cde9536a Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Tue, 9 Dec 2014 22:13:14 +0200 Subject: [PATCH 243/294] Going more MTR-friendly - for SST prefer to use mysql client, mysqldump and my_print_defaults from the local build tree. --- scripts/wsrep_sst_common.sh | 28 +++++++++++++++++++++++++++- scripts/wsrep_sst_mysqldump.sh | 8 ++++---- scripts/wsrep_sst_rsync.sh | 3 +-- scripts/wsrep_sst_xtrabackup-v2.sh | 10 +++++----- scripts/wsrep_sst_xtrabackup.sh | 10 +++++----- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index d9aa24169ce..2546074f7bd 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -88,8 +88,34 @@ shift done readonly WSREP_SST_OPT_BYPASS +# try to use my_print_defaults, mysql and mysqldump that come with the sources +# (for MTR suite) +SCRIPTS_DIR="$(cd $(dirname "$0"); pwd -P)" +EXTRA_DIR="$SCRIPTS_DIR/../extra" +CLIENT_DIR="$SCRIPTS_DIR/../client" + +if [ -x "$CLIENT_DIR/mysql" ]; then + MYSQL_CLIENT="$CLIENT_DIR/mysql" +else + MYSQL_CLIENT=$(which mysql) +fi + +if [ -x "$CLIENT_DIR/mysqldump" ]; then + MYSQLDUMP="$CLIENT_DIR/mysqldump" +else + MYSQLDUMP=$(which mysqldump) +fi + +if [ -x "$SCRIPTS_DIR/my_print_defaults" ]; then + MY_PRINT_DEFAULTS="$SCRIPTS_DIR/my_print_defaults" +elif [ -x "$EXTRA_DIR/my_print_defaults" ]; then + MY_PRINT_DEFAULTS="$EXTRA_DIR/my_print_defaults" +else + MY_PRINT_DEFAULTS=$(which my_print_defaults) +fi + # For Bug:1200727 -if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then +if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) fi diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 3db1d73bb9c..53371765f66 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -54,9 +54,9 @@ then fi # Check client version -if ! mysql --version | grep 'Distrib 5.5' >/dev/null +if ! $MYSQL_CLIENT --version | grep 'Distrib 5.5' >/dev/null then - mysql --version >&2 + $MYSQL_CLIENT --version >&2 wsrep_log_error "this operation requires MySQL client version 5.5.x" exit $EINVAL fi @@ -72,7 +72,7 @@ if test -n "$WSREP_SST_OPT_PSWD"; then AUTH="$AUTH -p$WSREP_SST_OPT_PSWD"; fi STOP_WSREP="SET wsrep_on=OFF;" # NOTE: we don't use --routines here because we're dumping mysql.proc table -MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ +MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \ --add-drop-database --add-drop-table --skip-add-locks --create-options \ --disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ --skip-comments --flush-privileges --all-databases" @@ -97,7 +97,7 @@ DROP PREPARE stmt;" SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" -MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ +MYSQL="$MYSQL_CLIENT $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ "--disable-reconnect --connect_timeout=10" # need to disable logging when loading the dump diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 464b2b1ef3e..494ed4b5c02 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -83,8 +83,7 @@ WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf if [ -z "$WSREP_LOG_DIR" ]; then - SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)" - WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \ + WSREP_LOG_DIR=$($MY_PRINT_DEFAULTS --defaults-file \ "$WSREP_SST_OPT_CONF" mysqld server mysqld-5.5 mariadb mariadb-5.5 \ | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ | cut -b 29- ) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index d80af7454fb..1a191a6ad6b 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -117,7 +117,7 @@ get_keys() fi if [[ $encrypt -eq 0 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " fi return @@ -230,7 +230,7 @@ parse_cnf() { local group=$1 local var=$2 - reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -241,7 +241,7 @@ get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. payload=$(( payload*1/2 )) @@ -443,8 +443,8 @@ check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index dd4060e6961..044f9995580 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -100,7 +100,7 @@ get_keys() fi if [[ $encrypt -eq 0 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " fi return @@ -195,7 +195,7 @@ parse_cnf() { local group=$1 local var=$2 - reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -206,7 +206,7 @@ get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. payload=$(( payload*1/2 )) @@ -385,8 +385,8 @@ check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. From c72ed05cdc215c14e41d0466a3d50d2c1a3a2033 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Wed, 10 Dec 2014 01:45:50 +0200 Subject: [PATCH 244/294] This commit * improves MySQL client version check making it no less than required as opposed to exactly as required. * adds event table copying to ensure same results as with rsync SST. --- scripts/wsrep_sst_mysqldump.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 53371765f66..e21e1cd01bc 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -54,7 +54,8 @@ then fi # Check client version -if ! $MYSQL_CLIENT --version | grep 'Distrib 5.5' >/dev/null +CLIENT_MINOR=$(mysql --version | cut -d ' ' -f 6 | cut -d '.' -f 2) +if [ $CLIENT_MINOR -lt "5" ] then $MYSQL_CLIENT --version >&2 wsrep_log_error "this operation requires MySQL client version 5.5.x" @@ -75,7 +76,7 @@ STOP_WSREP="SET wsrep_on=OFF;" MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \ --add-drop-database --add-drop-table --skip-add-locks --create-options \ --disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ ---skip-comments --flush-privileges --all-databases" +--skip-comments --flush-privileges --all-databases --events" # mysqldump cannot restore CSV tables, fix this issue CSV_TABLES_FIX=" From b02d73656000107250b288c77668ce671fdacb10 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Wed, 10 Dec 2014 23:29:28 +0200 Subject: [PATCH 245/294] Refs #25 - made sure signals that may be set to ignored in mysqld were set to default in the child process. --- sql/wsrep_utils.cc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 099e6403dd6..ee87b9615a8 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -150,7 +150,35 @@ process::process (const char* cmd, const char* type) goto cleanup_pipe; } - err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + /* make sure that no signlas are masked in child process */ + sigset_t sigmask_empty; sigemptyset(&sigmask_empty); + err_ = posix_spawnattr_setsigmask(&attr, &sigmask_empty); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setsigmask() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + /* make sure the following signals are not ignored in child process */ + sigset_t default_signals; sigemptyset(&default_signals); + sigaddset(&default_signals, SIGHUP); + sigaddset(&default_signals, SIGINT); + sigaddset(&default_signals, SIGQUIT); + sigaddset(&default_signals, SIGPIPE); + sigaddset(&default_signals, SIGTERM); + sigaddset(&default_signals, SIGCHLD); + err_ = posix_spawnattr_setsigdefault(&attr, &default_signals); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setsigdefault() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_SETSIGMASK | + /* start a new process group */ POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_USEVFORK); if (err_) { From f6b1e0fe0a33c724839abab74ae07bbbd41a23e6 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 5 Feb 2015 14:38:03 +0200 Subject: [PATCH 246/294] refs #55 fixed debug build compilation errors --- storage/innobase/lock/lock0lock.c | 2 +- storage/xtradb/lock/lock0lock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index b245e85ad1c..07e12cd43f6 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -989,7 +989,7 @@ lock_rec_has_to_wait( if (wsrep_debug) { fprintf(stderr, - "BF-BF lock conflict, locking: %d \n", + "BF-BF lock conflict, locking: %lu \n", for_locking); lock_rec_print(stderr, lock2); } diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 1ac39a6fb26..e36829daed6 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -990,7 +990,7 @@ lock_rec_has_to_wait( if (wsrep_debug) { fprintf(stderr, - "BF-BF lock conflict, locking: %d \n", + "BF-BF lock conflict, locking: %lu \n", for_locking); lock_rec_print(stderr, lock2); } From 70d6236afd55b74211fee507c5af6b2b631c3f26 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Tue, 10 Feb 2015 00:47:02 +0200 Subject: [PATCH 247/294] refs codership/mysql-wsrep#55 - To avoid compiler warming: sql/sql_parse.cc: In function 'bool do_command(THD*)': sql/sql_parse.cc:758:20: error: 'packet_length' may be used uninitialized in this function [-Werror=maybe-uninitialized] if ((WSREP(thd) && packet_length == packet_error) || [ --- sql/sql_parse.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 991f960b2c4..c931a02661e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -693,7 +693,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"); From f3efc63283a232bfe3dc74d45a7ca4a3fcc683c8 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Tue, 10 Feb 2015 18:27:21 +0200 Subject: [PATCH 248/294] refs codership/mysql-wsrep#60 explicit braces around empty body --- sql/wsrep_var.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index ba92c6a4773..66b33e7697c 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -570,7 +570,9 @@ static void export_wsrep_status_to_mysql(THD* thd) for (wsrep_status_len = 0; thd->wsrep_status_vars[wsrep_status_len].name != NULL; - wsrep_status_len++); + wsrep_status_len++) { + /* */ + } #if DYNAMIC if (wsrep_status_len != mysql_status_len) { From 42f99d00eee0023184c6d985fa6f4e7a9717c3d8 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 18 Mar 2015 21:17:31 +0200 Subject: [PATCH 249/294] codership/mysql-wsrep#67 - total order isolation for FLUSH The following FLUSH commands are now executed under total order isolation: * FLUSH DES_KEY_FILE * FLUSH HOSTS * FLUSH PRIVILEGES * FLUSH QUERY CACHE * FLUSH STATUS * FLUSH USER_RESOURCES This patch was backported from mysql-wsrep/5.6 commit cdea608d9a27701d76d0deec49976aa0a08b1a56 --- sql/sql_parse.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c931a02661e..1b965b080e0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4119,6 +4119,21 @@ end_with_restore_list: break; } +#ifdef WITH_WSREP + if (lex->type & ( + REFRESH_GRANT | + REFRESH_HOSTS | + REFRESH_DES_KEY_FILE | +#ifdef HAVE_QUERY_CACHE + REFRESH_QUERY_CACHE_FREE | +#endif /* HAVE_QUERY_CACHE */ + REFRESH_STATUS | + REFRESH_USER_RESOURCES)) + { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + } +#endif /* WITH_WSREP*/ + /* reload_acl_and_cache() will tell us if we are allowed to write to the binlog or not. From 0f405f216efcf7ca000cbf032a6a0a19b3de03cd Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 29 Oct 2014 17:08:51 +0200 Subject: [PATCH 250/294] refs #6 fixed compilation errors with -DWITH_DEBUG=1, removed unwanted files --- sql/mysqld.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index eb5c233af41..0324625f350 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1468,7 +1468,9 @@ bool mysqld_embedded=0; bool mysqld_embedded=1; #endif +#ifndef EMBEDDED_LIBRARY static my_bool plugins_are_initialized= FALSE; +#endif #ifndef DBUG_OFF static const char* default_dbug_option; From 9fdae3eb60746a07ade11236e513d393969e7afd Mon Sep 17 00:00:00 2001 From: dirtysalt Date: Fri, 31 Oct 2014 15:55:18 +0800 Subject: [PATCH 251/294] Refs #8: preserve gvwstate.dat for pc recovery feature --- scripts/wsrep_sst_xtrabackup-v2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 779dc828a8e..beab9cf6f43 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -282,7 +282,7 @@ read_cnf() progress=$(parse_cnf sst progress "") rebuild=$(parse_cnf sst rebuild 0) ttime=$(parse_cnf sst time 0) - cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*grastate\.dat$\|.*gvwstate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') incremental=$(parse_cnf sst incremental 0) ealgo=$(parse_cnf xtrabackup encrypt "") ekey=$(parse_cnf xtrabackup encrypt-key "") From 21bc3e3fdab516b86fbc1c33966d068471460ce2 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Wed, 12 Nov 2014 14:59:04 +0200 Subject: [PATCH 252/294] refs #2 - added binlog stmt cache reset after commit. This is needed for non-InnoDB statements --- sql/log.cc | 23 ++++++++++++++++++++++- sql/wsrep_hton.cc | 23 +++++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index b6b5ea67f20..8ea84ac189d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1712,15 +1712,36 @@ int binlog_init(void *p) return 0; } +#ifdef WITH_WSREP +#include "wsrep_binlog.h" +#endif /* WITH_WSREP */ static int binlog_close_connection(handlerton *hton, THD *thd) { + DBUG_ENTER("binlog_close_connection"); binlog_cache_mngr *const cache_mngr= (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); + uchar *buf; + size_t len=0; + wsrep_write_cache_buf(cache, &buf, &len); + WSREP_WARN("binlog trx cache not empty (%lu bytes) @ connection close %lu", + len, thd->thread_id); + if (len > 0) wsrep_dump_rbr_buf(thd, buf, len); + + cache = cache_mngr->get_binlog_cache_log(false); + wsrep_write_cache_buf(cache, &buf, &len); + WSREP_WARN("binlog stmt cache not empty (%lu bytes) @ connection close %lu", + len, thd->thread_id); + if (len > 0) wsrep_dump_rbr_buf(thd, buf, len); + } +#endif /* WITH_WSREP */ DBUG_ASSERT(cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty()); thd_set_ha_data(thd, binlog_hton, NULL); cache_mngr->~binlog_cache_mngr(); my_free(cache_mngr); - return 0; + DBUG_RETURN(0); } /* diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 1e16c0907c8..284c9d26d62 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -98,17 +98,32 @@ void wsrep_register_hton(THD* thd, bool all) */ void wsrep_post_commit(THD* thd, bool all) { - if (thd->wsrep_exec_mode == LOCAL_COMMIT) + switch (thd->wsrep_exec_mode) { - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); - if (wsrep->post_commit(wsrep, &thd->wsrep_ws_handle)) + case LOCAL_COMMIT: { + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); + if (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; } - wsrep_cleanup_transaction(thd); + case LOCAL_STATE: + { + /* + Non-InnoDB statements may have populated events in stmt cache => cleanup + */ + WSREP_DEBUG("cleanup transaction for LOCAL_STATE: %s", thd->query()); + wsrep_cleanup_transaction(thd); + break; + } + default: break; } + } /* From 13a9bcc6be4cb2e27c81c7e42bb534d8d1947870 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Thu, 13 Nov 2014 14:04:23 +0200 Subject: [PATCH 253/294] refs #11 #13 - skipping TOI, if all affected tables are temporary --- sql/wsrep_mysqld.cc | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9ac688953fe..08698c6e9fa 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1240,6 +1240,12 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len); } +/* + returns: + 0: statement was replicated as TOI + 1: TOI replication was skipped + -1: TOI replication failed + */ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list) { @@ -1276,31 +1282,39 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, wsrep_key_arr_t key_arr= {0, 0}; struct wsrep_buf buff = { buf, buf_len }; - if (!buf_err && + if (!buf_err && wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&& + key_arr.keys_len > 0 && WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, - key_arr.keys, key_arr.keys_len, - &buff, 1, - &thd->wsrep_trx_meta))) + key_arr.keys, key_arr.keys_len, + &buff, 1, + &thd->wsrep_trx_meta))) { thd->wsrep_exec_mode= TOTAL_ORDER; wsrep_to_isolation++; if (buf) my_free(buf); wsrep_keys_free(&key_arr); WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode); + thd->wsrep_exec_mode); } - else { + else if (key_arr.keys_len > 0) { /* jump to error handler in mysql_execute_command() */ WSREP_WARN("TO isolation failed for: %d, sql: %s. Check wsrep " "connection state and retry the query.", ret, (thd->query()) ? thd->query() : "void"); my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " - "your wsrep connection state and retry the query."); + "your wsrep connection state and retry the query."); if (buf) my_free(buf); wsrep_keys_free(&key_arr); return -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"); + return 1; + } return 0; } @@ -1454,9 +1468,15 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, table_list); break; case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; } - if (!ret) - { - thd->wsrep_exec_mode= TOTAL_ORDER; + switch (ret) { + case 0: thd->wsrep_exec_mode= TOTAL_ORDER; break; + case 1: + /* TOI replication skipped, treat as success */ + ret = 0; + break; + case -1: + /* TOI replication failed, treat as error */ + break; } } return ret; From 91417b404716e3c409a0a551a232c063d04f85a9 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Mon, 17 Nov 2014 23:47:14 +0200 Subject: [PATCH 254/294] refs #7 - merged fix from 5.5 branch. However, 5.6 branch has not (yet) surfaced similar applier hang as 5.5 --- storage/innobase/lock/lock0lock.cc | 34 ++++++++++++++++++------------ storage/xtradb/lock/lock0lock.cc | 32 ++++++++++++++++------------ 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 66033530a72..0be8f0be154 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1067,12 +1067,13 @@ lock_rec_has_to_wait( #ifdef WITH_WSREP /* if BF thread is locking and has conflict with another BF thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); + fprintf(stderr, + "BF-BF lock conflict, locking: %lu\n", + for_locking); lock_rec_print(stderr, lock2); } @@ -1081,16 +1082,21 @@ lock_rec_has_to_wait( (type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict," - "type_mode: %lu supremum: %lu\n", - type_mode, lock_is_on_supremum); - fprintf(stderr, "conflicts states: my %d locked %d\n", - wsrep_thd_conflict_state(trx->mysql_thd, FALSE), - wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); - lock_rec_print(stderr, lock2); - return FALSE; - //abort(); + if (for_locking || wsrep_debug) { + /* exclusive lock conflicts are not + accepted */ + fprintf(stderr, + "BF-BF X lock conflict," + "mode: %lu supremum: %lu\n", + type_mode, lock_is_on_supremum); + fprintf(stderr, + "conflicts states: my %d locked %d\n", + wsrep_thd_conflict_state(trx->mysql_thd, FALSE), + wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); + lock_rec_print(stderr, lock2); + if (for_locking) return FALSE; + //abort(); + } } else { /* if lock2->index->n_uniq <= lock2->index->n_user_defined_cols @@ -1110,7 +1116,7 @@ lock_rec_has_to_wait( #endif /* WITH_WSREP */ return(TRUE); } - + return(FALSE); } diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index e6d6071a15d..719888d41bd 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -1068,12 +1068,13 @@ lock_rec_has_to_wait( #ifdef WITH_WSREP /* if BF thread is locking and has conflict with another BF thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); + fprintf(stderr, + "BF-BF lock conflict, locking: %lu\n", + for_locking); lock_rec_print(stderr, lock2); } @@ -1082,16 +1083,21 @@ lock_rec_has_to_wait( (type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict," - "type_mode: %lu supremum: %lu\n", - type_mode, lock_is_on_supremum); - fprintf(stderr, "conflicts states: my %d locked %d\n", - wsrep_thd_conflict_state(trx->mysql_thd, FALSE), - wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); - lock_rec_print(stderr, lock2); - return FALSE; - //abort(); + if (for_locking || wsrep_debug) { + /* exclusive lock conflicts are not + accepted */ + fprintf(stderr, + "BF-BF X lock conflict," + "mode: %lu supremum: %lu\n", + type_mode, lock_is_on_supremum); + fprintf(stderr, + "conflicts states: my %d locked %d\n", + wsrep_thd_conflict_state(trx->mysql_thd, FALSE), + wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); + lock_rec_print(stderr, lock2); + if (for_locking) return FALSE; + //abort(); + } } else { /* if lock2->index->n_uniq <= lock2->index->n_user_defined_cols From 14b6172075eda88675d8b34951e0ee5f3f5874e3 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Tue, 9 Dec 2014 22:13:14 +0200 Subject: [PATCH 255/294] Going more MTR-friendly - for SST prefer to use mysql client, mysqldump and my_print_defaults from the local build tree. --- scripts/wsrep_sst_common.sh | 28 +++++++++++++++++++++++++++- scripts/wsrep_sst_mysqldump.sh | 10 +++++----- scripts/wsrep_sst_rsync.sh | 3 +-- scripts/wsrep_sst_xtrabackup-v2.sh | 10 +++++----- scripts/wsrep_sst_xtrabackup.sh | 10 +++++----- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 333d9dfab9a..b99e826fee5 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -94,8 +94,34 @@ done readonly WSREP_SST_OPT_BYPASS readonly WSREP_SST_OPT_BINLOG +# try to use my_print_defaults, mysql and mysqldump that come with the sources +# (for MTR suite) +SCRIPTS_DIR="$(cd $(dirname "$0"); pwd -P)" +EXTRA_DIR="$SCRIPTS_DIR/../extra" +CLIENT_DIR="$SCRIPTS_DIR/../client" + +if [ -x "$CLIENT_DIR/mysql" ]; then + MYSQL_CLIENT="$CLIENT_DIR/mysql" +else + MYSQL_CLIENT=$(which mysql) +fi + +if [ -x "$CLIENT_DIR/mysqldump" ]; then + MYSQLDUMP="$CLIENT_DIR/mysqldump" +else + MYSQLDUMP=$(which mysqldump) +fi + +if [ -x "$SCRIPTS_DIR/my_print_defaults" ]; then + MY_PRINT_DEFAULTS="$SCRIPTS_DIR/my_print_defaults" +elif [ -x "$EXTRA_DIR/my_print_defaults" ]; then + MY_PRINT_DEFAULTS="$EXTRA_DIR/my_print_defaults" +else + MY_PRINT_DEFAULTS=$(which my_print_defaults) +fi + # For Bug:1200727 -if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then +if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) fi diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index df6f816132c..3153cbcdfe0 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -57,9 +57,9 @@ then fi # Check client version -if ! mysql --version | grep 'Distrib 10.0' >/dev/null +if ! $MYSQL_CLIENT --version | grep 'Distrib 10.0' >/dev/null then - mysql --version >&2 + $MYSQL_CLIENT --version >&2 wsrep_log_error "this operation requires MySQL client version 10.0.x" exit $EINVAL fi @@ -98,10 +98,10 @@ SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" # Retrieve the donor's @@global.gtid_binlog_state. GTID_BINLOG_STATE=$(echo "SHOW GLOBAL VARIABLES LIKE 'gtid_binlog_state'" |\ -mysql $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeout=10 |\ +$MYSQL_CLIENT $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeout=10 |\ tail -1 | awk -F ' ' '{ print $2 }') -MYSQL="mysql $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ +MYSQL="$MYSQL_CLIENT $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ "--disable-reconnect --connect_timeout=10" # Check if binary logging is enabled on the joiner node. @@ -133,7 +133,7 @@ then fi # NOTE: we don't use --routines here because we're dumping mysql.proc table -MYSQLDUMP="mysqldump $AUTH -S$WSREP_SST_OPT_SOCKET \ +MYSQLDUMP="$MYSQLDUMP $AUTH -S$WSREP_SST_OPT_SOCKET \ --add-drop-database --add-drop-table --skip-add-locks --create-options \ --disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ --skip-comments --flush-privileges --all-databases" diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 86bf557662d..f5e304a1033 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -92,8 +92,7 @@ fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf if [ -z "$WSREP_LOG_DIR" ]; then - SCRIPT_DIR="$(cd $(dirname "$0"); pwd -P)" - WSREP_LOG_DIR=$($SCRIPT_DIR/my_print_defaults --defaults-file \ + WSREP_LOG_DIR=$($MY_PRINT_DEFAULTS --defaults-file \ "$WSREP_SST_OPT_CONF" mysqld server mysqld-10.0 mariadb mariadb-10.0 \ | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ | cut -b 29- ) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index beab9cf6f43..1d18b664b94 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -117,7 +117,7 @@ get_keys() fi if [[ $encrypt -eq 0 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " fi return @@ -230,7 +230,7 @@ parse_cnf() { local group=$1 local var=$2 - reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -241,7 +241,7 @@ get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. payload=$(( payload*1/2 )) @@ -443,8 +443,8 @@ check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index dd4060e6961..044f9995580 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -100,7 +100,7 @@ get_keys() fi if [[ $encrypt -eq 0 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q encrypt;then wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " fi return @@ -195,7 +195,7 @@ parse_cnf() { local group=$1 local var=$2 - reval=$(my_print_defaults -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -206,7 +206,7 @@ get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') - if my_print_defaults -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. payload=$(( payload*1/2 )) @@ -385,8 +385,8 @@ check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then + local eport=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. From 9d15689d1f529b493cd9f01fbd2271c3ff81497d Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Wed, 10 Dec 2014 23:29:28 +0200 Subject: [PATCH 256/294] Refs #25 - made sure signals that may be set to ignored in mysqld were set to default in the child process. --- sql/wsrep_utils.cc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index f30b3dcf702..a62fc4ec2ed 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -150,7 +150,35 @@ process::process (const char* cmd, const char* type) goto cleanup_pipe; } - err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + /* make sure that no signlas are masked in child process */ + sigset_t sigmask_empty; sigemptyset(&sigmask_empty); + err_ = posix_spawnattr_setsigmask(&attr, &sigmask_empty); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setsigmask() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + /* make sure the following signals are not ignored in child process */ + sigset_t default_signals; sigemptyset(&default_signals); + sigaddset(&default_signals, SIGHUP); + sigaddset(&default_signals, SIGINT); + sigaddset(&default_signals, SIGQUIT); + sigaddset(&default_signals, SIGPIPE); + sigaddset(&default_signals, SIGTERM); + sigaddset(&default_signals, SIGCHLD); + err_ = posix_spawnattr_setsigdefault(&attr, &default_signals); + if (err_) + { + WSREP_ERROR ("posix_spawnattr_setsigdefault() failed: %d (%s)", + err_, strerror(err_)); + goto cleanup_attr; + } + + err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_SETSIGMASK | + /* start a new process group */ POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_USEVFORK); if (err_) { From 7d550c76be13c58551e203f4eeb4f87ebd58ba4b Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Mon, 15 Dec 2014 04:45:58 -0800 Subject: [PATCH 257/294] LP1378355 - Pass the value of --defaults-group-suffix to xtrabackup during SST --- mysys/my_default.c | 21 +++++++++++++++++---- scripts/wsrep_sst_common.sh | 4 ++++ scripts/wsrep_sst_xtrabackup-v2.sh | 6 +++--- sql/wsrep_sst.cc | 12 ++++++++---- sql/wsrep_sst.h | 1 + 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/mysys/my_default.c b/mysys/my_default.c index d5ed1256f9c..a71a9c6fbcd 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -89,10 +89,13 @@ static char my_defaults_extra_file_buffer[FN_REFLEN]; static my_bool defaults_already_read= FALSE; #ifdef WITH_WSREP -/* The only purpose of this global array is to hold full name of my.cnf - * which seems to be otherwise unavailable */ -char wsrep_defaults_file[FN_REFLEN + 10]={0,}; -#endif /* WITH_WREP */ +/* + The only purpose of this global array is to hold full name of my.cnf + which seems to be otherwise unavailable. +*/ +char wsrep_defaults_file[FN_REFLEN + 10]= {0,}; +char wsrep_defaults_group_suffix[FN_REFLEN]= {0,}; +#endif /* WITH_WSREP */ /* Which directories are searched for options (and in which order) */ @@ -439,6 +442,16 @@ int get_defaults_options(int argc, char **argv, if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix=")) { *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; + +#ifdef WITH_WSREP + /* make sure we do this only once - for top-level file */ + if ('\0' == wsrep_defaults_group_suffix[0]) + { + strncpy(wsrep_defaults_group_suffix, *group_suffix, + sizeof(wsrep_defaults_group_suffix) - 1); + } +#endif /* WITH_WSREP */ + argc--; continue; } diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index b99e826fee5..46f4076111f 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -44,6 +44,10 @@ case "$1" in readonly WSREP_SST_OPT_CONF="$2" shift ;; + '--defaults-group-suffix') + readonly WSREP_SST_OPT_CONF_SUFFIX="$2" + shift + ;; '--host') readonly WSREP_SST_OPT_HOST="$2" shift diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 1d18b664b94..c6bfc86a74a 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -557,8 +557,8 @@ fi INNOEXTRA="" INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" -INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" -INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" +INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" +INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then @@ -879,7 +879,7 @@ then if [[ $incremental -eq 1 ]];then # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. - INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} \ + INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} \ --ibbackup=xtrabackup_56 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" fi diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 69f6b019d6b..f6ba14e5f53 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -30,6 +30,7 @@ #include extern const char wsrep_defaults_file[]; +extern const char wsrep_defaults_group_suffix[]; const char* wsrep_sst_method = WSREP_SST_DEFAULT; const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; @@ -462,11 +463,12 @@ static ssize_t sst_prepare_other (const char* method, WSREP_SST_OPT_AUTH" '%s' " WSREP_SST_OPT_DATA" '%s' " WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_CONF_SUFFIX" '%s' " WSREP_SST_OPT_PARENT" '%d'" " %s '%s' ", method, addr_in, (sst_auth_real) ? sst_auth_real : "", - sst_dir, wsrep_defaults_file, (int)getpid(), - binlog_opt, binlog_opt_val); + sst_dir, wsrep_defaults_file, wsrep_defaults_group_suffix, + (int) getpid(), binlog_opt, binlog_opt_val); my_free(binlog_opt_val); if (ret < 0 || ret >= (int)sizeof(cmd_str)) @@ -761,10 +763,11 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_CONF_SUFFIX" '%s' " WSREP_SST_OPT_GTID" '%s:%lld'" "%s", user, pswd, host, port, mysqld_port, mysqld_unix_port, - wsrep_defaults_file, uuid_str, + wsrep_defaults_file, wsrep_defaults_group_suffix, uuid_str, (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); WSREP_DEBUG("Running: '%s'", cmd_str); @@ -1034,12 +1037,13 @@ static int sst_donate_other (const char* method, WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_DATA" '%s' " WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_CONF_SUFFIX" '%s' " " %s '%s' " WSREP_SST_OPT_GTID" '%s:%lld'" "%s", method, addr, sst_auth_real, mysqld_unix_port, mysql_real_data_home, wsrep_defaults_file, - binlog_opt, binlog_opt_val, + wsrep_defaults_group_suffix, binlog_opt, binlog_opt_val, uuid, (long long) seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 28ad4cc17bc..42f1055bde2 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -24,6 +24,7 @@ #define WSREP_SST_OPT_AUTH "--auth" #define WSREP_SST_OPT_DATA "--datadir" #define WSREP_SST_OPT_CONF "--defaults-file" +#define WSREP_SST_OPT_CONF_SUFFIX "--defaults-group-suffix" #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" From da298348406747dcaf431dd5641b0d53590f5e83 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Tue, 16 Dec 2014 00:22:55 -0800 Subject: [PATCH 258/294] LP1378355 - Address review feedback, do not pass --defaults-group-suffix for mysqldump SST --- sql/wsrep_sst.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index f6ba14e5f53..0de4a474653 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -763,11 +763,10 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_CONF" '%s' " - WSREP_SST_OPT_CONF_SUFFIX" '%s' " WSREP_SST_OPT_GTID" '%s:%lld'" "%s", user, pswd, host, port, mysqld_port, mysqld_unix_port, - wsrep_defaults_file, wsrep_defaults_group_suffix, uuid_str, + wsrep_defaults_file, uuid_str, (long long)seqno, bypass ? " "WSREP_SST_OPT_BYPASS : ""); WSREP_DEBUG("Running: '%s'", cmd_str); From f725b0c49d23b9520d4e622c0291073943268ae1 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Tue, 16 Dec 2014 00:30:26 -0800 Subject: [PATCH 259/294] LP1378355 - Reduce memory consumption slightly. --- mysys/my_default.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_default.c b/mysys/my_default.c index a71a9c6fbcd..f79117c7259 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -94,7 +94,7 @@ static my_bool defaults_already_read= FALSE; which seems to be otherwise unavailable. */ char wsrep_defaults_file[FN_REFLEN + 10]= {0,}; -char wsrep_defaults_group_suffix[FN_REFLEN]= {0,}; +char wsrep_defaults_group_suffix[FN_EXTLEN]= {0,}; #endif /* WITH_WSREP */ /* Which directories are searched for options (and in which order) */ From 226c249ab396cbc57abb155183a8b86b712e4d63 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Thu, 29 Jan 2015 11:06:44 +0200 Subject: [PATCH 260/294] refs codership/mysql-wsrep#53 - fencing LOAD DATA splitting related commit to not happen with ALTER processing --- storage/innobase/handler/ha_innodb.cc | 24 +++++++++++++++------ storage/xtradb/handler/ha_innodb.cc | 30 ++++++++++++++++++--------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3b0b825f3af..81b91ae3976 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6554,6 +6554,10 @@ wsrep_store_key_val_for_row( DBUG_RETURN((uint)(buff - buff_start)); } #endif /* WITH_WSREP */ + +/*******************************************************************//** +Stores a key value for a row to a buffer. +@return key value length as stored in buff */ UNIV_INTERN uint ha_innobase::store_key_val_for_row( @@ -7480,15 +7484,19 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: - break; + break; case WSREP_TRX_SIZE_EXCEEDED: case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: - DBUG_RETURN(1); + DBUG_RETURN(1); } if (binlog_hton->commit(binlog_hton, user_thd, 1)) @@ -7507,15 +7515,19 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: - break; + break; case WSREP_TRX_SIZE_EXCEEDED: case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: - DBUG_RETURN(1); + DBUG_RETURN(1); } if (binlog_hton->commit(binlog_hton, user_thd, 1)) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index fe645ed4a14..93afd6832f3 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6808,10 +6808,10 @@ innobase_read_from_2_little_endian( return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])))); } +#ifdef WITH_WSREP /*******************************************************************//** Stores a key value for a row to a buffer. @return key value length as stored in buff */ -#ifdef WITH_WSREP UNIV_INTERN uint wsrep_store_key_val_for_row( @@ -7959,11 +7959,11 @@ ha_innobase::write_row( dberr_t error; int error_result= 0; ibool auto_inc_used= FALSE; - ulint sql_command; - trx_t* trx = thd_to_trx(user_thd); #ifdef WITH_WSREP ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ #endif + ulint sql_command; + trx_t* trx = thd_to_trx(user_thd); DBUG_ENTER("ha_innobase::write_row"); @@ -8001,7 +8001,9 @@ ha_innobase::write_row( || sql_command == SQLCOM_CREATE_INDEX #ifdef WITH_WSREP || (wsrep_on(user_thd) && wsrep_load_data_splitting && - sql_command == SQLCOM_LOAD) + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) #endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { @@ -8045,15 +8047,19 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: - break; + break; case WSREP_TRX_SIZE_EXCEEDED: case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: - DBUG_RETURN(1); + DBUG_RETURN(1); } if (binlog_hton->commit(binlog_hton, user_thd, 1)) @@ -8072,15 +8078,19 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options( + user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: - break; + break; case WSREP_TRX_SIZE_EXCEEDED: case WSREP_TRX_CERT_FAIL: case WSREP_TRX_ERROR: - DBUG_RETURN(1); + DBUG_RETURN(1); } if (binlog_hton->commit(binlog_hton, user_thd, 1)) From 0fdfca693702dafe69a1b33afb804aa0545dd81b Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Tue, 10 Feb 2015 18:27:21 +0200 Subject: [PATCH 261/294] refs codership/mysql-wsrep#60 explicit braces around empty body --- sql/wsrep_var.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index b8c454dafac..87698576c44 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -570,7 +570,9 @@ static void export_wsrep_status_to_mysql(THD* thd) for (wsrep_status_len = 0; thd->wsrep_status_vars[wsrep_status_len].name != NULL; - wsrep_status_len++); + wsrep_status_len++) { + /* */ + } #if DYNAMIC if (wsrep_status_len != mysql_status_len) { From f5bce5a6003e0591c822f217b63dc6b65a73000a Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 18 Mar 2015 14:56:46 +0200 Subject: [PATCH 262/294] codership/mysql-wsrep#67 - total order isolation for FLUSH The following FLUSH commands are now executed under total order isolation: * FLUSH DES_KEY_FILE * FLUSH HOSTS * FLUSH PRIVILEGES * FLUSH QUERY CACHE * FLUSH STATUS * FLUSH USER_RESOURCES --- mysql-test/suite/galera/r/galera_flush.result | 32 ++++++ .../suite/galera/t/galera_flush-master.opt | 1 + mysql-test/suite/galera/t/galera_flush.test | 107 ++++++++++++++++++ sql/sql_parse.cc | 15 +++ 4 files changed, 155 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_flush.result create mode 100644 mysql-test/suite/galera/t/galera_flush-master.opt create mode 100644 mysql-test/suite/galera/t/galera_flush.test diff --git a/mysql-test/suite/galera/r/galera_flush.result b/mysql-test/suite/galera/r/galera_flush.result new file mode 100644 index 00000000000..7636a30fced --- /dev/null +++ b/mysql-test/suite/galera/r/galera_flush.result @@ -0,0 +1,32 @@ +FLUSH DES_KEY_FILE; +wsrep_last_committed_diff +1 +FLUSH HOSTS; +wsrep_last_committed_diff +1 +SET GLOBAL wsrep_replicate_myisam = TRUE; +INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); +FLUSH PRIVILEGES; +DELETE FROM mysql.user WHERE user = 'user1'; +SET GLOBAL wsrep_replicate_myisam = FALSE; +FLUSH PRIVILEGES; +FLUSH QUERY CACHE; +wsrep_last_committed_diff +1 +FLUSH STATUS; +wsrep_last_committed_diff +1 +FLUSH USER_RESOURCES; +wsrep_last_committed_diff +1 +CREATE TABLE t1 (f1 INTEGER); +FLUSH LOGS; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; +wsrep_last_committed_diff +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_flush-master.opt b/mysql-test/suite/galera/t/galera_flush-master.opt new file mode 100644 index 00000000000..5a1fb6748d9 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_flush-master.opt @@ -0,0 +1 @@ +--query_cache_type=1 --query_cache_size=1000000 diff --git a/mysql-test/suite/galera/t/galera_flush.test b/mysql-test/suite/galera/t/galera_flush.test new file mode 100644 index 00000000000..21647a8328c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_flush.test @@ -0,0 +1,107 @@ +# +# Test that various FLUSH commands are replicated. Whenever possible, check the slave for the effects. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_perfschema.inc +--source include/have_query_cache.inc + +# +# The following FLUSH statements should be replicated +# + +--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 +FLUSH DES_KEY_FILE; +--connection node_2 +--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 + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +--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 +FLUSH HOSTS; +--connection node_2 +--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 + 1 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_1 +SET GLOBAL wsrep_replicate_myisam = TRUE; +INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); +FLUSH PRIVILEGES; +--connect node_2a, 127.0.0.1, user1, pass1, test, $NODE_MYPORT_2 +--connection node_1 +DELETE FROM mysql.user WHERE user = 'user1'; +SET GLOBAL wsrep_replicate_myisam = FALSE; +FLUSH PRIVILEGES; + + +--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 +FLUSH QUERY CACHE; +--connection node_2 +--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 + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +--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 +FLUSH STATUS; + +--connection node_2 +--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 + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +--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 +FLUSH USER_RESOURCES; +--connection node_2 +--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 + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +# +# The following statements should not be replicated: FLUSH LOGS, FLUSH TABLES +# + + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); + +--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 +FLUSH LOGS; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; + +--connection node_2 +--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 + +--connection node_1 +DROP TABLE t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9b7ea777335..29e9a9e7da9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4648,6 +4648,21 @@ end_with_restore_list: break; } +#ifdef WITH_WSREP + if (lex->type & ( + REFRESH_GRANT | + REFRESH_HOSTS | + REFRESH_DES_KEY_FILE | +#ifdef HAVE_QUERY_CACHE + REFRESH_QUERY_CACHE_FREE | +#endif /* HAVE_QUERY_CACHE */ + REFRESH_STATUS | + REFRESH_USER_RESOURCES)) + { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + } +#endif /* WITH_WSREP*/ + /* reload_acl_and_cache() will tell us if we are allowed to write to the binlog or not. From 4ed9ddd30eefbedb4bb2f96a0f0eb2ab18d283a0 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Mon, 23 Mar 2015 23:27:28 +0200 Subject: [PATCH 263/294] Refs codership/mysql-wsrep#33 1. factored XID-related functions to a separate wsrep_xid.cc unit. 2. refactored them to take refrences instead of pointers where appropriate 3. implemented wsrep_get/set_SE_position to take wsrep_uuid_t and wsrep_seqno_t instead of XID 4. call wsrep_set_SE_position() in wsrep_sst_received() to reinitialize SE checkpoint after SST was received, avoid assert() in setting code by first checking current position. --- sql/CMakeLists.txt | 3 +- sql/handler.cc | 5 +- sql/sql_parse.cc | 1 + sql/wsrep_applier.cc | 9 +- sql/wsrep_applier.h | 3 +- sql/wsrep_hton.cc | 5 +- sql/wsrep_mysqld.cc | 104 ++++------------ sql/wsrep_mysqld.h | 12 +- sql/wsrep_priv.h | 12 +- sql/wsrep_sst.cc | 49 ++++++-- sql/wsrep_utils.cc | 57 +-------- sql/wsrep_var.cc | 38 +++--- sql/wsrep_xid.cc | 150 +++++++++++++++++++++++ sql/wsrep_xid.h | 33 +++++ storage/innobase/include/ha_prototypes.h | 5 +- storage/xtradb/include/ha_prototypes.h | 5 +- 16 files changed, 292 insertions(+), 199 deletions(-) create mode 100644 sql/wsrep_xid.cc create mode 100644 sql/wsrep_xid.h diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 26dfad83810..c28d475d274 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -44,12 +44,13 @@ ENDIF() IF(WITH_WSREP) SET(WSREP_SOURCES + wsrep_utils.cc + wsrep_xid.cc wsrep_check_opts.cc wsrep_hton.cc wsrep_mysqld.cc wsrep_notify.cc wsrep_sst.cc - wsrep_utils.cc wsrep_var.cc wsrep_binlog.cc wsrep_applier.cc diff --git a/sql/handler.cc b/sql/handler.cc index 18cf61906a6..6a69af0b900 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -53,6 +53,7 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" +#include "wsrep_xid.h" #endif /* While we have legacy_db_type, we have this array to @@ -1468,7 +1469,7 @@ int ha_commit_trans(THD *thd, bool all) if (!error && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) { // xid was rewritten by wsrep - xid= wsrep_xid_seqno(&thd->transaction.xid_state.xid); + xid= wsrep_xid_seqno(thd->transaction.xid_state.xid); } #endif // WITH_WSREP if (!is_real_trans) @@ -1851,7 +1852,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, { #ifdef WITH_WSREP my_xid x=(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()); #else my_xid x=info->list[i].get_my_xid(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 29e9a9e7da9..a67674448c7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -106,6 +106,7 @@ #ifdef WITH_WSREP #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#include "wsrep_binlog.h" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state); #endif /* WITH_WSREP */ diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 8e5c49332a7..9fdc3952f3f 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Codership Oy +/* Copyright (C) 2013-2015 Codership Oy 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,11 +13,12 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "wsrep_applier.h" #include "wsrep_priv.h" #include "wsrep_binlog.h" // wsrep_dump_rbr_buf() +#include "wsrep_xid.h" -#include "log_event.h" // EVENT_LEN_OFFSET, etc. -#include "wsrep_applier.h" +#include "log_event.h" // class THD, EVENT_LEN_OFFSET, etc. /* read the first event from (*buf). The size of the (*buf) is (*buf_len). @@ -150,7 +151,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, thd->set_server_id(ev->server_id); thd->set_time(); // time the query wsrep_xid_init(&thd->transaction.xid_state.xid, - &thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); thd->lex->current_select= 0; if (!ev->when) diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h index 816970db67c..424db466e53 100644 --- a/sql/wsrep_applier.h +++ b/sql/wsrep_applier.h @@ -16,7 +16,8 @@ #ifndef WSREP_APPLIER_H #define WSREP_APPLIER_H -#include +#include +#include "../wsrep/wsrep_api.h" /* wsrep callback prototypes */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 284c9d26d62..144196aab2e 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -1,4 +1,4 @@ -/* Copyright 2008 Codership Oy +/* Copyright 2008-2015 Codership Oy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include #include "wsrep_mysqld.h" #include "wsrep_binlog.h" +#include "wsrep_xid.h" #include #include @@ -497,7 +498,7 @@ wsrep_run_wsrep_commit(THD *thd, handlerton *hton, bool all) 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.uuid, thd->wsrep_trx_meta.gtid.seqno); } DBUG_PRINT("wsrep", ("replicating commit success")); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 08698c6e9fa..7cfde65ebf1 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2013 Codership Oy +/* Copyright 2008-2015 Codership Oy 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 @@ -23,6 +23,7 @@ #include "wsrep_var.h" #include "wsrep_binlog.h" #include "wsrep_applier.h" +#include "wsrep_xid.h" #include #include #include "log_event.h" @@ -158,63 +159,22 @@ static void wsrep_log_states (wsrep_log_level_t const level, wsrep_log_cb (level, msg); } -static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) -{ - XID* xid= reinterpret_cast(arg); - handlerton* hton= plugin_data(plugin, handlerton *); - if (hton->db_type == DB_TYPE_INNODB) - { - const wsrep_uuid_t* uuid(wsrep_xid_uuid(xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); - WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(xid)); - hton->wsrep_set_checkpoint(hton, xid); - } - return FALSE; -} - -void wsrep_set_SE_checkpoint(XID* xid) -{ - plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); -} - -static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) -{ - XID* xid= reinterpret_cast(arg); - handlerton* hton= plugin_data(plugin, handlerton *); - if (hton->db_type == DB_TYPE_INNODB) - { - hton->wsrep_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_DEBUG("Read WSREPXid from InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(xid)); - - } - return FALSE; -} - -void wsrep_get_SE_checkpoint(XID* xid) -{ - plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, xid); -} - #ifdef GTID_SUPPORT -void wsrep_init_sidno(const wsrep_uuid_t& uuid) +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) { - ltid_uuid.data[i] = ~local_uuid.data[i]; + ltid_uuid.data[i] = ~wsrep_uuid.data[i]; } + sid.copy_from(ltid_uuid.data); global_sid_lock->wrlock(); wsrep_sidno= global_sid_map->add_sid(sid); - WSREP_INFO("inited wsrep sidno %d", wsrep_sidno); + WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno); global_sid_lock->unlock(); } #endif /* GTID_SUPPORT */ @@ -355,13 +315,11 @@ wsrep_view_handler_cb (void* app_ctx, local_seqno= view->state_id.seqno; } /* Init storage engine XIDs from first view */ - XID xid; - wsrep_xid_init(&xid, &local_uuid, local_seqno); - wsrep_set_SE_checkpoint(&xid); - new_status= WSREP_MEMBER_JOINED; + wsrep_set_SE_checkpoint(local_uuid, local_seqno); #ifdef GTID_SUPPORT wsrep_init_sidno(local_uuid); #endif /* GTID_SUPPORT */ + new_status= WSREP_MEMBER_JOINED; } // just some sanity check @@ -471,38 +429,28 @@ static void wsrep_synced_cb(void* app_ctx) static void wsrep_init_position() { /* read XIDs from storage engines */ - XID xid; - memset(&xid, 0, sizeof(xid)); - xid.formatID= -1; - wsrep_get_SE_checkpoint(&xid); + wsrep_uuid_t uuid; + wsrep_seqno_t seqno; + wsrep_get_SE_checkpoint(uuid, seqno); - if (xid.formatID == -1) + if (!memcmp(&uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t))) { WSREP_INFO("Read nil XID from storage engines, skipping position init"); return; } - else if (!wsrep_is_wsrep_xid(&xid)) - { - WSREP_WARN("Read non-wsrep XID from storage engines, skipping position init"); - return; - } - - const wsrep_uuid_t* uuid= wsrep_xid_uuid(&xid); - const wsrep_seqno_t seqno= wsrep_xid_seqno(&xid); char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + 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_uuid= uuid; local_seqno= seqno; } - else if (memcmp(&local_uuid, uuid, sizeof(local_uuid)) || + else if (memcmp(&local_uuid, &uuid, sizeof(local_uuid)) || local_seqno != seqno) { WSREP_WARN("Initial position was provided by configuration or SST, " @@ -758,14 +706,12 @@ void wsrep_recover() uuid_str, (long long)local_seqno); return; } - XID xid; - memset(&xid, 0, sizeof(xid)); - xid.formatID= -1; - wsrep_get_SE_checkpoint(&xid); + wsrep_uuid_t uuid; + wsrep_seqno_t seqno; + wsrep_get_SE_checkpoint(uuid, seqno); char uuid_str[40]; - wsrep_uuid_print(wsrep_xid_uuid(&xid), uuid_str, sizeof(uuid_str)); - WSREP_INFO("Recovered position: %s:%lld", uuid_str, - (long long)wsrep_xid_seqno(&xid)); + wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); + WSREP_INFO("Recovered position: %s:%lld", uuid_str, (long long)seqno); } @@ -1324,11 +1270,9 @@ static void wsrep_TOI_end(THD *thd) { WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); - - XID xid; - wsrep_xid_init(&xid, &thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); - wsrep_set_SE_checkpoint(&xid); + + 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)); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 4bd2489210a..79a16e5f8d1 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -1,4 +1,4 @@ -/* Copyright 2008-2013 Codership Oy +/* Copyright 2008-2015 Codership Oy 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 @@ -321,13 +321,7 @@ 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); int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len); -struct xid_t; -void wsrep_get_SE_checkpoint(xid_t*); -void wsrep_set_SE_checkpoint(xid_t*); +#ifdef GTID_SUPPORT void wsrep_init_sidno(const wsrep_uuid_t&); -void wsrep_xid_init(xid_t*, const wsrep_uuid_t*, wsrep_seqno_t); -const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*); -wsrep_seqno_t wsrep_xid_seqno(const xid_t*); -extern "C" int wsrep_is_wsrep_xid(const void* xid); - +#endif /* GTID_SUPPORT */ #endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h index 5c66587d757..30dce78c1a4 100644 --- a/sql/wsrep_priv.h +++ b/sql/wsrep_priv.h @@ -32,22 +32,20 @@ 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_gtid_t* current_id, + const wsrep_gtid_t* state_id, const char* state, size_t state_len, bool bypass); -extern unsigned int wsrep_check_ip (const char* addr); -extern size_t wsrep_guess_ip (char* buf, size_t buf_len); -extern size_t wsrep_guess_address(char* buf, size_t buf_len); extern wsrep_uuid_t local_uuid; extern wsrep_seqno_t local_seqno; // a helper function -extern void wsrep_sst_received(wsrep_t*, const wsrep_uuid_t*, wsrep_seqno_t, - const void*, size_t); +void wsrep_sst_received(wsrep_t*, const wsrep_uuid_t&, wsrep_seqno_t, + const void*, size_t); /*! SST thread signals init thread about sst completion */ -extern void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool); +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); + #endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 0de4a474653..73fd9d9a0f5 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2012 Codership Oy +/* Copyright 2008-2015 Codership Oy 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 @@ -26,6 +26,7 @@ #include #include "wsrep_priv.h" #include "wsrep_utils.h" +#include "wsrep_xid.h" #include #include @@ -244,20 +245,42 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, mysql_mutex_unlock (&LOCK_wsrep_sst); } -void wsrep_sst_received (wsrep_t* const wsrep, - const wsrep_uuid_t* const uuid, - wsrep_seqno_t const seqno, - const void* const state, - size_t const state_len) +void wsrep_sst_received (wsrep_t* const wsrep, + const wsrep_uuid_t& uuid, + wsrep_seqno_t const seqno, + const void* const state, + size_t const state_len) { - int const rcode(seqno < 0 ? seqno : 0); - wsrep_gtid_t const state_id = { - *uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno) - }; + wsrep_get_SE_checkpoint(local_uuid, local_seqno); + + if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) || + local_seqno < seqno || seqno < 0) + { + wsrep_set_SE_checkpoint(uuid, seqno); + local_uuid = uuid; + local_seqno = seqno; + } + else if (local_seqno > seqno) + { + WSREP_WARN("SST postion is in the past: %lld, current: %lld. " + "Can't continue.", + (long long)seqno, (long long)local_seqno); + unireg_abort(1); + } + #ifdef GTID_SUPPORT - wsrep_init_sidno(state_id.uuid); + wsrep_init_sidno(uuid); #endif /* GTID_SUPPORT */ - wsrep->sst_received(wsrep, &state_id, state, state_len, rcode); + + if (wsrep) + { + int const rcode(seqno < 0 ? seqno : 0); + wsrep_gtid_t const state_id = { + uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno) + }; + + wsrep->sst_received(wsrep, &state_id, state, state_len, rcode); + } } // Let applier threads to continue @@ -266,7 +289,7 @@ void wsrep_sst_continue () if (sst_needed) { WSREP_INFO("Signalling provider to continue."); - wsrep_sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); + wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0); } } diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index a62fc4ec2ed..7a87d38d430 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -1,4 +1,4 @@ -/* Copyright 2010 Codership Oy +/* Copyright 2010-2015 Codership Oy 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 @@ -467,58 +467,3 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) return 0; } - -/* - * WSREPXid - */ - -#define WSREP_XID_PREFIX "WSREPXid" -#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN -#define WSREP_XID_UUID_OFFSET 8 -#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) -{ - 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); - memcpy(xid->data + WSREP_XID_UUID_OFFSET, uuid, sizeof(wsrep_uuid_t)); - memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t)); -} - -const wsrep_uuid_t* wsrep_xid_uuid(const XID* xid) -{ - if (wsrep_is_wsrep_xid(xid)) - return reinterpret_cast(xid->data - + WSREP_XID_UUID_OFFSET); - else - return &WSREP_UUID_UNDEFINED; -} - -wsrep_seqno_t wsrep_xid_seqno(const XID* xid) -{ - - if (wsrep_is_wsrep_xid(xid)) - { - wsrep_seqno_t seqno; - memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); - return seqno; - } - else - { - return WSREP_SEQNO_UNDEFINED; - } -} - -extern -int wsrep_is_wsrep_xid(const void* xid_ptr) -{ - const XID* xid= reinterpret_cast(xid_ptr); - return (xid->formatID == 1 && - xid->gtrid_length == WSREP_XID_GTRID_LEN && - xid->bqual_length == 0 && - !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)); -} diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 87698576c44..00b9ce3e4e8 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -1,4 +1,4 @@ -/* Copyright 2008 Codership Oy +/* Copyright 2008-2015 Codership Oy 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 @@ -22,6 +22,7 @@ #include #include "wsrep_priv.h" #include "wsrep_thd.h" +#include "wsrep_xid.h" #include #include #include @@ -140,29 +141,30 @@ err: return 1; } -void wsrep_set_local_position (const char* value) +static +void wsrep_set_local_position(const char* const value, bool const sst) { - size_t value_len = strlen (value); - size_t uuid_len = wsrep_uuid_scan (value, value_len, &local_uuid); + size_t const value_len = strlen(value); + wsrep_uuid_t uuid; + size_t const uuid_len = wsrep_uuid_scan(value, value_len, &uuid); + wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10); - local_seqno = strtoll (value + uuid_len + 1, NULL, 10); - - XID xid; - wsrep_xid_init(&xid, &local_uuid, local_seqno); - wsrep_set_SE_checkpoint(&xid); - WSREP_INFO ("wsrep_start_position var submitted: '%s'", wsrep_start_position); + if (sst) { + wsrep_sst_received (wsrep, uuid, seqno, NULL, 0); + } else { + // initialization + local_uuid = uuid; + local_seqno = seqno; + } } bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) { + WSREP_INFO ("wsrep_start_position var submitted: '%s'", + wsrep_start_position); // since this value passed wsrep_start_position_check, don't check anything // here - wsrep_set_local_position (wsrep_start_position); - - if (wsrep) { - wsrep_sst_received (wsrep, &local_uuid, local_seqno, NULL, 0); - } - + wsrep_set_local_position (wsrep_start_position, true); return 0; } @@ -175,7 +177,7 @@ void wsrep_start_position_init (const char* val) return; } - wsrep_set_local_position (val); + wsrep_set_local_position (val, false); } static bool refresh_provider_options() @@ -212,7 +214,7 @@ static int wsrep_provider_verify (const char* provider_str) return 1; /* check that provider file exists */ - bzero(&f_stat, sizeof(MY_STAT)); + memset(&f_stat, 0, sizeof(MY_STAT)); if (!my_stat(path, &f_stat, MYF(0))) { return 1; diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc new file mode 100644 index 00000000000..056da5748b9 --- /dev/null +++ b/sql/wsrep_xid.cc @@ -0,0 +1,150 @@ +/* Copyright 2015 Codership Oy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//! @file some utility functions and classes not directly related to replication + +#include "wsrep_xid.h" +#include "sql_class.h" +#include "wsrep_mysqld.h" // for logging macros + +/* + * WSREPXid + */ + +#define WSREP_XID_PREFIX "WSREPXid" +#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN +#define WSREP_XID_UUID_OFFSET 8 +#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) +{ + 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); + memcpy(xid->data + WSREP_XID_UUID_OFFSET, &uuid, sizeof(wsrep_uuid_t)); + memcpy(xid->data + WSREP_XID_SEQNO_OFFSET, &seqno, sizeof(wsrep_seqno_t)); +} + +int wsrep_is_wsrep_xid(const void* xid_ptr) +{ + const XID* xid= reinterpret_cast(xid_ptr); + return (xid->formatID == 1 && + xid->gtrid_length == WSREP_XID_GTRID_LEN && + xid->bqual_length == 0 && + !memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)); +} + +const wsrep_uuid_t* wsrep_xid_uuid(const XID& xid) +{ + if (wsrep_is_wsrep_xid(&xid)) + return reinterpret_cast(xid.data + + WSREP_XID_UUID_OFFSET); + else + return &WSREP_UUID_UNDEFINED; +} + +wsrep_seqno_t wsrep_xid_seqno(const XID& xid) +{ + if (wsrep_is_wsrep_xid(&xid)) + { + wsrep_seqno_t seqno; + memcpy(&seqno, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof(wsrep_seqno_t)); + return seqno; + } + else + { + return WSREP_SEQNO_UNDEFINED; + } +} + +static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= static_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + + if (hton->db_type == DB_TYPE_INNODB) + { + const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid)); + char uuid_str[40] = {0, }; + wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(*xid)); + hton->wsrep_set_checkpoint(hton, xid); + } + + return FALSE; +} + +void wsrep_set_SE_checkpoint(XID& xid) +{ + plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); +} + +void wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) +{ + XID xid; + wsrep_xid_init(&xid, uuid, seqno); + wsrep_set_SE_checkpoint(xid); +} + +static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) +{ + XID* xid= reinterpret_cast(arg); + handlerton* hton= plugin_data(plugin, handlerton *); + + if (hton->db_type == DB_TYPE_INNODB) + { + hton->wsrep_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_DEBUG("Read WSREPXid from InnoDB: %s:%lld", + uuid_str, (long long)wsrep_xid_seqno(*xid)); + } + + return FALSE; +} + +void wsrep_get_SE_checkpoint(XID& xid) +{ + plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); +} + +void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) +{ + uuid= WSREP_UUID_UNDEFINED; + seqno= WSREP_SEQNO_UNDEFINED; + + XID xid; + memset(&xid, 0, sizeof(xid)); + xid.formatID= -1; + + wsrep_get_SE_checkpoint(xid); + + if (xid.formatID == -1) return; // nil XID + + if (!wsrep_is_wsrep_xid(&xid)) + { + WSREP_WARN("Read non-wsrep XID from storage engines."); + return; + } + + uuid= *wsrep_xid_uuid(xid); + seqno= wsrep_xid_seqno(xid); +} diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h new file mode 100644 index 00000000000..8a43e49c733 --- /dev/null +++ b/sql/wsrep_xid.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2015 Codership Oy + + 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_XID_H +#define WSREP_XID_H + +#include +#include "../wsrep/wsrep_api.h" +#include "handler.h" // XID typedef + +void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t); +int wsrep_is_wsrep_xid(const void* xid); +const wsrep_uuid_t* wsrep_xid_uuid(const XID&); +wsrep_seqno_t wsrep_xid_seqno(const XID&); + +//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */ +void wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); +//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */ +void wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t); + +#endif /* WSREP_UTILS_H */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 5ecaa33fb96..bc588c6ecf0 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -299,9 +299,8 @@ int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length, unsigned int buf_length); -int -wsrep_on(void *thd_ptr); -extern "C" int wsrep_is_wsrep_xid(const void*); +int wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); #endif /* WITH_WSREP */ /**********************************************************************//** Determines the connection character set. diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 4ebaee3c89e..86ba7464905 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -298,9 +298,8 @@ int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length, unsigned int buf_length); -int -wsrep_on(void *thd_ptr); -extern "C" int wsrep_is_wsrep_xid(const void*); +int wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); #endif /* WITH_WSREP */ /**********************************************************************//** Determines the connection character set. From 0115ca2ae1c0ce06b3de6cc8c4f7f8a06220cff6 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 26 Mar 2015 10:25:58 +0200 Subject: [PATCH 264/294] refs codership/mysql-wsrep#98 fixed sidno initialization Sidno initialization was skipped in wsrep_sst_received() if the received position matched to current position. However, sidno initialization must be done every time server is started to add inverted group uuid into sidno map. --- sql/wsrep_mysqld.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 79a16e5f8d1..24df127135e 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -324,4 +324,5 @@ int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len); #ifdef GTID_SUPPORT void wsrep_init_sidno(const wsrep_uuid_t&); #endif /* GTID_SUPPORT */ + #endif /* WSREP_MYSQLD_H */ From c16ec074196aee32326a8015f49c0b8bae25111f Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Thu, 26 Mar 2015 23:19:52 +0200 Subject: [PATCH 265/294] Refs codership/mysql-features#33 - this fixes a bug where wsrep_start_position_update() would pass local_uuid and local_seqno to wsrep_sst_received() instead of real, submitted position. --- sql/wsrep_var.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 00b9ce3e4e8..0f0a04ba435 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -144,10 +144,10 @@ err: static void wsrep_set_local_position(const char* const value, bool const sst) { - size_t const value_len = strlen(value); + size_t const value_len(strlen(value)); wsrep_uuid_t uuid; - size_t const uuid_len = wsrep_uuid_scan(value, value_len, &uuid); - wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10); + size_t const uuid_len(wsrep_uuid_scan(value, value_len, &uuid)); + wsrep_seqno_t const seqno(strtoll(value + uuid_len + 1, NULL, 10)); if (sst) { wsrep_sst_received (wsrep, uuid, seqno, NULL, 0); From 2df5ff2691a80873f44e779658c9a5d41c6c7e13 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 11 Mar 2015 13:04:00 +0200 Subject: [PATCH 266/294] refs codership/mysql-wsrep#90 - fixed race in OSU Make sure that thd uses the same method to begin and end OSU operation. --- sql/handler.cc | 4 ++-- sql/sql_class.cc | 3 ++- sql/sql_class.h | 1 + sql/wsrep_mysqld.cc | 27 +++++++++++++++++++++------ sql/wsrep_mysqld.h | 7 ++++++- sql/wsrep_thd.cc | 2 +- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 6a69af0b900..8bafb178e8b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6233,8 +6233,8 @@ int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) { DBUG_ENTER("ha_wsrep_abort_transaction"); if (!WSREP(bf_thd) && - !(wsrep_OSU_method_options == WSREP_OSU_RSU && - bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { + !(bf_thd->wsrep_OSU_method == WSREP_OSU_RSU && + bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { DBUG_RETURN(0); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8106eb95cb0..7f2b49a9f2b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1203,6 +1203,7 @@ THD::THD() wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_status_vars = 0; wsrep_mysql_replicated = 0; + wsrep_OSU_method = WSREP_OSU_NONE; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; #endif @@ -1609,7 +1610,7 @@ void THD::init(void) wsrep_PA_safe= true; wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_mysql_replicated = 0; - + wsrep_OSU_method = WSREP_OSU_NONE; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9b42f31c1f8..356fb3cd126 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2792,6 +2792,7 @@ public: wsrep_consistency_check; wsrep_stats_var* wsrep_status_vars; int wsrep_mysql_replicated; + ulong wsrep_OSU_method; const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 7cfde65ebf1..f1a91f40e1e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1392,6 +1392,12 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, thd->query(), thd->thread_id); } + /* + Save current global value into thd to persist the used method + even if global wsrep_OSU_method_options changes during isolation + */ + thd->wsrep_OSU_method= wsrep_OSU_method_options; + /* It makes sense to set auto_increment_* to defaults in TOI operations. Must be done before wsrep_TOI_begin() since Query_log_event encapsulating @@ -1407,19 +1413,23 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { - switch (wsrep_OSU_method_options) { + switch (thd->wsrep_OSU_method) { case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_, table_list); break; case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; + default: + WSREP_ERROR("Unsupported OSU method: %lu", thd->wsrep_OSU_method); + ret= -1; + break; } switch (ret) { case 0: thd->wsrep_exec_mode= TOTAL_ORDER; break; - case 1: - /* TOI replication skipped, treat as success */ - ret = 0; + case 1: + /* TOI replication skipped, treat as success */ + ret = 0; break; case -1: - /* TOI replication failed, treat as error */ + /* TOI replication failed, treat as error */ break; } } @@ -1430,13 +1440,18 @@ void wsrep_to_isolation_end(THD *thd) { if (thd->wsrep_exec_mode == TOTAL_ORDER) { - switch(wsrep_OSU_method_options) + switch(thd->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->wsrep_OSU_method); + break; } wsrep_cleanup_transaction(thd); } + thd->wsrep_OSU_method= WSREP_OSU_NONE; } #define WSREP_MDL_LOG(severity, msg, req, gra) \ diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 24df127135e..279aea0bef7 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -109,7 +109,12 @@ extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; extern bool wsrep_new_cluster; // bootstrap the cluster ? -enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; +enum enum_wsrep_OSU_method { + WSREP_OSU_TOI, + WSREP_OSU_RSU, + WSREP_OSU_NONE, +}; + enum enum_wsrep_sync_wait { WSREP_SYNC_WAIT_NONE = 0x0, // show, select, begin diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 81999d11296..1e27310a201 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -575,7 +575,7 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) DBUG_ENTER("wsrep_abort_thd"); if ( (WSREP(bf_thd) || - ( (WSREP_ON || wsrep_OSU_method_options == WSREP_OSU_RSU) && + ( (WSREP_ON || bf_thd->wsrep_OSU_method == WSREP_OSU_RSU) && bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && victim_thd) { From 03a8f83e2c6c80658c7863b452847dd04dfc5dda Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Wed, 11 Mar 2015 04:33:12 -0700 Subject: [PATCH 267/294] Add tests for galera/mysql-wsrep#90 --- .../galera/r/galera_var_OSU_method.result | 13 ++++++ .../galera/r/galera_var_OSU_method2.result | 17 ++++++++ .../suite/galera/t/galera_var_OSU_method.test | 37 ++++++++++++++++ .../galera/t/galera_var_OSU_method2.test | 43 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_var_OSU_method.result create mode 100644 mysql-test/suite/galera/r/galera_var_OSU_method2.result create mode 100644 mysql-test/suite/galera/t/galera_var_OSU_method.test create mode 100644 mysql-test/suite/galera/t/galera_var_OSU_method2.test diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method.result b/mysql-test/suite/galera/r/galera_var_OSU_method.result new file mode 100644 index 00000000000..826aa98af28 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +SET GLOBAL wsrep_OSU_method = "RSU"; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER;; +SET GLOBAL wsrep_OSU_method = "TOI"; +SET DEBUG_SYNC= 'now SIGNAL continue'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method2.result b/mysql-test/suite/galera/r/galera_var_OSU_method2.result new file mode 100644 index 00000000000..94708c18821 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +SET GLOBAL wsrep_OSU_method = "TOI"; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_OSU_method = "RSU"; +SET DEBUG_SYNC= 'now SIGNAL continue'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (1,2); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (3,4); +SET GLOBAL wsrep_OSU_method = "TOI"; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method.test b/mysql-test/suite/galera/t/galera_var_OSU_method.test new file mode 100644 index 00000000000..cfefc5419e2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_OSU_method.test @@ -0,0 +1,37 @@ +# +# Test that the wsrep_var_OSU_method variable can be changed in the middle of an ALTER without adverse effects. +# In-depth testing of various OSU methods is implemented in separate tests. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +--connection node_1 +SET GLOBAL wsrep_OSU_method = "RSU"; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 ADD COLUMN f2 INTEGER; + + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: alter_table_before_open_tables' +--source include/wait_condition.inc + +SET GLOBAL wsrep_OSU_method = "TOI"; +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1 +--reap + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_2 +# The ALTER above is not visible on node_2 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method2.test b/mysql-test/suite/galera/t/galera_var_OSU_method2.test new file mode 100644 index 00000000000..2aaba1c1af1 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_OSU_method2.test @@ -0,0 +1,43 @@ +# +# Test that the wsrep_var_OSU_method variable can be changed in the middle of an ALTER without adverse effects. +# In-depth testing of various OSU methods is implemented in separate tests. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +--connection node_1 +SET GLOBAL wsrep_OSU_method = "TOI"; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 ADD COLUMN f2 INTEGER; + + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a + +SET SESSION wsrep_sync_wait = 0; + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: alter_table_before_open_tables' +--source include/wait_condition.inc + +SET GLOBAL wsrep_OSU_method = "RSU"; +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1 +--reap + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +INSERT INTO t1 VALUES (1,2); + +--connection node_2 +# The ALTER above is visible on node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +INSERT INTO t1 VALUES (3,4); + +--connection node_1 +SET GLOBAL wsrep_OSU_method = "TOI"; +DROP TABLE t1; + From 00afd63984c91cabcfed748d834351ca54b7e50d Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 12 Mar 2015 10:25:34 +0200 Subject: [PATCH 268/294] refs codership/mysql-wsrep#90 made wsrep_OSU_method session variable --- sql/handler.cc | 4 ++-- sql/sql_class.cc | 2 -- sql/sql_class.h | 2 +- sql/sys_vars.cc | 2 +- sql/wsrep_mysqld.cc | 16 +++++----------- sql/wsrep_mysqld.h | 1 - sql/wsrep_thd.cc | 4 ++-- sql/wsrep_var.cc | 1 - 8 files changed, 11 insertions(+), 21 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 8bafb178e8b..2687361944d 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6233,8 +6233,8 @@ int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) { DBUG_ENTER("ha_wsrep_abort_transaction"); if (!WSREP(bf_thd) && - !(bf_thd->wsrep_OSU_method == WSREP_OSU_RSU && - bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { + !(bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU && + bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { DBUG_RETURN(0); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7f2b49a9f2b..33ebd1d462e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1203,7 +1203,6 @@ THD::THD() wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_status_vars = 0; wsrep_mysql_replicated = 0; - wsrep_OSU_method = WSREP_OSU_NONE; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; #endif @@ -1610,7 +1609,6 @@ void THD::init(void) wsrep_PA_safe= true; wsrep_consistency_check = NO_CONSISTENCY_CHECK; wsrep_mysql_replicated = 0; - wsrep_OSU_method = WSREP_OSU_NONE; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 356fb3cd126..dba6c9a5733 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -657,6 +657,7 @@ typedef struct system_variables my_bool wsrep_dirty_reads; uint wsrep_sync_wait; ulong wsrep_retry_autocommit; + ulong wsrep_OSU_method; #endif double long_query_time_double; @@ -2792,7 +2793,6 @@ public: wsrep_consistency_check; wsrep_stats_var* wsrep_status_vars; int wsrep_mysql_replicated; - ulong wsrep_OSU_method; const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 55a7cfc5a4a..0b748bfed14 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4682,7 +4682,7 @@ static Sys_var_uint Sys_wsrep_sync_wait( static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; static Sys_var_enum Sys_wsrep_OSU_method( "wsrep_OSU_method", "Method for Online Schema Upgrade", - GLOBAL_VAR(wsrep_OSU_method_options), CMD_LINE(OPT_ARG), + SESSION_VAR(wsrep_OSU_method), CMD_LINE(OPT_ARG), wsrep_OSU_method_names, DEFAULT(WSREP_OSU_TOI), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0)); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index f1a91f40e1e..16424f4ffd2 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1392,12 +1392,6 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, thd->query(), thd->thread_id); } - /* - Save current global value into thd to persist the used method - even if global wsrep_OSU_method_options changes during isolation - */ - thd->wsrep_OSU_method= wsrep_OSU_method_options; - /* It makes sense to set auto_increment_* to defaults in TOI operations. Must be done before wsrep_TOI_begin() since Query_log_event encapsulating @@ -1413,12 +1407,13 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { - switch (thd->wsrep_OSU_method) { + switch (thd->variables.wsrep_OSU_method) { case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_, table_list); break; case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break; default: - WSREP_ERROR("Unsupported OSU method: %lu", thd->wsrep_OSU_method); + WSREP_ERROR("Unsupported OSU method: %lu", + thd->variables.wsrep_OSU_method); ret= -1; break; } @@ -1440,18 +1435,17 @@ void wsrep_to_isolation_end(THD *thd) { if (thd->wsrep_exec_mode == TOTAL_ORDER) { - switch(thd->wsrep_OSU_method) + 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->wsrep_OSU_method); + thd->variables.wsrep_OSU_method); break; } wsrep_cleanup_transaction(thd); } - thd->wsrep_OSU_method= WSREP_OSU_NONE; } #define WSREP_MDL_LOG(severity, msg, req, gra) \ diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 279aea0bef7..414284f45fd 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -96,7 +96,6 @@ extern my_bool wsrep_certify_nonPK; extern long wsrep_max_protocol_version; extern long wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; -extern ulong wsrep_OSU_method_options; extern my_bool wsrep_desync; extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 1e27310a201..a65e0fe731d 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -575,8 +575,8 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) DBUG_ENTER("wsrep_abort_thd"); if ( (WSREP(bf_thd) || - ( (WSREP_ON || bf_thd->wsrep_OSU_method == WSREP_OSU_RSU) && - bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && + ( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) && + bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && victim_thd) { WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 0f0a04ba435..509ff7fcbc2 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -35,7 +35,6 @@ const char* wsrep_node_name = 0; const char* wsrep_node_address = 0; const char* wsrep_node_incoming_address = 0; const char* wsrep_start_position = 0; -ulong wsrep_OSU_method_options; int wsrep_init_vars() { From 504ff56ece2c3e3d18d905ca2a56a5c384f2fb43 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Thu, 12 Mar 2015 02:52:56 -0700 Subject: [PATCH 269/294] Adjust tests now that wsrep_OSU_method is a session variable. --- mysql-test/suite/galera/r/galera_var_OSU_method.result | 2 +- mysql-test/suite/galera/r/galera_var_OSU_method2.result | 2 +- mysql-test/suite/galera/t/galera_var_OSU_method.test | 2 +- mysql-test/suite/galera/t/galera_var_OSU_method2.test | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 826aa98af28..6d76c67e807 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result @@ -1,5 +1,5 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; -SET GLOBAL wsrep_OSU_method = "RSU"; +SET SESSION wsrep_OSU_method = "RSU"; SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; ALTER TABLE t1 ADD COLUMN f2 INTEGER;; SET GLOBAL wsrep_OSU_method = "TOI"; 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 94708c18821..67fc63ade74 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method2.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result @@ -1,5 +1,5 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; -SET GLOBAL wsrep_OSU_method = "TOI"; +SET SESSION wsrep_OSU_method = "TOI"; SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; ALTER TABLE t1 ADD COLUMN f2 INTEGER;; SET SESSION wsrep_sync_wait = 0; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method.test b/mysql-test/suite/galera/t/galera_var_OSU_method.test index cfefc5419e2..807d5c08157 100644 --- a/mysql-test/suite/galera/t/galera_var_OSU_method.test +++ b/mysql-test/suite/galera/t/galera_var_OSU_method.test @@ -10,7 +10,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; --connection node_1 -SET GLOBAL wsrep_OSU_method = "RSU"; +SET SESSION wsrep_OSU_method = "RSU"; SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; --send ALTER TABLE t1 ADD COLUMN f2 INTEGER; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method2.test b/mysql-test/suite/galera/t/galera_var_OSU_method2.test index 2aaba1c1af1..abc01ee3e0e 100644 --- a/mysql-test/suite/galera/t/galera_var_OSU_method2.test +++ b/mysql-test/suite/galera/t/galera_var_OSU_method2.test @@ -10,7 +10,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; --connection node_1 -SET GLOBAL wsrep_OSU_method = "TOI"; +SET SESSION wsrep_OSU_method = "TOI"; SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; --send ALTER TABLE t1 ADD COLUMN f2 INTEGER; From 58bbe9b0049638e1df12ab7443b233dcc25d0be9 Mon Sep 17 00:00:00 2001 From: Philip Stoev Date: Thu, 12 Mar 2015 05:06:33 -0700 Subject: [PATCH 270/294] Fix suite/galera/t/galera_var_OSU_method.test --- mysql-test/suite/galera/r/galera_var_OSU_method.result | 1 + mysql-test/suite/galera/t/galera_var_OSU_method.test | 2 ++ 2 files changed, 3 insertions(+) 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 6d76c67e807..8e47443184e 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result @@ -10,4 +10,5 @@ COUNT(*) = 2 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; COUNT(*) = 1 1 +SET SESSION wsrep_OSU_method = "TOI"; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method.test b/mysql-test/suite/galera/t/galera_var_OSU_method.test index 807d5c08157..6190d5cec9a 100644 --- a/mysql-test/suite/galera/t/galera_var_OSU_method.test +++ b/mysql-test/suite/galera/t/galera_var_OSU_method.test @@ -34,4 +34,6 @@ SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; --connection node_1 +SET SESSION wsrep_OSU_method = "TOI"; + DROP TABLE t1; From 608a1ce5b184f617d45c69095e1fae7b39402853 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Sat, 28 Mar 2015 13:57:38 +0200 Subject: [PATCH 271/294] Refs codership/mysql-wsrep#33 - change const initialization to assignment to follow the genral style of the file. --- sql/wsrep_var.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 509ff7fcbc2..bbfa79ac3fd 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -143,10 +143,10 @@ err: static void wsrep_set_local_position(const char* const value, bool const sst) { - size_t const value_len(strlen(value)); + size_t const value_len = strlen(value); wsrep_uuid_t uuid; - size_t const uuid_len(wsrep_uuid_scan(value, value_len, &uuid)); - wsrep_seqno_t const seqno(strtoll(value + uuid_len + 1, NULL, 10)); + size_t const uuid_len = wsrep_uuid_scan(value, value_len, &uuid); + wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10); if (sst) { wsrep_sst_received (wsrep, uuid, seqno, NULL, 0); From 3331d4e07efca993b3f34fa06b8a03b41b6b690d Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 21 Apr 2015 13:17:17 -0400 Subject: [PATCH 272/294] Merge galera tests from github.com/codership/mysql-wsrep --- mysql-test/std_data/galera-cert.pem | 20 + mysql-test/std_data/galera-key.pem | 28 + mysql-test/std_data/wsrep_notify.sh | 99 ++ mysql-test/suite/galera/disabled.def | 18 + mysql-test/suite/galera/galera_2nodes.cnf | 8 +- .../suite/galera/galera_2nodes_as_master.cnf | 69 ++ .../suite/galera/galera_2nodes_as_slave.cnf | 67 ++ mysql-test/suite/galera/galera_4nodes.cnf | 73 ++ .../galera/include/galera_have_debug_sync.inc | 9 + .../galera/include/galera_load_provider.inc | 10 + .../include/galera_reset_cluster_address.inc | 12 + .../suite/galera/include/galera_resume.inc | 9 + .../galera/include/galera_sst_restore.inc | 29 + .../include/galera_sst_set_mysqldump.inc | 22 + .../galera/include/galera_st_clean_slave.inc | 113 ++ .../include/galera_st_disconnect_slave.inc | 105 ++ .../galera/include/galera_st_kill_slave.inc | 108 ++ .../include/galera_st_kill_slave_ddl.inc | 123 ++ .../include/galera_st_shutdown_slave.inc | 105 ++ .../galera/include/galera_unload_provider.inc | 7 + .../galera/include/galera_wsrep_recover.inc | 23 + .../suite/galera/include/kill_galera.inc | 20 + .../suite/galera/include/shutdown_mysqld.inc | 18 + .../suite/galera/include/start_mysqld.inc | 22 + .../galera/r/galera_account_management.result | 40 + .../r/galera_alter_engine_innodb.result | 10 + .../r/galera_alter_engine_myisam.result | 11 + .../galera/r/galera_alter_table_force.result | 10 + .../suite/galera/r/galera_as_master.result | 7 + .../galera/r/galera_as_master_gtid.result | 59 + ...galera_as_master_gtid_change_master.result | 15 + .../suite/galera/r/galera_as_slave.result | 14 + .../galera/r/galera_as_slave_gtid.result | 16 + .../suite/galera/r/galera_bf_abort.result | 10 + .../r/galera_bf_abort_for_update.result | 10 + .../galera/r/galera_bf_abort_ftwrl.result | 8 + .../galera/r/galera_bf_abort_get_lock.result | 12 + .../r/galera_bf_abort_lock_table.result | 8 + .../galera/r/galera_bf_abort_sleep.result | 9 + .../galera/r/galera_binlog_cache_size.result | 12 + .../galera/r/galera_binlog_checksum.result | 10 + .../r/galera_binlog_event_max_size_max.result | 9 + .../r/galera_binlog_event_max_size_min.result | 6 + .../galera/r/galera_binlog_row_image.result | 79 ++ ...galera_binlog_rows_query_log_events.result | 12 + .../galera/r/galera_create_function.result | 55 + .../galera/r/galera_create_procedure.result | 53 + .../galera/r/galera_create_table_like.result | 47 + .../suite/galera/r/galera_defaults.result | 117 ++ .../suite/galera/r/galera_delete_limit.result | 19 + mysql-test/suite/galera/r/galera_enum.result | 37 + .../suite/galera/r/galera_events.result | 18 + .../galera/r/galera_fk_multicolumn.result | 6 +- .../galera/r/galera_fk_multitable.result | 4 +- mysql-test/suite/galera/r/galera_flush.result | 2 +- mysql-test/suite/galera/r/galera_ftwrl.result | 16 + .../suite/galera/r/galera_fulltext.result | 26 + .../suite/galera/r/galera_gcs_fc_limit.result | 17 + .../r/galera_gcs_max_packet_size.result | 15 + mysql-test/suite/galera/r/galera_gtid.result | 12 + .../galera/r/galera_insert_ignore.result | 52 + .../suite/galera/r/galera_insert_multi.result | 58 + .../r/galera_ist_innodb_flush_logs.result | 184 +++ .../galera/r/galera_ist_mysqldump.result | 284 +++++ .../galera/r/galera_ist_restart_joiner.result | 43 + .../suite/galera/r/galera_ist_rsync.result | 357 ++++++ .../galera/r/galera_ist_xtrabackup-v2.result | 357 ++++++ .../suite/galera/r/galera_kill_ddl.result | 11 + .../galera/r/galera_kill_largechanges.result | 14 + .../galera/r/galera_kill_nochanges.result | 10 + .../galera/r/galera_kill_smallchanges.result | 11 + .../suite/galera/r/galera_lock_table.result | 21 + .../suite/galera/r/galera_log_bin.result | 58 + .../galera/r/galera_log_output_csv.result | 21 + .../suite/galera/r/galera_many_columns.result | 1018 ----------------- .../suite/galera/r/galera_many_rows.result | 2 +- .../galera/r/galera_many_tables_nopk.result | 17 + .../galera/r/galera_many_tables_pk.result | 20 + .../suite/galera/r/galera_migrate.result | 79 ++ .../galera/r/galera_multi_database.result | 28 + .../galera/r/galera_myisam_autocommit.result | 24 + .../r/galera_myisam_transactions.result | 34 + .../suite/galera/r/galera_nopk_unicode.result | 24 + .../r/galera_parallel_apply_lock_table.result | 33 + .../r/galera_parallel_autoinc_largetrx.result | 18 + .../r/galera_parallel_autoinc_manytrx.result | 15 + .../galera/r/galera_parallel_simple.result | 27 + .../suite/galera/r/galera_pc_ignore_sb.result | 12 + .../galera/r/galera_pk_bigint_signed.result | 26 + .../galera/r/galera_pk_bigint_unsigned.result | 23 + .../suite/galera/r/galera_query_cache.result | 57 + .../suite/galera/r/galera_read_only.result | 8 + .../r/galera_repl_key_format_flat16.result | 18 + .../galera/r/galera_repl_max_ws_size.result | 8 + .../galera/r/galera_restart_nochanges.result | 9 + .../suite/galera/r/galera_rsu_add_pk.result | 26 + .../suite/galera/r/galera_rsu_drop_pk.result | 42 + .../suite/galera/r/galera_rsu_error.result | 21 + .../suite/galera/r/galera_rsu_simple.result | 21 + mysql-test/suite/galera/r/galera_sbr.result | 14 + .../suite/galera/r/galera_sbr_binlog.result | 14 + .../suite/galera/r/galera_split_brain.result | 5 + .../galera/r/galera_sql_log_bin_zero.result | 12 + mysql-test/suite/galera/r/galera_ssl.result | 18 + .../galera/r/galera_sst_mysqldump.result | 459 ++++++++ .../suite/galera/r/galera_sst_rsync.result | 359 ++++++ .../galera/r/galera_sst_xtrabackup-v2.result | 358 ++++++ .../galera/r/galera_status_cluster.result | 12 + .../galera/r/galera_status_local_state.result | 14 + .../galera/r/galera_suspend_slave.result | 10 + .../r/galera_toi_alter_auto_increment.result | 42 + .../galera/r/galera_toi_ddl_error.result | 19 + .../galera/r/galera_toi_ddl_fk_insert.result | 31 + .../galera/r/galera_toi_ddl_locking.result | 41 + .../r/galera_toi_ddl_nonconflicting.result | 23 + .../galera/r/galera_toi_ddl_sequential.result | 35 + .../suite/galera/r/galera_toi_ftwrl.result | 12 + .../galera/r/galera_toi_lock_exclusive.result | 17 + .../galera/r/galera_toi_lock_shared.result | 12 + .../r/galera_transaction_read_only.result | 21 + .../galera/r/galera_transaction_replay.result | 30 + .../suite/galera/r/galera_truncate.result | 29 + .../galera/r/galera_truncate_temporary.result | 63 + .../r/galera_unicode_identifiers.result | 18 +- .../suite/galera/r/galera_unicode_pk.result | 31 + .../suite/galera/r/galera_update_limit.result | 17 + .../galera/r/galera_v1_row_events.result | 10 + .../galera/r/galera_var_OSU_method.result | 2 + .../galera/r/galera_var_OSU_method2.result | 2 + .../r/galera_var_auto_inc_control_off.result | 6 - .../r/galera_var_auto_inc_control_on.result | 22 +- .../r/galera_var_cluster_address.result | 60 + .../galera/r/galera_var_desync_on.result | 29 + .../galera_var_innodb_disallow_writes.result | 12 + .../r/galera_var_load_data_splitting.result | 9 + .../galera/r/galera_var_max_ws_size.result | 12 + .../galera/r/galera_var_notify_cmd.result | 10 + .../r/galera_var_replicate_myisam_on.result | 72 +- .../galera/r/galera_var_slave_threads.result | 106 ++ .../galera/r/galera_var_wsrep_on_off.result | 19 + mysql-test/suite/galera/r/galera_wan.result | 14 + .../r/galera_wsrep_desync_wsrep_on.result | 33 + .../galera/r/galera_wsrep_new_cluster.result | 36 + .../r/galera_wsrep_provider_unset_set.result | 13 + .../galera/r/galera_zero_length_column.result | 38 + mysql-test/suite/galera/r/lp1276424.result | 11 + mysql-test/suite/galera/r/lp1347768.result | 17 + mysql-test/suite/galera/r/lp959512.result | 24 + .../suite/galera/r/mysql-wsrep#33.result | 103 ++ mysql-test/suite/galera/suite.pm | 14 + .../galera/t/galera_account_management.test | 101 ++ .../galera/t/galera_alter_engine_innodb.test | 17 + .../galera/t/galera_alter_engine_myisam.test | 25 + .../galera/t/galera_alter_table_force.test | 17 + .../suite/galera/t/galera_as_master.cnf | 1 + .../suite/galera/t/galera_as_master.test | 38 + .../suite/galera/t/galera_as_master_gtid.cnf | 8 + .../suite/galera/t/galera_as_master_gtid.test | 70 ++ .../t/galera_as_master_gtid_change_master.cnf | 8 + .../galera_as_master_gtid_change_master.test | 54 + mysql-test/suite/galera/t/galera_as_slave.cnf | 1 + .../suite/galera/t/galera_as_slave.test | 47 + .../suite/galera/t/galera_as_slave_gtid.cnf | 6 + .../suite/galera/t/galera_as_slave_gtid.test | 67 ++ .../suite/galera/t/galera_bf_abort.test | 29 + .../galera/t/galera_bf_abort_for_update.test | 29 + .../suite/galera/t/galera_bf_abort_ftwrl.test | 30 + .../galera/t/galera_bf_abort_get_lock.test | 36 + .../galera/t/galera_bf_abort_lock_table.test | 33 + .../suite/galera/t/galera_bf_abort_sleep.test | 30 + .../galera/t/galera_binlog_cache_size.test | 35 + .../t/galera_binlog_checksum-master.opt | 1 + .../galera/t/galera_binlog_checksum.test | 22 + ...alera_binlog_event_max_size_max-master.opt | 1 + .../t/galera_binlog_event_max_size_max.test | 20 + ...alera_binlog_event_max_size_min-master.opt | 1 + .../t/galera_binlog_event_max_size_min.test | 15 + .../galera/t/galera_binlog_row_image.test | 100 ++ .../galera_binlog_rows_query_log_events.test | 28 + .../galera/t/galera_create_function.test | 57 + .../galera/t/galera_create_procedure.test | 52 + .../galera/t/galera_create_table_like.test | 50 + .../suite/galera/t/galera_defaults.test | 69 ++ .../suite/galera/t/galera_delete_limit.test | 52 + mysql-test/suite/galera/t/galera_enum.test | 62 + mysql-test/suite/galera/t/galera_events.test | 53 + .../suite/galera/t/galera_fk_multicolumn.test | 6 +- .../suite/galera/t/galera_fk_multitable.test | 4 +- mysql-test/suite/galera/t/galera_flush.test | 2 +- mysql-test/suite/galera/t/galera_ftwrl.test | 39 + .../suite/galera/t/galera_fulltext.test | 62 + .../suite/galera/t/galera_gcs_fc_limit.test | 52 + .../galera/t/galera_gcs_max_packet_size.cnf | 5 + .../galera/t/galera_gcs_max_packet_size.test | 25 + .../suite/galera/t/galera_gtid-master.opt | 1 + mysql-test/suite/galera/t/galera_gtid.test | 27 + .../suite/galera/t/galera_insert_ignore.test | 60 + .../suite/galera/t/galera_insert_multi.test | 122 ++ .../galera/t/galera_ist_innodb_flush_logs.cnf | 12 + .../t/galera_ist_innodb_flush_logs.test | 12 + .../suite/galera/t/galera_ist_mysqldump.cnf | 11 + .../suite/galera/t/galera_ist_mysqldump.test | 17 + .../galera/t/galera_ist_restart_joiner.cnf | 4 + .../galera/t/galera_ist_restart_joiner.test | 106 ++ .../suite/galera/t/galera_ist_rsync.cnf | 11 + .../suite/galera/t/galera_ist_rsync.test | 8 + .../galera/t/galera_ist_xtrabackup-v2.cnf | 11 + .../galera/t/galera_ist_xtrabackup-v2.test | 9 + .../suite/galera/t/galera_kill_ddl.test | 39 + .../galera/t/galera_kill_largechanges.test | 43 + .../suite/galera/t/galera_kill_nochanges.test | 24 + .../galera/t/galera_kill_smallchanges.test | 39 + .../suite/galera/t/galera_lock_table.test | 43 + .../suite/galera/t/galera_log_bin-master.opt | 1 + mysql-test/suite/galera/t/galera_log_bin.test | 36 + .../galera/t/galera_log_output_csv-master.opt | 1 + .../suite/galera/t/galera_log_output_csv.test | 27 + .../suite/galera/t/galera_many_columns.test | 16 +- .../suite/galera/t/galera_many_rows.test | 2 +- .../galera/t/galera_many_tables_nopk.test | 103 ++ .../suite/galera/t/galera_many_tables_pk.test | 98 ++ mysql-test/suite/galera/t/galera_migrate.cnf | 59 + mysql-test/suite/galera/t/galera_migrate.test | 204 ++++ .../suite/galera/t/galera_multi_database.test | 43 + .../galera/t/galera_myisam_autocommit.test | 45 + .../galera/t/galera_myisam_transactions.test | 36 + .../suite/galera/t/galera_nopk_unicode.test | 43 + .../t/galera_parallel_apply_lock_table.test | 51 + .../t/galera_parallel_autoinc_largetrx.test | 50 + .../t/galera_parallel_autoinc_manytrx.test | 53 + .../galera/t/galera_parallel_simple.test | 45 + .../suite/galera/t/galera_pc_ignore_sb.test | 49 + .../galera/t/galera_pk_bigint_signed.test | 46 + .../galera/t/galera_pk_bigint_unsigned.test | 45 + .../galera/t/galera_query_cache-master.opt | 3 + .../suite/galera/t/galera_query_cache.test | 67 ++ .../suite/galera/t/galera_read_only.test | 23 + .../t/galera_repl_key_format_flat16.test | 34 + .../galera/t/galera_repl_max_ws_size.test | 25 + .../galera/t/galera_restart_nochanges.test | 23 + .../suite/galera/t/galera_rsu_add_pk.test | 43 + .../suite/galera/t/galera_rsu_drop_pk.test | 58 + .../suite/galera/t/galera_rsu_error.test | 31 + .../suite/galera/t/galera_rsu_simple.test | 34 + mysql-test/suite/galera/t/galera_sbr.test | 27 + .../galera/t/galera_sbr_binlog-master.opt | 1 + .../suite/galera/t/galera_sbr_binlog.test | 28 + .../suite/galera/t/galera_split_brain.test | 53 + .../galera/t/galera_sql_log_bin_zero.test | 25 + mysql-test/suite/galera/t/galera_ssl.cnf | 7 + mysql-test/suite/galera/t/galera_ssl.test | 24 + .../suite/galera/t/galera_sst_mysqldump.cnf | 11 + .../suite/galera/t/galera_sst_mysqldump.test | 18 + .../suite/galera/t/galera_sst_rsync.cnf | 11 + .../suite/galera/t/galera_sst_rsync.test | 9 + .../galera/t/galera_sst_xtrabackup-v2.cnf | 13 + .../galera/t/galera_sst_xtrabackup-v2.test | 9 + .../suite/galera/t/galera_status_cluster.test | 18 + .../galera/t/galera_status_local_state.test | 28 + .../suite/galera/t/galera_suspend_slave.test | 51 + .../t/galera_toi_alter_auto_increment.test | 120 ++ .../suite/galera/t/galera_toi_ddl_error.test | 29 + .../galera/t/galera_toi_ddl_fk_insert.test | 70 ++ .../galera/t/galera_toi_ddl_locking.test | 76 ++ .../t/galera_toi_ddl_nonconflicting.test | 30 + .../galera/t/galera_toi_ddl_sequential.test | 29 + .../suite/galera/t/galera_toi_ftwrl.test | 22 + .../galera/t/galera_toi_lock_exclusive.test | 38 + .../galera/t/galera_toi_lock_shared.test | 23 + .../t/galera_transaction_read_only.test | 58 + .../galera/t/galera_transaction_replay.test | 63 + .../suite/galera/t/galera_truncate.test | 57 + .../galera/t/galera_truncate_temporary.test | 82 ++ .../suite/galera/t/galera_udf-master.opt | 2 + .../galera/t/galera_unicode_identifiers.test | 10 +- .../suite/galera/t/galera_unicode_pk.test | 64 ++ .../suite/galera/t/galera_update_limit.test | 55 + .../galera/t/galera_v1_row_events-master.opt | 1 + .../suite/galera/t/galera_v1_row_events.test | 21 + .../suite/galera/t/galera_var_OSU_method.test | 6 + .../galera/t/galera_var_OSU_method2.test | 4 + .../t/galera_var_auto_inc_control_off.test | 4 + .../t/galera_var_auto_inc_control_on.test | 7 +- .../galera/t/galera_var_cluster_address.test | 105 ++ .../suite/galera/t/galera_var_desync_on.test | 58 + .../t/galera_var_innodb_disallow_writes.test | 33 + .../t/galera_var_load_data_splitting.test | 38 + .../galera/t/galera_var_max_ws_size.test | 27 + .../galera/t/galera_var_notify_cmd-master.opt | 1 + .../suite/galera/t/galera_var_notify_cmd.test | 14 + .../t/galera_var_replicate_myisam_on.test | 120 +- .../galera/t/galera_var_slave_threads.test | 70 ++ .../galera/t/galera_var_wsrep_on_off.test | 32 + mysql-test/suite/galera/t/galera_wan.cnf | 14 + mysql-test/suite/galera/t/galera_wan.test | 30 + .../t/galera_wsrep_desync_wsrep_on.test | 57 + .../t/galera_wsrep_new_cluster-master.opt | 1 + .../galera/t/galera_wsrep_new_cluster.test | 24 + .../t/galera_wsrep_provider_unset_set.test | 41 + .../galera/t/galera_zero_length_column.test | 41 + mysql-test/suite/galera/t/lp1276424.test | 17 + mysql-test/suite/galera/t/lp1347768.test | 24 + mysql-test/suite/galera/t/lp959512.test | 26 + mysql-test/suite/galera/t/mysql-wsrep#33.cnf | 8 + mysql-test/suite/galera/t/mysql-wsrep#33.test | 18 + mysql-test/suite/galera_3nodes/disabled.def | 2 + .../suite/galera_3nodes/galera_3nodes.cnf | 58 + .../galera_3nodes/include/galera_suspend.inc | 14 + mysql-test/suite/galera_3nodes/my.cnf | 1 + .../r/galera_certification_ccc.result | 17 + ...galera_certification_double_failure.result | 12 + .../r/galera_evs_suspect_timeout.result | 19 + .../suite/galera_3nodes/r/galera_garbd.result | 14 + .../r/galera_ist_gcache_rollover.result | 46 + .../r/galera_parallel_apply_3nodes.result | 13 + .../galera_3nodes/r/galera_pc_weight.result | 118 ++ mysql-test/suite/galera_3nodes/suite.pm | 52 + .../t/galera_certification_ccc.test | 60 + .../galera_certification_double_failure.test | 33 + .../t/galera_evs_suspect_timeout.test | 67 ++ .../suite/galera_3nodes/t/galera_garbd.test | 50 + .../t/galera_ist_gcache_rollover.cnf | 11 + .../t/galera_ist_gcache_rollover.test | 98 ++ .../t/galera_parallel_apply_3nodes.test | 38 + .../galera_3nodes/t/galera_pc_weight.test | 110 ++ mysql-test/suite/wsrep/r/variables.result | 8 + mysql-test/suite/wsrep/t/variables.test | 2 +- sql/sql_table.cc | 11 + 328 files changed, 12629 insertions(+), 1090 deletions(-) create mode 100644 mysql-test/std_data/galera-cert.pem create mode 100644 mysql-test/std_data/galera-key.pem create mode 100755 mysql-test/std_data/wsrep_notify.sh create mode 100644 mysql-test/suite/galera/disabled.def create mode 100644 mysql-test/suite/galera/galera_2nodes_as_master.cnf create mode 100644 mysql-test/suite/galera/galera_2nodes_as_slave.cnf create mode 100644 mysql-test/suite/galera/galera_4nodes.cnf create mode 100644 mysql-test/suite/galera/include/galera_have_debug_sync.inc create mode 100644 mysql-test/suite/galera/include/galera_load_provider.inc create mode 100644 mysql-test/suite/galera/include/galera_reset_cluster_address.inc create mode 100644 mysql-test/suite/galera/include/galera_resume.inc create mode 100644 mysql-test/suite/galera/include/galera_sst_restore.inc create mode 100644 mysql-test/suite/galera/include/galera_sst_set_mysqldump.inc create mode 100644 mysql-test/suite/galera/include/galera_st_clean_slave.inc create mode 100644 mysql-test/suite/galera/include/galera_st_disconnect_slave.inc create mode 100644 mysql-test/suite/galera/include/galera_st_kill_slave.inc create mode 100644 mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc create mode 100644 mysql-test/suite/galera/include/galera_st_shutdown_slave.inc create mode 100644 mysql-test/suite/galera/include/galera_unload_provider.inc create mode 100644 mysql-test/suite/galera/include/galera_wsrep_recover.inc create mode 100644 mysql-test/suite/galera/include/kill_galera.inc create mode 100644 mysql-test/suite/galera/include/shutdown_mysqld.inc create mode 100644 mysql-test/suite/galera/include/start_mysqld.inc create mode 100644 mysql-test/suite/galera/r/galera_account_management.result create mode 100644 mysql-test/suite/galera/r/galera_alter_engine_innodb.result create mode 100644 mysql-test/suite/galera/r/galera_alter_engine_myisam.result create mode 100644 mysql-test/suite/galera/r/galera_alter_table_force.result create mode 100644 mysql-test/suite/galera/r/galera_as_master.result create mode 100644 mysql-test/suite/galera/r/galera_as_master_gtid.result create mode 100644 mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result create mode 100644 mysql-test/suite/galera/r/galera_as_slave.result create mode 100644 mysql-test/suite/galera/r/galera_as_slave_gtid.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_for_update.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_get_lock.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_lock_table.result create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_sleep.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_cache_size.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_checksum.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_row_image.result create mode 100644 mysql-test/suite/galera/r/galera_binlog_rows_query_log_events.result create mode 100644 mysql-test/suite/galera/r/galera_create_function.result create mode 100644 mysql-test/suite/galera/r/galera_create_procedure.result create mode 100644 mysql-test/suite/galera/r/galera_create_table_like.result create mode 100644 mysql-test/suite/galera/r/galera_defaults.result create mode 100644 mysql-test/suite/galera/r/galera_delete_limit.result create mode 100644 mysql-test/suite/galera/r/galera_enum.result create mode 100644 mysql-test/suite/galera/r/galera_events.result create mode 100644 mysql-test/suite/galera/r/galera_ftwrl.result create mode 100644 mysql-test/suite/galera/r/galera_fulltext.result create mode 100644 mysql-test/suite/galera/r/galera_gcs_fc_limit.result create mode 100644 mysql-test/suite/galera/r/galera_gcs_max_packet_size.result create mode 100644 mysql-test/suite/galera/r/galera_gtid.result create mode 100644 mysql-test/suite/galera/r/galera_insert_ignore.result create mode 100644 mysql-test/suite/galera/r/galera_insert_multi.result create mode 100644 mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result create mode 100644 mysql-test/suite/galera/r/galera_ist_mysqldump.result create mode 100644 mysql-test/suite/galera/r/galera_ist_restart_joiner.result create mode 100644 mysql-test/suite/galera/r/galera_ist_rsync.result create mode 100644 mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result create mode 100644 mysql-test/suite/galera/r/galera_kill_ddl.result create mode 100644 mysql-test/suite/galera/r/galera_kill_largechanges.result create mode 100644 mysql-test/suite/galera/r/galera_kill_nochanges.result create mode 100644 mysql-test/suite/galera/r/galera_kill_smallchanges.result create mode 100644 mysql-test/suite/galera/r/galera_lock_table.result create mode 100644 mysql-test/suite/galera/r/galera_log_bin.result create mode 100644 mysql-test/suite/galera/r/galera_log_output_csv.result create mode 100644 mysql-test/suite/galera/r/galera_many_tables_nopk.result create mode 100644 mysql-test/suite/galera/r/galera_many_tables_pk.result create mode 100644 mysql-test/suite/galera/r/galera_migrate.result create mode 100644 mysql-test/suite/galera/r/galera_multi_database.result create mode 100644 mysql-test/suite/galera/r/galera_myisam_autocommit.result create mode 100644 mysql-test/suite/galera/r/galera_myisam_transactions.result create mode 100644 mysql-test/suite/galera/r/galera_nopk_unicode.result create mode 100644 mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result create mode 100644 mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result create mode 100644 mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result create mode 100644 mysql-test/suite/galera/r/galera_parallel_simple.result create mode 100644 mysql-test/suite/galera/r/galera_pc_ignore_sb.result create mode 100644 mysql-test/suite/galera/r/galera_pk_bigint_signed.result create mode 100644 mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result create mode 100644 mysql-test/suite/galera/r/galera_query_cache.result create mode 100644 mysql-test/suite/galera/r/galera_read_only.result create mode 100644 mysql-test/suite/galera/r/galera_repl_key_format_flat16.result create mode 100644 mysql-test/suite/galera/r/galera_repl_max_ws_size.result create mode 100644 mysql-test/suite/galera/r/galera_restart_nochanges.result create mode 100644 mysql-test/suite/galera/r/galera_rsu_add_pk.result create mode 100644 mysql-test/suite/galera/r/galera_rsu_drop_pk.result create mode 100644 mysql-test/suite/galera/r/galera_rsu_error.result create mode 100644 mysql-test/suite/galera/r/galera_rsu_simple.result create mode 100644 mysql-test/suite/galera/r/galera_sbr.result create mode 100644 mysql-test/suite/galera/r/galera_sbr_binlog.result create mode 100644 mysql-test/suite/galera/r/galera_split_brain.result create mode 100644 mysql-test/suite/galera/r/galera_sql_log_bin_zero.result create mode 100644 mysql-test/suite/galera/r/galera_ssl.result create mode 100644 mysql-test/suite/galera/r/galera_sst_mysqldump.result create mode 100644 mysql-test/suite/galera/r/galera_sst_rsync.result create mode 100644 mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result create mode 100644 mysql-test/suite/galera/r/galera_status_cluster.result create mode 100644 mysql-test/suite/galera/r/galera_status_local_state.result create mode 100644 mysql-test/suite/galera/r/galera_suspend_slave.result create mode 100644 mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ddl_error.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ddl_fk_insert.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ddl_locking.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ddl_sequential.result create mode 100644 mysql-test/suite/galera/r/galera_toi_ftwrl.result create mode 100644 mysql-test/suite/galera/r/galera_toi_lock_exclusive.result create mode 100644 mysql-test/suite/galera/r/galera_toi_lock_shared.result create mode 100644 mysql-test/suite/galera/r/galera_transaction_read_only.result create mode 100644 mysql-test/suite/galera/r/galera_transaction_replay.result create mode 100644 mysql-test/suite/galera/r/galera_truncate.result create mode 100644 mysql-test/suite/galera/r/galera_truncate_temporary.result create mode 100644 mysql-test/suite/galera/r/galera_unicode_pk.result create mode 100644 mysql-test/suite/galera/r/galera_update_limit.result create mode 100644 mysql-test/suite/galera/r/galera_v1_row_events.result create mode 100644 mysql-test/suite/galera/r/galera_var_cluster_address.result create mode 100644 mysql-test/suite/galera/r/galera_var_desync_on.result create mode 100644 mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result create mode 100644 mysql-test/suite/galera/r/galera_var_load_data_splitting.result create mode 100644 mysql-test/suite/galera/r/galera_var_max_ws_size.result create mode 100644 mysql-test/suite/galera/r/galera_var_notify_cmd.result create mode 100644 mysql-test/suite/galera/r/galera_var_slave_threads.result create mode 100644 mysql-test/suite/galera/r/galera_var_wsrep_on_off.result create mode 100644 mysql-test/suite/galera/r/galera_wan.result create mode 100644 mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result create mode 100644 mysql-test/suite/galera/r/galera_wsrep_new_cluster.result create mode 100644 mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result create mode 100644 mysql-test/suite/galera/r/galera_zero_length_column.result create mode 100644 mysql-test/suite/galera/r/lp1276424.result create mode 100644 mysql-test/suite/galera/r/lp1347768.result create mode 100644 mysql-test/suite/galera/r/lp959512.result create mode 100644 mysql-test/suite/galera/r/mysql-wsrep#33.result create mode 100644 mysql-test/suite/galera/t/galera_account_management.test create mode 100644 mysql-test/suite/galera/t/galera_alter_engine_innodb.test create mode 100644 mysql-test/suite/galera/t/galera_alter_engine_myisam.test create mode 100644 mysql-test/suite/galera/t/galera_alter_table_force.test create mode 100644 mysql-test/suite/galera/t/galera_as_master.cnf create mode 100644 mysql-test/suite/galera/t/galera_as_master.test create mode 100644 mysql-test/suite/galera/t/galera_as_master_gtid.cnf create mode 100644 mysql-test/suite/galera/t/galera_as_master_gtid.test create mode 100644 mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf create mode 100644 mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test create mode 100644 mysql-test/suite/galera/t/galera_as_slave.cnf create mode 100644 mysql-test/suite/galera/t/galera_as_slave.test create mode 100644 mysql-test/suite/galera/t/galera_as_slave_gtid.cnf create mode 100644 mysql-test/suite/galera/t/galera_as_slave_gtid.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_for_update.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_ftwrl.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_get_lock.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_lock_table.test create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_sleep.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_cache_size.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_checksum-master.opt create mode 100644 mysql-test/suite/galera/t/galera_binlog_checksum.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_event_max_size_max-master.opt create mode 100644 mysql-test/suite/galera/t/galera_binlog_event_max_size_max.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_event_max_size_min-master.opt create mode 100644 mysql-test/suite/galera/t/galera_binlog_event_max_size_min.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_row_image.test create mode 100644 mysql-test/suite/galera/t/galera_binlog_rows_query_log_events.test create mode 100644 mysql-test/suite/galera/t/galera_create_function.test create mode 100644 mysql-test/suite/galera/t/galera_create_procedure.test create mode 100644 mysql-test/suite/galera/t/galera_create_table_like.test create mode 100644 mysql-test/suite/galera/t/galera_defaults.test create mode 100644 mysql-test/suite/galera/t/galera_delete_limit.test create mode 100644 mysql-test/suite/galera/t/galera_enum.test create mode 100644 mysql-test/suite/galera/t/galera_events.test create mode 100644 mysql-test/suite/galera/t/galera_ftwrl.test create mode 100644 mysql-test/suite/galera/t/galera_fulltext.test create mode 100644 mysql-test/suite/galera/t/galera_gcs_fc_limit.test create mode 100644 mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf create mode 100644 mysql-test/suite/galera/t/galera_gcs_max_packet_size.test create mode 100644 mysql-test/suite/galera/t/galera_gtid-master.opt create mode 100644 mysql-test/suite/galera/t/galera_gtid.test create mode 100644 mysql-test/suite/galera/t/galera_insert_ignore.test create mode 100644 mysql-test/suite/galera/t/galera_insert_multi.test create mode 100644 mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test create mode 100644 mysql-test/suite/galera/t/galera_ist_mysqldump.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_mysqldump.test create mode 100644 mysql-test/suite/galera/t/galera_ist_restart_joiner.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_restart_joiner.test create mode 100644 mysql-test/suite/galera/t/galera_ist_rsync.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_rsync.test create mode 100644 mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.test create mode 100644 mysql-test/suite/galera/t/galera_kill_ddl.test create mode 100644 mysql-test/suite/galera/t/galera_kill_largechanges.test create mode 100644 mysql-test/suite/galera/t/galera_kill_nochanges.test create mode 100644 mysql-test/suite/galera/t/galera_kill_smallchanges.test create mode 100644 mysql-test/suite/galera/t/galera_lock_table.test create mode 100644 mysql-test/suite/galera/t/galera_log_bin-master.opt create mode 100644 mysql-test/suite/galera/t/galera_log_bin.test create mode 100644 mysql-test/suite/galera/t/galera_log_output_csv-master.opt create mode 100644 mysql-test/suite/galera/t/galera_log_output_csv.test create mode 100644 mysql-test/suite/galera/t/galera_many_tables_nopk.test create mode 100644 mysql-test/suite/galera/t/galera_many_tables_pk.test create mode 100644 mysql-test/suite/galera/t/galera_migrate.cnf create mode 100644 mysql-test/suite/galera/t/galera_migrate.test create mode 100644 mysql-test/suite/galera/t/galera_multi_database.test create mode 100644 mysql-test/suite/galera/t/galera_myisam_autocommit.test create mode 100644 mysql-test/suite/galera/t/galera_myisam_transactions.test create mode 100644 mysql-test/suite/galera/t/galera_nopk_unicode.test create mode 100644 mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test create mode 100644 mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test create mode 100644 mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test create mode 100644 mysql-test/suite/galera/t/galera_parallel_simple.test create mode 100644 mysql-test/suite/galera/t/galera_pc_ignore_sb.test create mode 100644 mysql-test/suite/galera/t/galera_pk_bigint_signed.test create mode 100644 mysql-test/suite/galera/t/galera_pk_bigint_unsigned.test create mode 100644 mysql-test/suite/galera/t/galera_query_cache-master.opt create mode 100644 mysql-test/suite/galera/t/galera_query_cache.test create mode 100644 mysql-test/suite/galera/t/galera_read_only.test create mode 100644 mysql-test/suite/galera/t/galera_repl_key_format_flat16.test create mode 100644 mysql-test/suite/galera/t/galera_repl_max_ws_size.test create mode 100644 mysql-test/suite/galera/t/galera_restart_nochanges.test create mode 100644 mysql-test/suite/galera/t/galera_rsu_add_pk.test create mode 100644 mysql-test/suite/galera/t/galera_rsu_drop_pk.test create mode 100644 mysql-test/suite/galera/t/galera_rsu_error.test create mode 100644 mysql-test/suite/galera/t/galera_rsu_simple.test create mode 100644 mysql-test/suite/galera/t/galera_sbr.test create mode 100644 mysql-test/suite/galera/t/galera_sbr_binlog-master.opt create mode 100644 mysql-test/suite/galera/t/galera_sbr_binlog.test create mode 100644 mysql-test/suite/galera/t/galera_split_brain.test create mode 100644 mysql-test/suite/galera/t/galera_sql_log_bin_zero.test create mode 100644 mysql-test/suite/galera/t/galera_ssl.cnf create mode 100644 mysql-test/suite/galera/t/galera_ssl.test create mode 100644 mysql-test/suite/galera/t/galera_sst_mysqldump.cnf create mode 100644 mysql-test/suite/galera/t/galera_sst_mysqldump.test create mode 100644 mysql-test/suite/galera/t/galera_sst_rsync.cnf create mode 100644 mysql-test/suite/galera/t/galera_sst_rsync.test create mode 100644 mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf create mode 100644 mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.test create mode 100644 mysql-test/suite/galera/t/galera_status_cluster.test create mode 100644 mysql-test/suite/galera/t/galera_status_local_state.test create mode 100644 mysql-test/suite/galera/t/galera_suspend_slave.test create mode 100644 mysql-test/suite/galera/t/galera_toi_alter_auto_increment.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ddl_error.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ddl_fk_insert.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ddl_locking.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ddl_sequential.test create mode 100644 mysql-test/suite/galera/t/galera_toi_ftwrl.test create mode 100644 mysql-test/suite/galera/t/galera_toi_lock_exclusive.test create mode 100644 mysql-test/suite/galera/t/galera_toi_lock_shared.test create mode 100644 mysql-test/suite/galera/t/galera_transaction_read_only.test create mode 100644 mysql-test/suite/galera/t/galera_transaction_replay.test create mode 100644 mysql-test/suite/galera/t/galera_truncate.test create mode 100644 mysql-test/suite/galera/t/galera_truncate_temporary.test create mode 100644 mysql-test/suite/galera/t/galera_udf-master.opt create mode 100644 mysql-test/suite/galera/t/galera_unicode_pk.test create mode 100644 mysql-test/suite/galera/t/galera_update_limit.test create mode 100644 mysql-test/suite/galera/t/galera_v1_row_events-master.opt create mode 100644 mysql-test/suite/galera/t/galera_v1_row_events.test create mode 100644 mysql-test/suite/galera/t/galera_var_cluster_address.test create mode 100644 mysql-test/suite/galera/t/galera_var_desync_on.test create mode 100644 mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test create mode 100644 mysql-test/suite/galera/t/galera_var_load_data_splitting.test create mode 100644 mysql-test/suite/galera/t/galera_var_max_ws_size.test create mode 100644 mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt create mode 100644 mysql-test/suite/galera/t/galera_var_notify_cmd.test create mode 100644 mysql-test/suite/galera/t/galera_var_slave_threads.test create mode 100644 mysql-test/suite/galera/t/galera_var_wsrep_on_off.test create mode 100644 mysql-test/suite/galera/t/galera_wan.cnf create mode 100644 mysql-test/suite/galera/t/galera_wan.test create mode 100644 mysql-test/suite/galera/t/galera_wsrep_desync_wsrep_on.test create mode 100644 mysql-test/suite/galera/t/galera_wsrep_new_cluster-master.opt create mode 100644 mysql-test/suite/galera/t/galera_wsrep_new_cluster.test create mode 100644 mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test create mode 100644 mysql-test/suite/galera/t/galera_zero_length_column.test create mode 100644 mysql-test/suite/galera/t/lp1276424.test create mode 100644 mysql-test/suite/galera/t/lp1347768.test create mode 100644 mysql-test/suite/galera/t/lp959512.test create mode 100644 mysql-test/suite/galera/t/mysql-wsrep#33.cnf create mode 100644 mysql-test/suite/galera/t/mysql-wsrep#33.test create mode 100644 mysql-test/suite/galera_3nodes/disabled.def create mode 100644 mysql-test/suite/galera_3nodes/galera_3nodes.cnf create mode 100644 mysql-test/suite/galera_3nodes/include/galera_suspend.inc create mode 100644 mysql-test/suite/galera_3nodes/my.cnf create mode 100644 mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_garbd.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result create mode 100644 mysql-test/suite/galera_3nodes/r/galera_pc_weight.result create mode 100644 mysql-test/suite/galera_3nodes/suite.pm create mode 100644 mysql-test/suite/galera_3nodes/t/galera_certification_ccc.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_garbd.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf create mode 100644 mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test create mode 100644 mysql-test/suite/galera_3nodes/t/galera_pc_weight.test diff --git a/mysql-test/std_data/galera-cert.pem b/mysql-test/std_data/galera-cert.pem new file mode 100644 index 00000000000..3b48002f47a --- /dev/null +++ b/mysql-test/std_data/galera-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWTCCAkGgAwIBAgIJAIlW4JmZGnU4MA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNV +BAYTAkZJMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg +Q29tcGFueSBMdGQwIBcNMTQxMDI0MDc1MTU1WhgPMzAxNDAyMjQwNzUxNTVaMEIx +CzAJBgNVBAYTAkZJMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl +ZmF1bHQgQ29tcGFueSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDDzU6xLZDD5rZENsOpTpTmqS8YisBaefU3ZeN7VJepZZ/7unM/1YLGJtuRh2Qa +MyTkvyjzf7bSFsDt9L5lfQwBBblVeWkrCvGnQmHDQQYB7JrSmFDPz9W9Mxf9Q2BW +B3lcoKXXJgMnWw0WGrt0lEdFp9gWbq8H9hwJdjpyyk4ZTIuucSOD4JUP3QFEhYU5 +kdcIbDRVw81J4eAZ6EdvbjDN05S7qWjW7rJTnCHAHEd18hcsMGwjpwhjEaSdhMrM +mhOeL8kuQV0fI8v2xfYBliIn9xBZGOVzySPzwFmQceORlW6F3V5w6mwFkmuXqXWX +Qo98swTu7mb89qVYmR71d3L3AgMBAAGjUDBOMB0GA1UdDgQWBBRdWet/kGNTyvXK +wuBdP/eSldOgWjAfBgNVHSMEGDAWgBRdWet/kGNTyvXKwuBdP/eSldOgWjAMBgNV +HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCcJpP+DR4AJxVelNTSZa+V38c+ +jgrMD2Ku2eU8NQlsjgMfNEU5Md/g7FpP8aCFzVf0kAAT7DxZmSE3uWXQbMXyVJmy +bF+qXinf71QzdWULm6sASoshC6wbHnXL9ZjWQ3gh1nqVgo3MmLQYrb3eJfKaaLoc +wpjhYxVxGFOx1ITN3jED64lUfoLHvR6NFbESYKAuAAzSNqX4HOQ3uGk2THM8JocZ +oH2+38d81Kd4HQ7DDDKS/isG0+rR60Ti1cMgu7OT7p1dZCwT/KQuI5eGjE9lubkc +yAJjaod4rVLdBri3XVvtySfS2+/75qUgv2TF7d/s7mxMq4DDt29yeKSUhZCs +-----END CERTIFICATE----- diff --git a/mysql-test/std_data/galera-key.pem b/mysql-test/std_data/galera-key.pem new file mode 100644 index 00000000000..c88c613cacf --- /dev/null +++ b/mysql-test/std_data/galera-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDDzU6xLZDD5rZE +NsOpTpTmqS8YisBaefU3ZeN7VJepZZ/7unM/1YLGJtuRh2QaMyTkvyjzf7bSFsDt +9L5lfQwBBblVeWkrCvGnQmHDQQYB7JrSmFDPz9W9Mxf9Q2BWB3lcoKXXJgMnWw0W +Grt0lEdFp9gWbq8H9hwJdjpyyk4ZTIuucSOD4JUP3QFEhYU5kdcIbDRVw81J4eAZ +6EdvbjDN05S7qWjW7rJTnCHAHEd18hcsMGwjpwhjEaSdhMrMmhOeL8kuQV0fI8v2 +xfYBliIn9xBZGOVzySPzwFmQceORlW6F3V5w6mwFkmuXqXWXQo98swTu7mb89qVY +mR71d3L3AgMBAAECggEBAIMT0UdZSp1quL/nrYqNGa9kuSuDz4uCM3+3jNcGZVU4 +vCYHxpmINLi0UK8W5ROJA3zC4AZKjDgOlW93NXK5iKyyiUTIN3hiJi4jiVDuGbh2 +DZtH7mmAKAU1zCx2y2osLLmurfbe8qOJF7ShhrZfgWsHFujFhhUdU92dsTkhZ7EU +2NF8ScxCo4PbOJoHC3j0ApfwCMxUMAKZF5+08EeKYqK7OAXI79HeIvEbHn3cUDGm +bvg6ykwlz2UUO4sg+xdCmn1Bt36HF/4e973Y5fkE/vd9mryHIlu9t7GJgWyUiPr8 +BGEoAWDSpPOMd/b9ivtxh9Gd+LW/uitMuBIfrRPgz9kCgYEA+JqeeD2xqF2IzZyq +i1UqgKe3su2U2zhkgbu1h/1M/reNIZGylF0wFs3P+kNIB2NavmHjXcgSjdJzqRL9 +XEWfFJRmeARo9RTEQEVd8zp1Eo8ISeiksGgvbL4rrNIRR5V5MZytfISRiGCWN6jx +ulJ6EieQk5EcvknGlWpJY/bBsQ0CgYEAyaCLqrR38gVl2Z0t6YlhW/HWAwGt+lf4 +apN1AS4uykx7wRW2B0y9QUDfsrYeVlbbeRPP4UzPmJez+J2cweoIIeFFyo3KP2L7 +79E3EVYywjXhPg52F7OjFA4Bp970XclIC5Al7kDufSgwZmWdceSx4Jjc5ixyQEC8 +Ad0ThgP6yxMCgYAvC4OFmZcvF1Q2JLmZWGqMojB/KbqLqaZLbqwxqduSMEYC3kF/ +FgttpVEAOQ8+ZqzbbkbKjnwEXpkIm9FaTsqF6HdjquH5zw48Y2QeDSfudSbKZb4U +rAKdf3dgYvhmJYEjxFSIRcYMmsqSieQEsGrtWJNheYqI8AkmaVCuHBoXWQKBgQCj +daelNffD2wJuQNI28axfiRjSiSsNuQHpDTCfS1ydnxH5QGu5UUphO4HfdWv03SfC +6f/vDIGEmQBLvyOVxfDf3qzhAMCFUO8kxj1ZrcMq1dmMoNa2cmj0WkKXYNZFrmfd +D/jgRf3Ss6FBcoIJErnudp8nb8MUOibxb9RjIpjQxwKBgEliKaGN+/QkPTNJ4vXz +609CIilxpE+YVTzlv3YeZP5HqsJTJPS2ARIUr/Pjpbl3LHfYNeeGDCwgkJIK0JJH +iA1M51q6t3zG2y9gKmC15FF0jShoZkRgqBxqrSHAnrCo5t2C48ElxJ3FEU8T75sz +dlGTbkmR0Wm43Kh++dWICJ3g +-----END PRIVATE KEY----- diff --git a/mysql-test/std_data/wsrep_notify.sh b/mysql-test/std_data/wsrep_notify.sh new file mode 100755 index 00000000000..7036f603c84 --- /dev/null +++ b/mysql-test/std_data/wsrep_notify.sh @@ -0,0 +1,99 @@ +#!/bin/sh -eu + +# This is a simple example of wsrep notification script (wsrep_notify_cmd). +# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' +# and fill them on every membership or node status change. +# +# Edit parameters below to specify the address and login to server. + +USER=root +HOST=127.0.0.1 +PORT=$NODE_MYPORT_1 + +SCHEMA="mtr_wsrep_notify" +MEMB_TABLE="$SCHEMA.membership" +STATUS_TABLE="$SCHEMA.status" + +BEGIN=" +SET wsrep_on=0; +CREATE SCHEMA IF NOT EXISTS $SCHEMA; +CREATE TABLE IF NOT EXISTS $MEMB_TABLE ( + idx INT, + uuid CHAR(40), /* node UUID */ + name VARCHAR(32), /* node name */ + addr VARCHAR(256) /* node address */ +) ENGINE=MEMORY; +CREATE TABLE IF NOT EXISTS $STATUS_TABLE ( + size INT, /* component size */ + idx INT, /* this node index */ + status CHAR(16), /* this node status */ + uuid CHAR(40), /* cluster UUID */ + prim BOOLEAN /* if component is primary */ +) ENGINE=MEMORY; +BEGIN; +" +END="COMMIT;" + +configuration_change() +{ + echo "$BEGIN;" + + local idx=0 + + for NODE in $(echo $MEMBERS | sed s/,/\ /g) + do + echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " + # Don't forget to properly quote string values + echo "'$NODE'" | sed s/\\//\',\'/g + echo ");" + idx=$(( $idx + 1 )) + done + + echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" + + echo "$END" +} + +status_update() +{ + echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;" +} + +COM=status_update # not a configuration change by default + +while [ $# -gt 0 ] +do + case $1 in + --status) + STATUS=$2 + shift + ;; + --uuid) + CLUSTER_UUID=$2 + shift + ;; + --primary) + [ "$2" = "yes" ] && PRIMARY="1" || PRIMARY="0" + COM=configuration_change + shift + ;; + --index) + INDEX=$2 + shift + ;; + --members) + MEMBERS=$2 + shift + ;; + esac + shift +done + +# Undefined means node is shutting down +if [ "$STATUS" != "Undefined" ] +then + $COM | mysql -B -u$USER -h$HOST -P$PORT +fi + +exit 0 +# diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def new file mode 100644 index 00000000000..397bf8e75c5 --- /dev/null +++ b/mysql-test/suite/galera/disabled.def @@ -0,0 +1,18 @@ +galera_wsrep_provider_unset_set : lp1379204 'Unsupported protocol downgrade: incremental data collection disabled. Expect abort.' +galera_kill_nochanges : mysql-wsrep#24 Galera server does not restart properly if killed +galera_bf_abort_for_update : mysql-wsrep#26 SELECT FOR UPDATE sometimes allowed to proceed in the face of a concurrent update +galera_toi_ddl_fk_insert : qa#39 galera_toi_ddl_fk_insert fails sporadically +galera_binlog_row_image : MDEV-7471 - Enable binlog_row_image parameter in MariaDB +galera_binlog_rows_query_log_events : Unknown system variable 'binlog_rows_query_log_events' (see annotate_rows_log_event) + +galera_sbr : MDEV-7995 - DMLs not getting replicated with log-bin=OFF & binlog-format != ROW +galera_create_trigger : MDEV-7996 - CURRENT_USER definer does not replicate for triggers +galera_ist_mysqldump : Lost connection to MySQL server during query +galera_ist_xtrabackup-v2 : mysqltest failed but provided no output +galera_ist_innodb_flush_logs : mysqltest failed but provided no output +galera_sst_mysqldump : query 'show status' failed with wrong errno 1927 +galera_as_master_gtid : Needs to be re-worked +galera_as_master_gtid_change_master : Needs to be re-worked +galera_migrate : query 'let $success= `$wait_condition`' failed: 1146 +galera_var_notify_cmd : Result content mismatch + diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index 38a57758064..7e998e387dc 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -5,9 +5,8 @@ binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb - -wsrep-cluster-address=gcomm:// 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=7 @@ -16,9 +15,10 @@ wsrep-sync-wait=7 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +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' -wsrep_node_incoming_address=127.0.0.1 [mysqld.2] #galera_port=@OPT.port @@ -26,8 +26,10 @@ wsrep_node_incoming_address=127.0.0.1 #sst_port=@OPT.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' + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf new file mode 100644 index 00000000000..08d860e9ba4 --- /dev/null +++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf @@ -0,0 +1,69 @@ +# +# This file creates a setup with a 2-node Galera cluster (master) and one +# standalone MariaDB server, to be used as a slave. +# + +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb + +[mysqld.1] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +server-id=1 +log-bin=mysqld-bin +log_slave_updates + +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_cluster_address=gcomm:// +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' +wsrep_node_address=127.0.0.1 +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=7 + +[mysqld.2] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +server-id=2 +log-bin=mysqld-bin +log_slave_updates + +wsrep_provider=@ENV.WSREP_PROVIDER +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_node_address=127.0.0.1 +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=7 + +[mysqld.3] +server-id=3 + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +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 new file mode 100644 index 00000000000..3822301fc6e --- /dev/null +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -0,0 +1,67 @@ +# +# This .cnf file creates a setup with 1 standard MariaDB server, followed by a 2-node Galera cluster +# + +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +binlog-format=row + +[mysqld.1] +log-bin +server-id=1 + +[mysqld.2] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +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:// +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=7 +server-id=2 + +[mysqld.3] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +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' + +# enforce read-committed characteristics across the cluster +wsrep-causal-reads=ON +wsrep-sync-wait=7 +server-id=3 + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +NODE_MYSOCK_2= @mysqld.2.socket + +NODE_MYPORT_3= @mysqld.2.port +NODE_MYSOCK_3= @mysqld.2.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_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf new file mode 100644 index 00000000000..e54ff27759e --- /dev/null +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -0,0 +1,73 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb +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=7 + +[mysqld.1] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +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' + +[mysqld.2] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='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' + + +[mysqld.3] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='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' + + +[mysqld.4] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='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' + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +NODE_MYSOCK_2= @mysqld.2.socket + +NODE_MYPORT_3= @mysqld.3.port +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_have_debug_sync.inc b/mysql-test/suite/galera/include/galera_have_debug_sync.inc new file mode 100644 index 00000000000..7c0156052d8 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_have_debug_sync.inc @@ -0,0 +1,9 @@ +--disable_query_log + +--let $galera_have_debug_sync = `SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'` + +--if (!$galera_have_debug_sync) { + --skip "Test requires Galera debug library with debug_sync functionality" +} + +--enable_query_log diff --git a/mysql-test/suite/galera/include/galera_load_provider.inc b/mysql-test/suite/galera/include/galera_load_provider.inc new file mode 100644 index 00000000000..761a1a89fd3 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_load_provider.inc @@ -0,0 +1,10 @@ +--echo Loading wsrep provider ... + +--disable_query_log +--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +--enable_reconnect +--source include/wait_until_connected_again.inc +--source include/wait_until_ready.inc diff --git a/mysql-test/suite/galera/include/galera_reset_cluster_address.inc b/mysql-test/suite/galera/include/galera_reset_cluster_address.inc new file mode 100644 index 00000000000..02937ec8ea3 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_reset_cluster_address.inc @@ -0,0 +1,12 @@ +--echo Resetting wsrep_cluster_address + +--let $wsrep_cluster_size_orig = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'` + +SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; + +--source include/wait_until_connected_again.inc + +# Wait for wsrep_cluster_size to go back to its original value + +--let $wait_condition = SELECT VARIABLE_VALUE = $wsrep_cluster_size_orig 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_resume.inc b/mysql-test/suite/galera/include/galera_resume.inc new file mode 100644 index 00000000000..232cb46479e --- /dev/null +++ b/mysql-test/suite/galera/include/galera_resume.inc @@ -0,0 +1,9 @@ +--echo Resuming node ... +--perl + my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -18 $mysqld_pid"); + exit(0); +EOF + diff --git a/mysql-test/suite/galera/include/galera_sst_restore.inc b/mysql-test/suite/galera/include/galera_sst_restore.inc new file mode 100644 index 00000000000..a08b148c31a --- /dev/null +++ b/mysql-test/suite/galera/include/galera_sst_restore.inc @@ -0,0 +1,29 @@ +# +# Restore the various options used for SST to their original values +# so that MTR's end-of-test checks are happy. +# + +--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"); + +--disable_query_log +--eval SET GLOBAL wsrep_sst_auth = '$wsrep_sst_auth_orig'; +--enable_query_log + +--error 0,ER_CANNOT_USER +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"); + +--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'; +--enable_query_log diff --git a/mysql-test/suite/galera/include/galera_sst_set_mysqldump.inc b/mysql-test/suite/galera/include/galera_sst_set_mysqldump.inc new file mode 100644 index 00000000000..405c16ce4f1 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_sst_set_mysqldump.inc @@ -0,0 +1,22 @@ +# +# Set all the variables required for the SST to be performed via mysqldump +# + +--echo Setting SST method to mysqldump ... + +--connection node_1 +# We need a user with a password to perform SST, otherwise we hit LP #1378253 +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; + +--let $wsrep_sst_auth_orig = `SELECT @@wsrep_sst_auth` +SET GLOBAL wsrep_sst_auth = 'sst:sst'; + +--connection node_2 +--let $wsrep_sst_method_orig = `SELECT @@wsrep_sst_method` +--let $wsrep_sst_receive_address_orig = `SELECT @@wsrep_sst_receive_address` + +--disable_query_log +# Set wsrep_sst_receive_address to the SQL port +--eval SET GLOBAL wsrep_sst_receive_address = '127.0.0.2:$NODE_MYPORT_2'; +--enable_query_log +SET GLOBAL wsrep_sst_method = 'mysqldump'; diff --git a/mysql-test/suite/galera/include/galera_st_clean_slave.inc b/mysql-test/suite/galera/include/galera_st_clean_slave.inc new file mode 100644 index 00000000000..81ba54aa6f5 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_st_clean_slave.inc @@ -0,0 +1,113 @@ +--echo Performing State Transfer on a server that starts from a clean var directory +--echo This is accomplished by shutting down node #2 and removing its var directory before restarting it + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; + +--echo Shutting down server ... +--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' +--source include/wait_condition.inc + +--echo Cleaning var directory ... +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mtr +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); + +--connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); + +--connection node_2 +--echo Starting server ... +--source include/start_mysqld.inc +--source include/wait_until_ready.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; + +--connection node_1 +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; + +--connection node_1a_galera_st_clean_slave +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; + +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc new file mode 100644 index 00000000000..c8869746bd1 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc @@ -0,0 +1,105 @@ +--echo Performing State Transfer on a server that has been temporarily disconnected + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; + +--source suite/galera/include/galera_unload_provider.inc + +--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; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); + +--connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); + +--connection node_2 +--source suite/galera/include/galera_load_provider.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; + +--connection node_1 +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; + +--connection node_1a_galera_st_disconnect_slave +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; + +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/include/galera_st_kill_slave.inc b/mysql-test/suite/galera/include/galera_st_kill_slave.inc new file mode 100644 index 00000000000..bae37755c65 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_st_kill_slave.inc @@ -0,0 +1,108 @@ +--echo Performing State Transfer on a server that has been killed and restarted + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; + +--source include/kill_galera.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); + +--connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); + +--connection node_2 +--let $galera_wsrep_recover_server_id=2 +--source suite/galera/include/galera_wsrep_recover.inc + +--echo Starting server ... +--source include/start_mysqld.inc +--source include/wait_until_ready.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; + +--connection node_1 +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; + +--connection node_1a_galera_st_kill_slave +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; + +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc b/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc new file mode 100644 index 00000000000..b8dd0fda987 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc @@ -0,0 +1,123 @@ +--echo Performing State Transfer on a server that has been killed and restarted +--echo while a DDL was in progress on it + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); + +--connection node_2 +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; + +# Suspend the applier as it applies the ALTER TABLE +--let $debug_orig = `SELECT @@debug_dbug` +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +SET wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now' +--source include/wait_condition.inc + +--source include/kill_galera.inc + +--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; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; + +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); + +--connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); + +--connection node_2 +--let $galera_wsrep_recover_server_id=2 +--source suite/galera/include/galera_wsrep_recover.inc + +--connection node_2 +--echo Starting server ... +--source include/start_mysqld.inc +--source include/wait_until_ready.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; + +--connection node_1 +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; + +--connection node_1a_galera_st_kill_slave_ddl +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; + +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc b/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc new file mode 100644 index 00000000000..1a65ef1bd94 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc @@ -0,0 +1,105 @@ +--echo Performing State Transfer on a server that has been shut down cleanly and restarted + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; + +--echo Shutting down server ... +--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' +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); + +--connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); + +--connection node_2 +--echo Starting server ... +--source include/start_mysqld.inc +--source include/wait_until_ready.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; + +--connection node_1 +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; + +--connection node_1a_galera_st_shutdown_slave +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; + +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) = 35 FROM t1; +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/include/galera_unload_provider.inc b/mysql-test/suite/galera/include/galera_unload_provider.inc new file mode 100644 index 00000000000..edc7eb31e0e --- /dev/null +++ b/mysql-test/suite/galera/include/galera_unload_provider.inc @@ -0,0 +1,7 @@ +--echo Unloading wsrep provider ... + +--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` + +SET GLOBAL wsrep_provider = 'none'; diff --git a/mysql-test/suite/galera/include/galera_wsrep_recover.inc b/mysql-test/suite/galera/include/galera_wsrep_recover.inc new file mode 100644 index 00000000000..090ffe5f5df --- /dev/null +++ b/mysql-test/suite/galera/include/galera_wsrep_recover.inc @@ -0,0 +1,23 @@ +--echo Performing --wsrep-recover ... +--exec $MYSQLD --defaults-group-suffix=.$galera_wsrep_recover_server_id --defaults-file=$MYSQLTEST_VARDIR/my.cnf --innodb --wsrep-recover > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1 + +--perl + use strict; + my $wsrep_start_position_str = "grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'"; + 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; + print FILE "--let \$galera_wsrep_start_position = $wsrep_start_position\n"; + close FILE; +EOF + +--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc + +if ($galera_wsrep_start_position == '') { + --die "Could not obtain wsrep_start_position." +} + +--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc diff --git a/mysql-test/suite/galera/include/kill_galera.inc b/mysql-test/suite/galera/include/kill_galera.inc new file mode 100644 index 00000000000..d7f665df6c7 --- /dev/null +++ b/mysql-test/suite/galera/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/suite/galera/include/shutdown_mysqld.inc b/mysql-test/suite/galera/include/shutdown_mysqld.inc new file mode 100644 index 00000000000..54bba1318e7 --- /dev/null +++ b/mysql-test/suite/galera/include/shutdown_mysqld.inc @@ -0,0 +1,18 @@ +# This is the first half of include/restart_mysqld.inc. +if ($rpl_inited) +{ + if (!$allow_rpl_inited) + { + --die ERROR IN TEST: When using the replication test framework (master-slave.inc, rpl_init.inc etc), use rpl_restart_server.inc instead of restart_mysqld.inc. If you know what you are doing and you really have to use restart_mysqld.inc, set allow_rpl_inited=1 before you source restart_mysqld.inc + } +} + +# Write file to make mysql-test-run.pl expect the "crash", but don't start it +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect +--exec echo "wait" > $_expect_file_name + +# Send shutdown to the connected server +--shutdown_server +--source include/wait_until_disconnected.inc + diff --git a/mysql-test/suite/galera/include/start_mysqld.inc b/mysql-test/suite/galera/include/start_mysqld.inc new file mode 100644 index 00000000000..4ee3d17810c --- /dev/null +++ b/mysql-test/suite/galera/include/start_mysqld.inc @@ -0,0 +1,22 @@ +# Include this script only after using shutdown_mysqld.inc +# where $_expect_file_name was initialized. +# Write file to make mysql-test-run.pl start up the server again + +if ($galera_wsrep_start_position != '') { + --echo Using --wsrep-start-position when starting mysqld ... + --exec echo "restart:$start_mysqld_params --wsrep-start-position=$galera_wsrep_start_position" > $_expect_file_name + --let $galera_wsrep_start_position = 0 +} + +if ($galera_wsrep_start_position == '') { + --exec echo "restart:$start_mysqld_params" > $_expect_file_name +} + +# Turn on reconnect +--enable_reconnect + +# Call script that will poll the server waiting for it to be back online again +--source include/wait_until_connected_again.inc + +# Turn off reconnect again +--disable_reconnect diff --git a/mysql-test/suite/galera/r/galera_account_management.result b/mysql-test/suite/galera/r/galera_account_management.result new file mode 100644 index 00000000000..9b3ae9ba46e --- /dev/null +++ b/mysql-test/suite/galera/r/galera_account_management.result @@ -0,0 +1,40 @@ +CREATE USER user1, user2 IDENTIFIED BY 'password'; +SELECT COUNT(*) = 2 FROM mysql.user WHERE user IN ('user1', 'user2'); +COUNT(*) = 2 +1 +RENAME USER user2 TO user3; +SELECT COUNT(*) = 0 FROM mysql.user WHERE user = 'user2'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM mysql.user WHERE user = 'user3'; +COUNT(*) = 1 +1 +SET PASSWORD FOR user3 = PASSWORD('foo'); +SELECT password != '' FROM mysql.user WHERE user = 'user3'; +password != '' +1 +DROP USER user1, user3; +SELECT COUNT(*) = 0 FROM mysql.user WHERE user IN ('user1', 'user2'); +COUNT(*) = 0 +1 +GRANT ALL ON *.* TO user4 IDENTIFIED BY 'password'; +SELECT COUNT(*) = 1 FROM mysql.user WHERE user = 'user4'; +COUNT(*) = 1 +1 +SELECT Select_priv = 'Y' FROM mysql.user WHERE user = 'user4'; +Select_priv = 'Y' +1 +CREATE USER user5; +GRANT PROXY ON user4 TO user5; +SELECT COUNT(*) = 1 FROM mysql.proxies_priv WHERE user = 'user5'; +COUNT(*) = 1 +1 +REVOKE ALL PRIVILEGES ON *.* FROM user4; +SELECT Select_priv = 'N' FROM mysql.user WHERE user = 'user4'; +Select_priv = 'N' +1 +REVOKE PROXY ON user4 FROM user5; +SELECT COUNT(*) = 0 FROM mysql.proxies_priv WHERE user = 'user5'; +COUNT(*) = 0 +1 +DROP USER user4, user5; diff --git a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result new file mode 100644 index 00000000000..2b30ac5814d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ENGINE=InnoDB; +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +ENGINE = 'InnoDB' +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result new file mode 100644 index 00000000000..280cb58208c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_replicate_myisam = TRUE; +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ENGINE=InnoDB; +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +ENGINE = 'InnoDB' +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_alter_table_force.result b/mysql-test/suite/galera/r/galera_alter_table_force.result new file mode 100644 index 00000000000..401ab46d868 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_alter_table_force.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 FORCE; +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +ENGINE = 'InnoDB' +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_as_master.result b/mysql-test/suite/galera/r/galera_as_master.result new file mode 100644 index 00000000000..aba93573ecf --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_master.result @@ -0,0 +1,7 @@ +START SLAVE; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +DROP TABLE t1; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid.result b/mysql-test/suite/galera/r/galera_as_master_gtid.result new file mode 100644 index 00000000000..8dfe462d495 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_master_gtid.result @@ -0,0 +1,59 @@ +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +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= ':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= ':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= ':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= ':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= ':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= ':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= ':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= ':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; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result b/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result new file mode 100644 index 00000000000..80fbccf58e2 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_master_gtid_change_master.result @@ -0,0 +1,15 @@ +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +STOP SLAVE; +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +INSERT INTO t1 VALUES(3); +INSERT INTO t1 VALUES(4); +DROP TABLE t1; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_slave.result b/mysql-test/suite/galera/r/galera_as_slave.result new file mode 100644 index 00000000000..1e86afa35b7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_slave.result @@ -0,0 +1,14 @@ +START SLAVE; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (3); +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE t1; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid.result b/mysql-test/suite/galera/r/galera_as_slave_gtid.result new file mode 100644 index 00000000000..fbac7b1b6b5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result @@ -0,0 +1,16 @@ +START SLAVE; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +SELECT LENGTH(@@global.gtid_binlog_state) > 1; +LENGTH(@@global.gtid_binlog_state) > 1 +1 +gtid_binlog_state_equal +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +gtid_binlog_state_equal +1 +DROP TABLE t1; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_bf_abort.result b/mysql-test/suite/galera/r/galera_bf_abort.result new file mode 100644 index 00000000000..c55f1a4dfcb --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +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_for_update.result b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result new file mode 100644 index 00000000000..3978a3df193 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +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_ftwrl.result b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result new file mode 100644 index 00000000000..e3819172510 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result @@ -0,0 +1,8 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +FLUSH TABLES WITH READ LOCK;; +INSERT INTO t1 VALUES (1); +UNLOCK TABLES; +wsrep_local_aborts_increment +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..2e44a773b23 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT GET_LOCK("foo", 1000); +GET_LOCK("foo", 1000) +1 +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT GET_LOCK("foo", 1000);; +INSERT INTO t1 VALUES (1); +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_lock_table.result b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result new file mode 100644 index 00000000000..e657e724a8b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result @@ -0,0 +1,8 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +LOCK TABLE t1 WRITE; +INSERT INTO t1 VALUES (1);; +INSERT INTO t1 VALUES (2); +wsrep_local_aborts_increment +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 new file mode 100644 index 00000000000..8e85a5feda2 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT SLEEP(1000);; +INSERT INTO t1 VALUES (1); +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_binlog_cache_size.result b/mysql-test/suite/galera/r/galera_binlog_cache_size.result new file mode 100644 index 00000000000..9726cf2a440 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_cache_size.result @@ -0,0 +1,12 @@ +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); +SET GLOBAL binlog_cache_size=4096; +SET GLOBAL max_binlog_cache_size=4096; +SET AUTOCOMMIT=ON; +START TRANSACTION; +INSERT INTO t1 SELECT REPEAT('a', 767) FROM ten; +INSERT INTO t1 SELECT REPEAT('a', 767) FROM ten; +ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_binlog_checksum.result b/mysql-test/suite/galera/r/galera_binlog_checksum.result new file mode 100644 index 00000000000..a6ab62350b1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_checksum.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result new file mode 100644 index 00000000000..4156c0c70a7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result @@ -0,0 +1,9 @@ +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)); +INSERT INTO t1 SELECT REPEAT('x', 1000) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +SELECT COUNT(*) = 10000 FROM t1; +COUNT(*) = 10000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result new file mode 100644 index 00000000000..984a943fcbe --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result @@ -0,0 +1,6 @@ +CREATE TABLE t1 (f1 VARCHAR(1000)); +INSERT INTO t1 VALUES (REPEAT('x', 1000)); +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = REPEAT('x', 1000); +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_binlog_row_image.result b/mysql-test/suite/galera/r/galera_binlog_row_image.result new file mode 100644 index 00000000000..a1f0fb455f3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_row_image.result @@ -0,0 +1,79 @@ +SET SESSION binlog_row_image=minimal; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL UNIQUE) ENGINE=InnoDB; +CREATE TABLE t3 (f1 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t3 VALUES (1); +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t3 WHERE f1 = 1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +UPDATE t2 SET f1 = 2 WHERE f1 = 1; +UPDATE t3 SET f1 = 2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t3 WHERE f1 = 2; +COUNT(*) = 1 +1 +DELETE FROM t1; +DELETE FROM t2; +DELETE FROM t3; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t3; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +SET SESSION binlog_row_image=noblob; +CREATE TABLE t1 (f1 BLOB, f2 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 BLOB) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('abc', 1); +INSERT INTO t2 VALUES ('abc'); +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'abc'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 'abc'; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 'xyz'; +UPDATE t2 SET f1 = 'xyz'; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'xyz'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 'xyz'; +COUNT(*) = 1 +1 +UPDATE t1 SET f2 = 2 WHERE f2 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'xyz'; +COUNT(*) = 1 +1 +DELETE FROM t1; +DELETE FROM t2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_binlog_rows_query_log_events.result b/mysql-test/suite/galera/r/galera_binlog_rows_query_log_events.result new file mode 100644 index 00000000000..80ae3d0de2c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_binlog_rows_query_log_events.result @@ -0,0 +1,12 @@ +SET GLOBAL binlog_rows_query_log_events=TRUE; +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SET GLOBAL binlog_rows_query_log_events = 0; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_create_function.result b/mysql-test/suite/galera/r/galera_create_function.result new file mode 100644 index 00000000000..442e2cf0e10 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_function.result @@ -0,0 +1,55 @@ +CREATE USER 'user1'; +CREATE +DEFINER = 'user1' +FUNCTION f1 (param INTEGER) +RETURNS VARCHAR(200) +COMMENT 'f1_comment' +LANGUAGE SQL +NOT DETERMINISTIC +MODIFIES SQL DATA +SQL SECURITY DEFINER +RETURN 'abc'; +GRANT EXECUTE ON FUNCTION f1 TO user1; +CREATE +DEFINER = CURRENT_USER +FUNCTION f2 (param VARCHAR(100)) +RETURNS INTEGER +DETERMINISTIC +NO SQL +SQL SECURITY INVOKER +RETURN 123; +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f1 CREATE DEFINER=`user1`@`%` FUNCTION `f1`(param INTEGER) RETURNS varchar(200) CHARSET latin1 + MODIFIES SQL DATA + COMMENT 'f1_comment' +RETURN 'abc' latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f1 CREATE DEFINER=`user1`@`%` FUNCTION `f1`(param INTEGER) RETURNS varchar(200) CHARSET latin1 + MODIFIES SQL DATA + COMMENT 'f1_comment' +RETURN 'abc' latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION f2; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f2 CREATE DEFINER=`root`@`localhost` FUNCTION `f2`(param VARCHAR(100)) RETURNS int(11) + NO SQL + DETERMINISTIC + SQL SECURITY INVOKER +RETURN 123 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION f2; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f2 CREATE DEFINER=`root`@`localhost` FUNCTION `f2`(param VARCHAR(100)) RETURNS int(11) + NO SQL + DETERMINISTIC + SQL SECURITY INVOKER +RETURN 123 latin1 latin1_swedish_ci latin1_swedish_ci +SELECT f1(1) = 'abc'; +f1(1) = 'abc' +1 +SELECT f2('abc') = 123; +f2('abc') = 123 +1 +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP USER 'user1'; diff --git a/mysql-test/suite/galera/r/galera_create_procedure.result b/mysql-test/suite/galera/r/galera_create_procedure.result new file mode 100644 index 00000000000..0806749ebc8 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_procedure.result @@ -0,0 +1,53 @@ +CREATE USER 'user1'; +CREATE TABLE t1 (f1 INTEGER); +CREATE +DEFINER = 'user1' +PROCEDURE p1 (IN param1 INTEGER, OUT param2 INTEGER, INOUT param3 INTEGER) +COMMENT 'p1_comment' +LANGUAGE SQL +NOT DETERMINISTIC +MODIFIES SQL DATA +SQL SECURITY DEFINER +INSERT INTO t1 VALUES (1); +GRANT EXECUTE ON PROCEDURE p1 TO user1; +CREATE +DEFINER = CURRENT_USER +PROCEDURE p2 (param VARCHAR(100)) +DETERMINISTIC +NO SQL +SQL SECURITY INVOKER BEGIN END ; +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p1 CREATE DEFINER=`user1`@`%` PROCEDURE `p1`(IN param1 INTEGER, OUT param2 INTEGER, INOUT param3 INTEGER) + MODIFIES SQL DATA + COMMENT 'p1_comment' +INSERT INTO t1 VALUES (1) latin1 latin1_swedish_ci latin1_swedish_ci +SELECT 1 FROM DUAL; +1 +1 +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p1 CREATE DEFINER=`user1`@`%` PROCEDURE `p1`(IN param1 INTEGER, OUT param2 INTEGER, INOUT param3 INTEGER) + MODIFIES SQL DATA + COMMENT 'p1_comment' +INSERT INTO t1 VALUES (1) latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE p2; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p2 CREATE DEFINER=`root`@`localhost` PROCEDURE `p2`(param VARCHAR(100)) + NO SQL + DETERMINISTIC + SQL SECURITY INVOKER +BEGIN END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE p2; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p2 CREATE DEFINER=`root`@`localhost` PROCEDURE `p2`(param VARCHAR(100)) + NO SQL + DETERMINISTIC + SQL SECURITY INVOKER +BEGIN END latin1 latin1_swedish_ci latin1_swedish_ci +CALL p1(@a, @b, @c); +CALL p2('abc'); +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP USER 'user1'; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_create_table_like.result b/mysql-test/suite/galera/r/galera_create_table_like.result new file mode 100644 index 00000000000..b335101fa62 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_table_like.result @@ -0,0 +1,47 @@ +CREATE SCHEMA schema1; +CREATE SCHEMA schema2; +USE schema1; +CREATE TABLE real_table (f1 INTEGER) ENGINE=InnoDB; +CREATE TEMPORARY TABLE temp_table (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE myisam_table (f1 INTEGER) ENGINE=MyISAM; +USE schema2; +CREATE TABLE real_table1 LIKE schema1.real_table; +CREATE TABLE real_table2 LIKE schema1.temp_table; +CREATE TABLE real_table3 LIKE schema1.myisam_table; +CREATE TEMPORARY TABLE temp_table1 LIKE schema1.real_table; +CREATE TEMPORARY TABLE temp_table2 LIKE schema1.temp_table; +CREATE TEMPORARY TABLE temp_table3 LIKE schema1.myisam_table; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table' AND TABLE_SCHEMA = 'schema1'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'myisam_table' AND TABLE_SCHEMA = 'schema1'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table' AND TABLE_SCHEMA = 'schema1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table1' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table2' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table3' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table1' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table2' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table3' AND TABLE_SCHEMA = 'schema2'; +COUNT(*) = 0 +1 +DROP TABLE schema1.real_table; +DROP TABLE schema1.myisam_table; +DROP TABLE schema2.real_table1; +DROP TABLE schema2.real_table2; +DROP TABLE schema2.real_table3; +DROP SCHEMA schema1; +DROP SCHEMA schema2; diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result new file mode 100644 index 00000000000..4493a5df9ff --- /dev/null +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -0,0 +1,117 @@ +SELECT COUNT(*) = 39 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +COUNT(*) = 39 +1 +SELECT VARIABLE_NAME, VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME NOT IN ( +'WSREP_PROVIDER_OPTIONS', +'WSREP_SST_RECEIVE_ADDRESS', +'WSREP_NODE_ADDRESS', +'WSREP_NODE_NAME', +'WSREP_PROVIDER', +'WSREP_DATA_HOME_DIR', +'WSREP_NODE_INCOMING_ADDRESS', +'WSREP_START_POSITION' +) +ORDER BY VARIABLE_NAME; +VARIABLE_NAME VARIABLE_VALUE +WSREP_AUTO_INCREMENT_CONTROL ON +WSREP_CAUSAL_READS ON +WSREP_CERTIFY_NONPK ON +WSREP_CLUSTER_ADDRESS gcomm:// +WSREP_CLUSTER_NAME my_wsrep_cluster +WSREP_CONVERT_LOCK_TO_TRX OFF +WSREP_DBUG_OPTION +WSREP_DEBUG OFF +WSREP_DESYNC OFF +WSREP_DRUPAL_282555_WORKAROUND OFF +WSREP_FORCED_BINLOG_FORMAT NONE +WSREP_LOAD_DATA_SPLITTING ON +WSREP_LOG_CONFLICTS OFF +WSREP_MAX_WS_ROWS 131072 +WSREP_MAX_WS_SIZE 1073741824 +WSREP_MYSQL_REPLICATION_BUNDLE 0 +WSREP_NOTIFY_CMD +WSREP_ON ON +WSREP_OSU_METHOD TOI +WSREP_RECOVER OFF +WSREP_REPLICATE_MYISAM OFF +WSREP_RESTART_SLAVE OFF +WSREP_RETRY_AUTOCOMMIT 1 +WSREP_SLAVE_FK_CHECKS ON +WSREP_SLAVE_THREADS 1 +WSREP_SLAVE_UK_CHECKS OFF +WSREP_SST_AUTH +WSREP_SST_DONOR +WSREP_SST_DONOR_REJECTS_QUERIES OFF +WSREP_SST_METHOD rsync +WSREP_SYNC_WAIT 7 +; ; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; ; gcache.keep_pages_size = 0; gcache.mem_size = 0; ; gcache.page_size = 128M; gcache.size = 10M; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; gcs.recv_q_hard_limit = 9223372036854775807; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; ; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; ; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = P30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT30S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; +COUNT(*) +57 +SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME != 'wsrep_debug_sync_waiters' +ORDER BY VARIABLE_NAME; +VARIABLE_NAME +WSREP_APPLY_OOOE +WSREP_APPLY_OOOL +WSREP_APPLY_WINDOW +WSREP_CAUSAL_READS +WSREP_CERT_DEPS_DISTANCE +WSREP_CERT_INDEX_SIZE +WSREP_CERT_INTERVAL +WSREP_CLUSTER_CONF_ID +WSREP_CLUSTER_SIZE +WSREP_CLUSTER_STATE_UUID +WSREP_CLUSTER_STATUS +WSREP_COMMIT_OOOE +WSREP_COMMIT_OOOL +WSREP_COMMIT_WINDOW +WSREP_CONNECTED +WSREP_EVS_DELAYED +WSREP_EVS_EVICT_LIST +WSREP_EVS_REPL_LATENCY +WSREP_EVS_STATE +WSREP_FLOW_CONTROL_PAUSED +WSREP_FLOW_CONTROL_PAUSED_NS +WSREP_FLOW_CONTROL_RECV +WSREP_FLOW_CONTROL_SENT +WSREP_GCOMM_UUID +WSREP_INCOMING_ADDRESSES +WSREP_LAST_COMMITTED +WSREP_LOCAL_BF_ABORTS +WSREP_LOCAL_CACHED_DOWNTO +WSREP_LOCAL_CERT_FAILURES +WSREP_LOCAL_COMMITS +WSREP_LOCAL_INDEX +WSREP_LOCAL_RECV_QUEUE +WSREP_LOCAL_RECV_QUEUE_AVG +WSREP_LOCAL_RECV_QUEUE_MAX +WSREP_LOCAL_RECV_QUEUE_MIN +WSREP_LOCAL_REPLAYS +WSREP_LOCAL_SEND_QUEUE +WSREP_LOCAL_SEND_QUEUE_AVG +WSREP_LOCAL_SEND_QUEUE_MAX +WSREP_LOCAL_SEND_QUEUE_MIN +WSREP_LOCAL_STATE +WSREP_LOCAL_STATE_COMMENT +WSREP_LOCAL_STATE_UUID +WSREP_PROTOCOL_VERSION +WSREP_PROVIDER_NAME +WSREP_PROVIDER_VENDOR +WSREP_PROVIDER_VERSION +WSREP_READY +WSREP_RECEIVED +WSREP_RECEIVED_BYTES +WSREP_REPLICATED +WSREP_REPLICATED_BYTES +WSREP_REPL_DATA_BYTES +WSREP_REPL_KEYS +WSREP_REPL_KEYS_BYTES +WSREP_REPL_OTHER_BYTES +WSREP_THREAD_COUNT diff --git a/mysql-test/suite/galera/r/galera_delete_limit.result b/mysql-test/suite/galera/r/galera_delete_limit.result new file mode 100644 index 00000000000..72bee18eab6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_delete_limit.result @@ -0,0 +1,19 @@ +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) Engine=InnoDB; +INSERT INTO t1 SELECT f1 FROM ten ORDER BY RAND(); +DELETE FROM t1 ORDER BY RAND() LIMIT 5; +sum_matches +1 +max_matches +1 +DROP TABLE t1; +CREATE TABLE t2 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t2 SELECT f1 FROM ten ORDER BY RAND(); +DELETE FROM t2 ORDER BY RAND() LIMIT 5; +sum_matches +1 +max_matches +1 +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_enum.result b/mysql-test/suite/galera/r/galera_enum.result new file mode 100644 index 00000000000..e853c5c9943 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_enum.result @@ -0,0 +1,37 @@ +CREATE TABLE t1 (f1 ENUM('', 'one', 'two'), KEY (f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (''); +INSERT INTO t1 VALUES ('one'), ('two'); +INSERT INTO t1 VALUES (0), (1), (2); +Warnings: +Warning 1265 Data truncated for column 'f1' at row 1 +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 2 FROM t1 where f1 = ''; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1 where f1 = 'one'; +COUNT(*) = 2 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (''), ('one'), ('two'); +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; +COUNT(*) = 1 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'three' where f1 = ''; +SET AUTOCOMMIt=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'four' where f1 = ''; +COMMIT; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_events.result b/mysql-test/suite/galera/r/galera_events.result new file mode 100644 index 00000000000..09d8406d5d0 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_events.result @@ -0,0 +1,18 @@ +CREATE EVENT event1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO SELECT 1; +SELECT DEFINER= 'root@localhost', ORIGINATOR = 1, STATUS = 'SLAVESIDE_DISABLED', EVENT_TYPE = 'ONE TIME', ON_COMPLETION = 'NOT PRESERVE' FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; +DEFINER= 'root@localhost' ORIGINATOR = 1 STATUS = 'SLAVESIDE_DISABLED' EVENT_TYPE = 'ONE TIME' ON_COMPLETION = 'NOT PRESERVE' +1 1 1 1 1 +ALTER EVENT event1 DISABLE; +SELECT DEFINER= 'root@localhost', ORIGINATOR = 1, STATUS = 'SLAVESIDE_DISABLED', EVENT_TYPE = 'ONE TIME', ON_COMPLETION = 'NOT PRESERVE' FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; +DEFINER= 'root@localhost' ORIGINATOR = 1 STATUS = 'SLAVESIDE_DISABLED' EVENT_TYPE = 'ONE TIME' ON_COMPLETION = 'NOT PRESERVE' +1 1 1 1 1 +SET GLOBAL event_scheduler = ON; +CREATE EVENT event2 ON SCHEDULE AT CURRENT_TIMESTAMP ON COMPLETION NOT PRESERVE DO SELECT 1; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event2'; +COUNT(*) = 0 +1 +DROP EVENT event1; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; +COUNT(*) = 0 +1 +SET GLOBAL event_scheduler = OFF;; diff --git a/mysql-test/suite/galera/r/galera_fk_multicolumn.result b/mysql-test/suite/galera/r/galera_fk_multicolumn.result index 62ec9f85cd4..a86b87a83ef 100644 --- a/mysql-test/suite/galera/r/galera_fk_multicolumn.result +++ b/mysql-test/suite/galera/r/galera_fk_multicolumn.result @@ -1,19 +1,19 @@ CREATE TABLE t0 ( f1 INT PRIMARY KEY, f2 INT UNIQUE -) ENGINE=INNODB; +); CREATE TABLE t1 ( f1 INT PRIMARY KEY, FOREIGN KEY (f1) REFERENCES t0(f1) ON UPDATE CASCADE -) ENGINE=INNODB; +); CREATE TABLE t2 ( f2 INT PRIMARY KEY, FOREIGN KEY (f2) REFERENCES t0(f2) ON UPDATE CASCADE -) ENGINE=INNODB; +); INSERT INTO t0 VALUES (0, 0); INSERT INTO t1 VALUES (0); INSERT INTO t2 VALUES (0); diff --git a/mysql-test/suite/galera/r/galera_fk_multitable.result b/mysql-test/suite/galera/r/galera_fk_multitable.result index 410565eb0ed..e77128d3b04 100644 --- a/mysql-test/suite/galera/r/galera_fk_multitable.result +++ b/mysql-test/suite/galera/r/galera_fk_multitable.result @@ -1,13 +1,13 @@ CREATE TABLE t0 ( f0 INT PRIMARY KEY -) ENGINE=INNODB; +); CREATE TABLE t1 ( f1 INT PRIMARY KEY, f0 INTEGER, FOREIGN KEY (f0) REFERENCES t0(f0) ON DELETE CASCADE -) ENGINE=INNODB; +); INSERT INTO t0 VALUES (0), (1); INSERT INTO t1 VALUES (0, 0); INSERT INTO t1 VALUES (1, 0); diff --git a/mysql-test/suite/galera/r/galera_flush.result b/mysql-test/suite/galera/r/galera_flush.result index 7636a30fced..68266439414 100644 --- a/mysql-test/suite/galera/r/galera_flush.result +++ b/mysql-test/suite/galera/r/galera_flush.result @@ -5,7 +5,7 @@ FLUSH HOSTS; wsrep_last_committed_diff 1 SET GLOBAL wsrep_replicate_myisam = TRUE; -INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); +INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N','N'); FLUSH PRIVILEGES; DELETE FROM mysql.user WHERE user = 'user1'; SET GLOBAL wsrep_replicate_myisam = FALSE; diff --git a/mysql-test/suite/galera/r/galera_ftwrl.result b/mysql-test/suite/galera/r/galera_ftwrl.result new file mode 100644 index 00000000000..c216b52650b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ftwrl.result @@ -0,0 +1,16 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +FLUSH TABLES WITH READ LOCK; +INSERT INTO t1 VALUES (1); +SHOW TABLES; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UNLOCK TABLES; +SHOW TABLES; +Tables_in_test +t1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result new file mode 100644 index 00000000000..72577695202 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_fulltext.result @@ -0,0 +1,26 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; +SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%'; +COUNT(*) = 13 +1 +INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz'); +COUNT(f2) = 10000 +1 +UPDATE t1 SET f2 = 'abcdefjhk'; +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk'); +COUNT(f2) = 10000 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB; +INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz'); +COUNT(f1) = 1000 +1 +UPDATE t1 SET f1 = 'abcdefjhk'; +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk'); +COUNT(f1) = 1000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result new file mode 100644 index 00000000000..99c710f25a5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; +FLUSH TABLES WITH READ LOCK; +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'query end' AND INFO = 'INSERT INTO t1 VALUES (5)'; +COUNT(*) = 1 +1 +UNLOCK TABLES; +INSERT INTO t1 VALUES (6); +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +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 new file mode 100644 index 00000000000..606cb549def --- /dev/null +++ b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result @@ -0,0 +1,15 @@ +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; +CREATE TABLE t2 (f1 VARCHAR(512) UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +INSERT INTO t2 VALUES (REPEAT('x', 512)); +SELECT COUNT(*) = 10000 FROM t1; +COUNT(*) = 10000 +1 +SELECT LENGTH(f1) = 512 FROM t2 WHERE f1 = REPEAT('x', 512); +LENGTH(f1) = 512 +1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_gtid.result b/mysql-test/suite/galera/r/galera_gtid.result new file mode 100644 index 00000000000..546c29cb49a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_gtid.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 2; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +gtid_binlog_state_equal +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_insert_ignore.result b/mysql-test/suite/galera/r/galera_insert_ignore.result new file mode 100644 index 00000000000..b53b5795416 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_insert_ignore.result @@ -0,0 +1,52 @@ +SET GLOBAL wsrep_sync_wait = 7; +SET GLOBAL wsrep_sync_wait = 7; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1), (2); +Warnings: +Warning 1062 Duplicate entry '1' for key 'PRIMARY' +SELECT * FROM t1; +f1 +1 +2 +SELECT * FROM t1; +f1 +1 +2 +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (0), (2), (3); +INSERT IGNORE INTO t1 SELECT f1 FROM t2; +Warnings: +Warning 1062 Duplicate entry '2' for key 'PRIMARY' +SELECT * FROM t1; +f1 +0 +1 +2 +3 +SELECT * FROM t1; +f1 +0 +1 +2 +3 +CREATE TABLE t3 (f1 INTEGER UNIQUE) Engine=InnoDB; +INSERT INTO t3 VALUES (NULL); +INSERT IGNORE INTO t3 VALUES (1), (NULL), (2); +SELECT * FROM t3; +f1 +NULL +NULL +1 +2 +SELECT * FROM t3; +f1 +NULL +NULL +1 +2 +SET GLOBAL wsrep_sync_wait = (SELECT @@wsrep_sync_wait); +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +SET GLOBAL wsrep_sync_wait = (SELECT @@wsrep_sync_wait); diff --git a/mysql-test/suite/galera/r/galera_insert_multi.result b/mysql-test/suite/galera/r/galera_insert_multi.result new file mode 100644 index 00000000000..33717781f2c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_insert_multi.result @@ -0,0 +1,58 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t1 VALUES (3),(4); +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER, KEY (f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(1); +INSERT INTO t1 VALUES (2),(2); +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +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), (1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT = OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2); +SET AUTOCOMMIT = OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); +COMMIT; +COMMIT; +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' +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2); +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); +ROLLBACK; +COMMIT; +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..5421b234ee1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result @@ -0,0 +1,184 @@ +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_ist_mysqldump.result b/mysql-test/suite/galera/r/galera_ist_mysqldump.result new file mode 100644 index 00000000000..4b5a8fe948a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mysqldump.result @@ -0,0 +1,284 @@ +Setting SST method to mysqldump ... +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:sst'; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +DROP USER sst; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); +CALL mtr.add_suppression("InnoDB: New log files created"); +CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +CALL mtr.add_suppression("Can't open and lock time zone table"); +CALL mtr.add_suppression("Can't open and lock privilege tables"); +CALL mtr.add_suppression("Info table is not ready to be used"); +CALL mtr.add_suppression("Native table .* has the wrong structure"); diff --git a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result new file mode 100644 index 00000000000..f7a1386e7f8 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result @@ -0,0 +1,43 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'a'),(6, 'a'); +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +UPDATE t1 SET f2 = 'b' WHERE f1 > 1; +UPDATE t1 SET f2 = 'c' WHERE f1 > 2; +SET GLOBAL wsrep_provider_options = 'dbug=d,recv_IST_after_apply_trx'; +SET SESSION wsrep_sync_wait = 0; +Loading wsrep_provider ... +SHOW STATUS LIKE 'wsrep_debug_sync_waiters'; +Variable_name Value +wsrep_debug_sync_waiters recv_IST_after_apply_trx +UPDATE t1 SET f2 = 'd' WHERE f1 > 3; +CREATE TABLE t2 (f1 INTEGER); +UPDATE t1 SET f2 = 'e' WHERE f1 > 4; +CREATE TABLE t3 (f1 INTEGER); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +UPDATE t1 SET f2 = 'f' WHERE f1 > 5; +SELECT * FROM t1; +f1 f2 +1 a +2 b +3 c +4 d +5 e +6 f +SELECT * FROM t1; +f1 f2 +1 a +2 b +3 c +4 d +5 e +6 f +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t3; +COUNT(*) = 0 +1 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera/r/galera_ist_rsync.result b/mysql-test/suite/galera/r/galera_ist_rsync.result new file mode 100644 index 00000000000..175e7443a4d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_rsync.result @@ -0,0 +1,357 @@ +Performing State Transfer on a server that has been temporarily disconnected +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Loading wsrep provider ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result new file mode 100644 index 00000000000..175e7443a4d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result @@ -0,0 +1,357 @@ +Performing State Transfer on a server that has been temporarily disconnected +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Loading wsrep provider ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_kill_ddl.result b/mysql-test/suite/galera/r/galera_kill_ddl.result new file mode 100644 index 00000000000..8dd36497dfb --- /dev/null +++ b/mysql-test/suite/galera/r/galera_kill_ddl.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +Killing server ... +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +COUNT(*) = 2 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result new file mode 100644 index 00000000000..a37056ad9b0 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_kill_largechanges.result @@ -0,0 +1,14 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 VARCHAR(128)) ENGINE=InnoDB; +Killing server ... +INSERT INTO t1 SELECT REPEAT('a', 128) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6; +SELECT COUNT(*) = 1000000 FROM t1; +COUNT(*) = 1000000 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_kill_nochanges.result b/mysql-test/suite/galera/r/galera_kill_nochanges.result new file mode 100644 index 00000000000..db3c75e2886 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_kill_nochanges.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +Killing server ... +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result new file mode 100644 index 00000000000..8409740a035 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_kill_smallchanges.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +Killing server ... +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_lock_table.result b/mysql-test/suite/galera/r/galera_lock_table.result new file mode 100644 index 00000000000..16e9037a4de --- /dev/null +++ b/mysql-test/suite/galera/r/galera_lock_table.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; +LOCK TABLE t1 READ; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +SET SESSION wsrep_sync_wait=0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +UNLOCK TABLES; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_log_bin.result b/mysql-test/suite/galera/r/galera_log_bin.result new file mode 100644 index 00000000000..845326e6912 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_log_bin.result @@ -0,0 +1,58 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (id INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +FLUSH LOGS; +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' LIMIT 4,18; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 353 Gtid 1 391 GTID 0-1-1 +mysqld-bin.000002 391 Query 1 504 use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB +mysqld-bin.000002 504 Gtid 1 542 BEGIN GTID 0-1-2 +mysqld-bin.000002 542 Table_map 1 583 table_id: 100 (test.t1) +mysqld-bin.000002 583 Write_rows_v1 1 617 table_id: 100 flags: STMT_END_F +mysqld-bin.000002 617 Xid 1 644 COMMIT /* xid=2 */ +mysqld-bin.000002 644 Gtid 1 682 GTID 0-1-3 +mysqld-bin.000002 682 Query 1 783 use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB +mysqld-bin.000002 783 Gtid 1 821 BEGIN GTID 0-1-4 +mysqld-bin.000002 821 Table_map 1 862 table_id: 101 (test.t2) +mysqld-bin.000002 862 Write_rows_v1 1 896 table_id: 101 flags: STMT_END_F +mysqld-bin.000002 896 Xid 1 923 COMMIT /* xid=4 */ +mysqld-bin.000002 923 Gtid 1 961 BEGIN GTID 0-1-5 +mysqld-bin.000002 961 Table_map 1 1002 table_id: 101 (test.t2) +mysqld-bin.000002 1002 Write_rows_v1 1 1036 table_id: 101 flags: STMT_END_F +mysqld-bin.000002 1036 Xid 1 1063 COMMIT /* xid=5 */ +mysqld-bin.000002 1063 Gtid 1 1101 GTID 0-1-6 +mysqld-bin.000002 1101 Query 1 1200 use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' LIMIT 3,19; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 313 Gtid 1 351 GTID 0-1-1 +mysqld-bin.000003 351 Query 1 464 use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB +mysqld-bin.000003 464 Gtid 1 502 BEGIN GTID 0-1-2 +mysqld-bin.000003 502 Table_map 1 543 table_id: 82 (test.t1) +mysqld-bin.000003 543 Write_rows_v1 1 577 table_id: 82 flags: STMT_END_F +mysqld-bin.000003 577 Xid 1 604 COMMIT /* xid=2 */ +mysqld-bin.000003 604 Gtid 1 642 GTID 0-1-3 +mysqld-bin.000003 642 Query 1 743 use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB +mysqld-bin.000003 743 Gtid 1 781 BEGIN GTID 0-1-4 +mysqld-bin.000003 781 Table_map 1 822 table_id: 83 (test.t2) +mysqld-bin.000003 822 Write_rows_v1 1 856 table_id: 83 flags: STMT_END_F +mysqld-bin.000003 856 Xid 1 883 COMMIT /* xid=4 */ +mysqld-bin.000003 883 Gtid 1 921 BEGIN GTID 0-1-5 +mysqld-bin.000003 921 Table_map 1 962 table_id: 83 (test.t2) +mysqld-bin.000003 962 Write_rows_v1 1 996 table_id: 83 flags: STMT_END_F +mysqld-bin.000003 996 Xid 1 1023 COMMIT /* xid=5 */ +mysqld-bin.000003 1023 Gtid 1 1061 GTID 0-1-6 +mysqld-bin.000003 1061 Query 1 1160 use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_log_output_csv.result b/mysql-test/suite/galera/r/galera_log_output_csv.result new file mode 100644 index 00000000000..07a78469578 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_log_output_csv.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) > 0 FROM mysql.general_log; +COUNT(*) > 0 +1 +SELECT 1 = 1 FROM t1; +1 = 1 +1 +SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 1 = 1 FROM t1'; +COUNT(*) = 1 +1 +SELECT COUNT(*) > 0 FROM mysql.general_log WHERE argument = 'CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB'; +COUNT(*) > 0 +1 +SELECT 2 = 2 FROM t1; +2 = 2 +1 +SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 2 = 2 FROM t1'; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_many_columns.result b/mysql-test/suite/galera/r/galera_many_columns.result index ba7b9116e7c..6fa574e47c2 100644 --- a/mysql-test/suite/galera/r/galera_many_columns.result +++ b/mysql-test/suite/galera/r/galera_many_columns.result @@ -1,1021 +1,3 @@ -CREATE TABLE t1 (f1017 VARCHAR(3) DEFAULT 'ABC') ENGINE=InnoDB; -ALTER TABLE t1 ADD COLUMN f1016 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1015 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1014 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1013 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1012 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1011 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1010 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1009 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1008 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1007 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1006 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1005 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1004 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1003 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1002 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1001 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1000 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f999 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f998 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f997 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f996 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f995 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f994 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f993 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f992 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f991 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f990 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f989 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f988 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f987 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f986 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f985 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f984 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f983 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f982 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f981 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f980 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f979 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f978 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f977 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f976 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f975 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f974 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f973 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f972 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f971 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f970 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f969 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f968 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f967 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f966 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f965 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f964 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f963 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f962 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f961 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f960 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f959 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f958 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f957 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f956 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f955 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f954 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f953 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f952 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f951 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f950 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f949 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f948 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f947 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f946 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f945 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f944 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f943 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f942 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f941 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f940 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f939 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f938 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f937 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f936 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f935 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f934 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f933 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f932 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f931 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f930 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f929 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f928 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f927 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f926 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f925 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f924 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f923 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f922 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f921 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f920 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f919 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f918 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f917 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f916 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f915 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f914 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f913 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f912 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f911 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f910 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f909 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f908 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f907 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f906 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f905 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f904 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f903 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f902 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f901 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f900 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f899 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f898 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f897 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f896 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f895 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f894 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f893 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f892 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f891 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f890 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f889 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f888 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f887 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f886 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f885 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f884 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f883 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f882 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f881 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f880 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f879 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f878 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f877 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f876 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f875 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f874 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f873 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f872 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f871 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f870 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f869 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f868 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f867 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f866 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f865 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f864 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f863 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f862 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f861 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f860 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f859 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f858 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f857 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f856 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f855 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f854 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f853 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f852 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f851 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f850 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f849 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f848 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f847 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f846 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f845 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f844 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f843 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f842 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f841 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f840 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f839 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f838 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f837 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f836 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f835 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f834 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f833 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f832 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f831 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f830 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f829 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f828 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f827 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f826 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f825 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f824 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f823 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f822 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f821 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f820 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f819 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f818 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f817 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f816 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f815 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f814 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f813 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f812 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f811 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f810 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f809 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f808 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f807 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f806 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f805 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f804 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f803 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f802 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f801 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f800 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f799 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f798 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f797 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f796 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f795 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f794 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f793 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f792 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f791 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f790 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f789 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f788 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f787 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f786 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f785 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f784 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f783 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f782 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f781 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f780 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f779 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f778 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f777 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f776 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f775 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f774 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f773 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f772 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f771 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f770 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f769 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f768 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f767 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f766 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f765 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f764 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f763 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f762 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f761 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f760 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f759 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f758 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f757 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f756 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f755 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f754 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f753 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f752 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f751 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f750 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f749 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f748 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f747 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f746 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f745 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f744 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f743 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f742 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f741 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f740 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f739 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f738 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f737 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f736 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f735 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f734 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f733 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f732 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f731 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f730 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f729 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f728 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f727 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f726 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f725 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f724 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f723 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f722 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f721 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f720 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f719 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f718 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f717 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f716 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f715 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f714 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f713 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f712 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f711 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f710 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f709 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f708 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f707 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f706 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f705 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f704 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f703 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f702 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f701 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f700 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f699 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f698 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f697 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f696 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f695 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f694 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f693 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f692 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f691 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f690 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f689 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f688 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f687 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f686 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f685 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f684 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f683 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f682 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f681 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f680 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f679 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f678 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f677 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f676 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f675 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f674 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f673 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f672 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f671 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f670 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f669 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f668 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f667 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f666 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f665 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f664 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f663 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f662 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f661 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f660 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f659 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f658 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f657 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f656 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f655 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f654 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f653 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f652 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f651 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f650 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f649 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f648 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f647 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f646 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f645 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f644 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f643 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f642 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f641 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f640 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f639 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f638 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f637 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f636 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f635 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f634 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f633 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f632 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f631 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f630 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f629 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f628 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f627 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f626 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f625 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f624 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f623 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f622 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f621 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f620 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f619 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f618 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f617 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f616 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f615 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f614 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f613 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f612 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f611 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f610 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f609 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f608 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f607 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f606 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f605 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f604 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f603 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f602 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f601 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f600 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f599 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f598 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f597 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f596 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f595 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f594 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f593 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f592 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f591 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f590 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f589 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f588 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f587 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f586 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f585 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f584 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f583 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f582 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f581 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f580 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f579 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f578 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f577 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f576 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f575 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f574 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f573 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f572 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f571 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f570 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f569 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f568 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f567 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f566 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f565 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f564 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f563 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f562 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f561 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f560 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f559 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f558 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f557 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f556 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f555 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f554 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f553 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f552 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f551 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f550 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f549 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f548 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f547 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f546 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f545 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f544 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f543 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f542 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f541 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f540 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f539 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f538 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f537 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f536 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f535 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f534 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f533 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f532 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f531 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f530 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f529 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f528 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f527 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f526 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f525 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f524 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f523 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f522 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f521 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f520 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f519 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f518 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f517 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f516 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f515 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f514 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f513 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f512 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f511 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f510 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f509 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f508 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f507 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f506 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f505 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f504 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f503 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f502 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f501 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f500 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f499 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f498 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f497 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f496 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f495 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f494 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f493 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f492 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f491 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f490 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f489 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f488 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f487 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f486 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f485 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f484 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f483 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f482 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f481 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f480 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f479 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f478 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f477 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f476 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f475 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f474 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f473 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f472 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f471 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f470 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f469 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f468 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f467 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f466 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f465 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f464 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f463 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f462 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f461 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f460 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f459 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f458 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f457 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f456 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f455 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f454 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f453 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f452 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f451 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f450 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f449 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f448 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f447 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f446 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f445 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f444 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f443 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f442 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f441 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f440 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f439 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f438 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f437 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f436 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f435 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f434 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f433 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f432 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f431 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f430 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f429 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f428 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f427 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f426 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f425 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f424 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f423 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f422 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f421 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f420 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f419 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f418 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f417 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f416 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f415 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f414 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f413 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f412 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f411 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f410 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f409 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f408 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f407 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f406 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f405 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f404 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f403 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f402 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f401 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f400 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f399 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f398 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f397 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f396 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f395 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f394 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f393 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f392 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f391 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f390 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f389 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f388 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f387 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f386 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f385 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f384 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f383 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f382 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f381 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f380 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f379 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f378 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f377 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f376 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f375 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f374 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f373 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f372 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f371 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f370 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f369 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f368 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f367 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f366 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f365 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f364 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f363 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f362 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f361 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f360 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f359 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f358 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f357 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f356 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f355 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f354 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f353 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f352 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f351 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f350 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f349 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f348 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f347 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f346 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f345 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f344 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f343 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f342 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f341 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f340 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f339 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f338 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f337 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f336 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f335 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f334 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f333 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f332 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f331 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f330 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f329 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f328 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f327 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f326 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f325 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f324 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f323 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f322 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f321 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f320 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f319 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f318 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f317 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f316 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f315 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f314 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f313 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f312 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f311 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f310 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f309 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f308 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f307 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f306 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f305 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f304 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f303 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f302 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f301 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f300 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f299 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f298 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f297 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f296 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f295 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f294 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f293 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f292 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f291 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f290 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f289 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f288 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f287 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f286 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f285 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f284 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f283 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f282 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f281 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f280 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f279 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f278 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f277 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f276 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f275 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f274 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f273 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f272 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f271 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f270 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f269 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f268 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f267 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f266 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f265 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f264 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f263 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f262 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f261 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f260 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f259 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f258 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f257 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f256 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f255 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f254 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f253 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f252 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f251 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f250 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f249 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f248 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f247 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f246 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f245 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f244 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f243 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f242 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f241 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f240 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f239 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f238 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f237 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f236 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f235 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f234 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f233 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f232 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f231 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f230 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f229 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f228 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f227 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f226 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f225 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f224 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f223 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f222 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f221 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f220 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f219 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f218 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f217 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f216 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f215 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f214 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f213 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f212 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f211 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f210 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f209 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f208 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f207 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f206 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f205 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f204 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f203 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f202 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f201 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f200 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f199 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f198 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f197 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f196 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f195 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f194 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f193 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f192 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f191 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f190 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f189 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f188 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f187 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f186 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f185 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f184 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f183 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f182 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f181 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f180 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f179 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f178 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f177 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f176 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f175 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f174 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f173 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f172 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f171 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f170 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f169 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f168 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f167 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f166 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f165 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f164 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f163 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f162 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f161 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f160 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f159 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f158 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f157 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f156 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f155 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f154 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f153 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f152 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f151 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f150 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f149 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f148 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f147 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f146 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f145 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f144 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f143 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f142 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f141 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f140 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f139 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f138 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f137 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f136 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f135 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f134 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f133 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f132 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f131 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f130 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f129 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f128 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f127 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f126 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f125 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f124 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f123 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f122 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f121 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f120 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f119 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f118 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f117 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f116 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f115 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f114 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f113 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f112 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f111 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f110 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f109 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f108 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f107 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f106 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f105 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f104 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f103 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f102 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f101 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f100 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f99 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f98 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f97 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f96 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f95 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f94 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f93 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f92 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f91 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f90 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f89 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f88 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f87 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f86 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f85 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f84 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f83 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f82 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f81 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f80 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f79 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f78 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f77 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f76 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f75 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f74 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f73 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f72 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f71 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f70 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f69 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f68 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f67 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f66 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f65 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f64 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f63 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f62 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f61 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f60 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f59 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f58 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f57 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f56 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f55 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f54 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f53 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f52 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f51 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f50 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f49 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f48 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f47 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f46 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f45 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f44 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f43 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f42 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f41 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f40 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f39 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f38 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f37 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f36 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f35 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f34 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f33 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f32 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f31 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f30 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f29 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f28 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f27 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f26 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f25 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f24 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f23 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f22 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f21 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f20 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f19 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f18 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f17 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f16 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f15 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f14 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f13 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f12 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f11 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f10 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f9 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f8 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f7 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f6 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f5 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f4 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f3 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f2 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD COLUMN f1 VARCHAR(3) DEFAULT 'ABC'; -ALTER TABLE t1 ADD PRIMARY KEY (f1, f1017); INSERT INTO t1 (f1) VALUES (DEFAULT); SELECT f1 = 'ABC', f1017 = 'ABC' FROM t1; f1 = 'ABC' f1017 = 'ABC' diff --git a/mysql-test/suite/galera/r/galera_many_rows.result b/mysql-test/suite/galera/r/galera_many_rows.result index fdcec573030..6ec0add8ba8 100644 --- a/mysql-test/suite/galera/r/galera_many_rows.result +++ b/mysql-test/suite/galera/r/galera_many_rows.result @@ -1,4 +1,4 @@ -CREATE TABLE ten (f1 INTEGER) ENGINE=INNODB; +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; INSERT INTO t1 (f2) SELECT a1.f1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; diff --git a/mysql-test/suite/galera/r/galera_many_tables_nopk.result b/mysql-test/suite/galera/r/galera_many_tables_nopk.result new file mode 100644 index 00000000000..7a4f364730c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_many_tables_nopk.result @@ -0,0 +1,17 @@ +SET AUTOCOMMIT=OFF; +START TRANSACTION; +COMMIT; +CREATE TABLE sum_table (f1 INTEGER); +SELECT SUM(f1) = 1000 FROM sum_table; +SUM(f1) = 1000 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1000 SET f1 = 3; +COMMIT; +COMMIT; +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 new file mode 100644 index 00000000000..6b6899d979d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_many_tables_pk.result @@ -0,0 +1,20 @@ +SELECT COUNT(*) = 1000 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%'; +COUNT(*) = 1000 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +COMMIT; +CREATE TABLE sum_table (f1 INTEGER); +SELECT SUM(f1) = 1000 FROM sum_table; +SUM(f1) = 1000 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1000 SET f1 = 3; +COMMIT; +COMMIT; +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_migrate.result b/mysql-test/suite/galera/r/galera_migrate.result new file mode 100644 index 00000000000..7c92d66ff97 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_migrate.result @@ -0,0 +1,79 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +INSERT INTO t1 VALUES (2); +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +SET GLOBAL wsrep_cluster_address='gcomm://'; +INSERT INTO t1 VALUES (5); +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 1 +1 +INSERT INTO t1 VALUES (6); +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:sst'; +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +STOP SLAVE; +RESET SLAVE ALL; +STOP SLAVE; +RESET SLAVE ALL; +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +SELECT COUNT(*) = 8 FROM t1; +COUNT(*) = 8 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT COUNT(*) = 8 FROM t1; +COUNT(*) = 8 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; +DROP TABLE t1; +SET GLOBAL wsrep_provider = 'none'; +SET GLOBAL wsrep_sst_auth = ''; +SET GLOBAL wsrep_provider_options = ''; +DROP TABLE t1; +DROP USER sst; +SET GLOBAL wsrep_provider = 'none'; +SET GLOBAL wsrep_sst_method = 'rsync'; +SET GLOBAL wsrep_provider_options = ''; +SET GLOBAL wsrep_sst_receive_address = 'AUTO'; +DROP TABLE t1; +DROP USER sst; +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); diff --git a/mysql-test/suite/galera/r/galera_multi_database.result b/mysql-test/suite/galera/r/galera_multi_database.result new file mode 100644 index 00000000000..a04eb484caf --- /dev/null +++ b/mysql-test/suite/galera/r/galera_multi_database.result @@ -0,0 +1,28 @@ +CREATE DATABASE d1; +CREATE TABLE d1.t1(f1 INTEGER) ENGINE=InnoDB; +CREATE DATABASE d2; +CREATE TABLE d2.t1(f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO d1.t1 VALUES (1); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO d2.t1 VALUES (1); +COMMIT; +COMMIT; +SELECT COUNT(*) = 1 FROM d1.t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM d2.t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM d1.t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM d2.t1; +COUNT(*) = 1 +1 +DROP TABLE d1.t1; +DROP TABLE d2.t1; +DROP DATABASE d1; +DROP DATABASE d2; diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result new file mode 100644 index 00000000000..3f8d93bae76 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result @@ -0,0 +1,24 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2), (3); +INSERT INTO t1 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2), (3); +INSERT INTO t2 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; +INSERT INTO t2 VALUES (6), (1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +UPDATE t1 SET f1 = 9; +UPDATE t2 SET f1 = 9 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 9; +DELETE FROM t2 WHERE f1 = 9; +TRUNCATE TABLE t1; +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_myisam_transactions.result b/mysql-test/suite/galera/r/galera_myisam_transactions.result new file mode 100644 index 00000000000..284f92b414c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_myisam_transactions.result @@ -0,0 +1,34 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t3 (f1 INTEGER) ENGINE=MyISAM; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (NEW.f1); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +COMMIT; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera/r/galera_nopk_unicode.result b/mysql-test/suite/galera/r/galera_nopk_unicode.result new file mode 100644 index 00000000000..68d049a2146 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_nopk_unicode.result @@ -0,0 +1,24 @@ +CREATE TABLE t1 ( +f1 VARCHAR(255), +KEY (f1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('текÑÑ‚'); +SELECT f1 = 'текÑÑ‚' FROM t1; +f1 = 'текÑÑ‚' +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚2'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚3'; +COMMIT; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT f1 = 'текÑÑ‚2' FROM t1; +f1 = 'текÑÑ‚2' +1 +SELECT f1 = 'текÑÑ‚2' FROM t1 WHERE f1 = 'текÑÑ‚2'; +f1 = 'текÑÑ‚2' +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..b9718026828 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result @@ -0,0 +1,33 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL wsrep_slave_threads = 2; +LOCK TABLE t1 READ; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +SET SESSION wsrep_sync_wait=0; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table level lock%'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +UNLOCK TABLES; +SET SESSION wsrep_sync_wait = 7;; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'closing tables'; +COUNT(*) = 2 +1 +SET GLOBAL wsrep_slave_threads = 1;; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result new file mode 100644 index 00000000000..1f163f4366c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result @@ -0,0 +1,18 @@ +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 GLOBAL wsrep_slave_threads = 4; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +SELECT COUNT(*) = 30000 FROM t1; +COUNT(*) = 30000 +1 +SELECT COUNT(DISTINCT f1) = 30000 FROM t1; +COUNT(DISTINCT f1) = 30000 +1 +SELECT COUNT(*) = 5 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = 5 +1 +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 new file mode 100644 index 00000000000..d7ee754f695 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result @@ -0,0 +1,15 @@ +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 GLOBAL wsrep_slave_threads = 4; +SELECT COUNT(*) = 20000 FROM t1; +COUNT(*) = 20000 +1 +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 'closing tables'; +COUNT(*) = 4 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_parallel_simple.result b/mysql-test/suite/galera/r/galera_parallel_simple.result new file mode 100644 index 00000000000..880d4e8ae3d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_parallel_simple.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 (id INT) ENGINE=InnoDB; +CREATE TABLE t2 (id INT) ENGINE=InnoDB; +SET GLOBAL wsrep_slave_threads = 2; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 6 FROM t2; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'closing tables'; +COUNT(*) = 2 +1 +SET GLOBAL wsrep_slave_threads = 1;; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_pc_ignore_sb.result b/mysql-test/suite/galera/r/galera_pc_ignore_sb.result new file mode 100644 index 00000000000..5fcccfe2d59 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_pc_ignore_sb.result @@ -0,0 +1,12 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +Killing server ... +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 1 +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SET GLOBAL wsrep_cluster_address = ''; diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result new file mode 100644 index 00000000000..a3075994657 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 BIGINT SIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(-9223372036854775808, 'min'), +(9223372036854775807, 'max') +; +SELECT * FROM t1; +f1 f2 +-9223372036854775808 min +9223372036854775807 max +UPDATE t1 SET f2 = CONCAT(f2, '_'); +SELECT * FROM t1; +f1 f2 +-9223372036854775808 min_ +9223372036854775807 max_ +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'foo' WHERE f1 = -9223372036854775808; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'bar' WHERE f1 = -9223372036854775808; +COMMIT; +SET AUTOCOMMIT=ON; +COMMIT; +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 new file mode 100644 index 00000000000..441926e949c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 (f1 BIGINT UNSIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(18446744073709551615, 'max') +; +SELECT f1 = 18446744073709551615 FROM t1; +f1 = 18446744073709551615 +1 +UPDATE t1 SET f2 = CONCAT(f2, '_'); +SELECT f1 = 18446744073709551615 FROM t1; +f1 = 18446744073709551615 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'foo' WHERE f1 = 18446744073709551615; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'bar' WHERE f1 = 18446744073709551615; +COMMIT; +SET AUTOCOMMIT=ON; +COMMIT; +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_query_cache.result b/mysql-test/suite/galera/r/galera_query_cache.result new file mode 100644 index 00000000000..502d8a58e9c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_query_cache.result @@ -0,0 +1,57 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +RESET QUERY CACHE; +FLUSH STATUS; +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +VARIABLE_VALUE = 1 +1 +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 +INSERT INTO t1 VALUES (2); +FLUSH STATUS; +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +VARIABLE_VALUE = 0 +1 +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +VARIABLE_VALUE = 1 +1 +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 0 +1 +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +FLUSH STATUS; +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +VARIABLE_VALUE = 0 +1 +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +VARIABLE_VALUE = 1 +1 +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 0 +1 +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_read_only.result b/mysql-test/suite/galera/r/galera_read_only.result new file mode 100644 index 00000000000..d2af3867fe7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_read_only.result @@ -0,0 +1,8 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL read_only=TRUE; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET GLOBAL read_only=FALSE; +DROP TABLE t1; 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 new file mode 100644 index 00000000000..4acf0143f8b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result @@ -0,0 +1,18 @@ +SET GLOBAL wsrep_provider_options = 'repl.key_format=FLAT16'; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (123); +CREATE TABLE t2 (f1 VARCHAR(256)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (REPEAT('a', 256)); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 234; +UPDATE t2 SET f1 = REPEAT('b', 256); +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 234; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = REPEAT('b', 256); +COUNT(*) = 1 +1 +DROP TABLE t1; +DROP TABLE t2; 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 new file mode 100644 index 00000000000..6cfd10bdedd --- /dev/null +++ b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result @@ -0,0 +1,8 @@ +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 5 "Input/output error" during COMMIT +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_restart_nochanges.result b/mysql-test/suite/galera/r/galera_restart_nochanges.result new file mode 100644 index 00000000000..accace97826 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_restart_nochanges.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_rsu_add_pk.result b/mysql-test/suite/galera/r/galera_rsu_add_pk.result new file mode 100644 index 00000000000..3fd24af9ad7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_rsu_add_pk.result @@ -0,0 +1,26 @@ +CREATE TABLE ten (f1 INTEGER); +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;; +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_OSU_method = "TOI"; +INSERT INTO t1 (f1) SELECT 200000 + (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; +SELECT COUNT(*) = 300000 FROM t1; +COUNT(*) = 300000 +1 +SELECT MAX(f1) = 299999 FROM t1; +MAX(f1) = 299999 +1 +SELECT COUNT(*) = 300000 FROM t1; +COUNT(*) = 300000 +1 +SELECT MAX(f1) = 299999 FROM t1; +MAX(f1) = 299999 +1 +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_OSU_method = "TOI"; +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result new file mode 100644 index 00000000000..039fb68d244 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result @@ -0,0 +1,42 @@ +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) 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;; +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 DROP PRIMARY KEY; +SET SESSION wsrep_OSU_method = "TOI"; +INSERT INTO t1 (f1) SELECT 200000 + (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; +SELECT COUNT(*) = 300000 FROM t1; +COUNT(*) = 300000 +1 +SELECT MAX(f1) = 299999 FROM t1; +MAX(f1) = 299999 +1 +SELECT COUNT(*) = 300000 FROM t1; +COUNT(*) = 300000 +1 +SELECT MAX(f1) = 299999 FROM t1; +MAX(f1) = 299999 +1 +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 DROP PRIMARY KEY; +SET SESSION wsrep_OSU_method = "TOI"; +INSERT INTO t1 (f1) VALUES (1); +INSERT INTO t1 (f1) VALUES (10); +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 10; +COUNT(*) = 2 +1 +INSERT INTO t1 (f1) VALUES (100); +INSERT INTO t1 (f1) VALUES (1000); +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 100; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 1000; +COUNT(*) = 2 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_rsu_error.result b/mysql-test/suite/galera/r/galera_rsu_error.result new file mode 100644 index 00000000000..bfe41390d1d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_rsu_error.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t1 VALUES (1), (1); +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SET SESSION wsrep_OSU_method = "TOI"; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +INSERT INTO t1 VALUES (1); +SELECT COUNT(3) = 4 FROM t1; +COUNT(3) = 4 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_rsu_simple.result b/mysql-test/suite/galera/r/galera_rsu_simple.result new file mode 100644 index 00000000000..4c2780a2933 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_rsu_simple.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 1 +1 +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +INSERT INTO t1 (f1) VALUES (2); +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result new file mode 100644 index 00000000000..0bf6cc7c9d3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sbr.result @@ -0,0 +1,14 @@ +SET SESSION binlog_format = 'STATEMENT'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION binlog_format = 'MIXED'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; +SET GLOBAL binlog_format = 'ROW'; diff --git a/mysql-test/suite/galera/r/galera_sbr_binlog.result b/mysql-test/suite/galera/r/galera_sbr_binlog.result new file mode 100644 index 00000000000..0bf6cc7c9d3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sbr_binlog.result @@ -0,0 +1,14 @@ +SET SESSION binlog_format = 'STATEMENT'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION binlog_format = 'MIXED'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; +SET GLOBAL binlog_format = 'ROW'; diff --git a/mysql-test/suite/galera/r/galera_split_brain.result b/mysql-test/suite/galera/r/galera_split_brain.result new file mode 100644 index 00000000000..615615040fe --- /dev/null +++ b/mysql-test/suite/galera/r/galera_split_brain.result @@ -0,0 +1,5 @@ +call mtr.add_suppression("WSREP: TO isolation failed for: "); +Killing server ... +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET GLOBAL wsrep_cluster_address = ''; 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 new file mode 100644 index 00000000000..89ab8d5e55b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION sql_log_bin = 0; +INSERT INTO t1 VALUES (1); +SET SESSION sql_log_bin = 1; +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 1; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_ssl.result b/mysql-test/suite/galera/r/galera_ssl.result new file mode 100644 index 00000000000..569c3c607d5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ssl.result @@ -0,0 +1,18 @@ +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump.result b/mysql-test/suite/galera/r/galera_sst_mysqldump.result new file mode 100644 index 00000000000..1be2002001b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump.result @@ -0,0 +1,459 @@ +Setting SST method to mysqldump ... +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:sst'; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +Performing State Transfer on a server that has been temporarily disconnected +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Loading wsrep provider ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +DROP USER sst; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); +CALL mtr.add_suppression("InnoDB: New log files created"); +CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +CALL mtr.add_suppression("Can't open and lock time zone table"); +CALL mtr.add_suppression("Can't open and lock privilege tables"); +CALL mtr.add_suppression("Info table is not ready to be used"); +CALL mtr.add_suppression("Native table .* has the wrong structure"); diff --git a/mysql-test/suite/galera/r/galera_sst_rsync.result b/mysql-test/suite/galera/r/galera_sst_rsync.result new file mode 100644 index 00000000000..df2d9190a4b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_rsync.result @@ -0,0 +1,359 @@ +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result new file mode 100644 index 00000000000..750d73b615f --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result @@ -0,0 +1,358 @@ +Performing State Transfer on a server that has been shut down cleanly and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET wsrep_sync_wait = 0; +Killing server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_status_cluster.result b/mysql-test/suite/galera/r/galera_status_cluster.result new file mode 100644 index 00000000000..d7cf671cb10 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_status_cluster.result @@ -0,0 +1,12 @@ +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 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 diff --git a/mysql-test/suite/galera/r/galera_status_local_state.result b/mysql-test/suite/galera/r/galera_status_local_state.result new file mode 100644 index 00000000000..65713f1975c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_status_local_state.result @@ -0,0 +1,14 @@ +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SET GLOBAL wsrep_desync = 1; +SELECT VARIABLE_VALUE = 'Donor/Desynced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Donor/Desynced' +1 +SET GLOBAL wsrep_desync = 0; +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_suspend_slave.result b/mysql-test/suite/galera/r/galera_suspend_slave.result new file mode 100644 index 00000000000..02904812dd5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_suspend_slave.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +Suspending node_2 ... +INSERT INTO t1 VALUES (1); +Got one of the listed errors +Resuming node_2 ... +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..f91415323ec --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result @@ -0,0 +1,42 @@ +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; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +ALTER TABLE t1 AUTO_INCREMENT = 1000; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +SELECT MIN(f1) >= 1000, COUNT(*) = 20, COUNT(DISTINCT f1) = 20 FROM t1 WHERE f1 >= 1000; +MIN(f1) >= 1000 COUNT(*) = 20 COUNT(DISTINCT f1) = 20 +1 1 1 +SELECT MIN(f1) >= 1000, COUNT(*) = 20, COUNT(DISTINCT f1) = 20 FROM t1 WHERE f1 >= 1000; +MIN(f1) >= 1000 COUNT(*) = 20 COUNT(DISTINCT f1) = 20 +1 1 1 +ALTER TABLE t1 AUTO_INCREMENT = 5; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +SELECT MIN(f1) >= 1000, COUNT(*) = 40, COUNT(DISTINCT f1) = 40 FROM t1 WHERE f1 >= 1000; +MIN(f1) >= 1000 COUNT(*) = 40 COUNT(DISTINCT f1) = 40 +1 1 1 +SELECT MIN(f1) >= 1000, COUNT(*) = 40, COUNT(DISTINCT f1) = 40 FROM t1 WHERE f1 >= 1000; +MIN(f1) >= 1000 COUNT(*) = 40 COUNT(DISTINCT f1) = 40 +1 1 1 +DROP TABLE t1; +SET GLOBAL wsrep_auto_increment_control = OFF; +SET GLOBAL auto_increment_increment = 1; +SET GLOBAL auto_increment_offset = 1; +SET GLOBAL wsrep_auto_increment_control = OFF; +SET GLOBAL auto_increment_increment = 1; +SET GLOBAL auto_increment_offset = 1; +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +ALTER TABLE t1 AUTO_INCREMENT=100; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +INSERT INTO t1 (f2) SELECT 1 FROM ten; +SELECT MIN(f1) = 100, MAX(f1) = 119, COUNT(f1) = 20, COUNT(DISTINCT f1) = 20 FROM t1; +MIN(f1) = 100 MAX(f1) = 119 COUNT(f1) = 20 COUNT(DISTINCT f1) = 20 +1 1 1 1 +SELECT MIN(f1) = 100, MAX(f1) = 119, COUNT(f1) = 20, COUNT(DISTINCT f1) = 20 FROM t1; +MIN(f1) = 100 MAX(f1) = 119 COUNT(f1) = 20 COUNT(DISTINCT f1) = 20 +1 1 1 1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_error.result b/mysql-test/suite/galera/r/galera_toi_ddl_error.result new file mode 100644 index 00000000000..656e20bcc46 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ddl_error.result @@ -0,0 +1,19 @@ +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 (f1) SELECT (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 MAX(f1) FROM t1; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +ERROR 23000: Duplicate entry '111110' for key 'PRIMARY' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP TABLE ten; 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 new file mode 100644 index 00000000000..81781fbeae7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ddl_fk_insert.result @@ -0,0 +1,31 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +CREATE TABLE parent ( +id INT PRIMARY KEY AUTO_INCREMENT, +f2 INTEGER, +KEY (id) +) ENGINE=InnoDB; +CREATE TABLE child ( +id INT PRIMARY KEY AUTO_INCREMENT, +parent_id INT +) ENGINE=InnoDB; +INSERT INTO parent VALUES (DEFAULT, 0); +INSERT INTO child (parent_id) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO parent (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO parent (f2) SELECT 2 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +ALTER TABLE child ADD FOREIGN KEY (parent_id) REFERENCES parent(id);; +SELECT COUNT(*) = 20001 FROM parent; +COUNT(*) = 20001 +1 +SELECT COUNT(*) = 10000 FROM child; +COUNT(*) = 10000 +1 +SELECT COUNT(*) = 20001 FROM parent; +COUNT(*) = 20001 +1 +SELECT COUNT(*) = 10000 FROM child; +COUNT(*) = 10000 +1 +DROP TABLE child; +DROP TABLE parent; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result new file mode 100644 index 00000000000..d72a80b5a23 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result @@ -0,0 +1,41 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +COMMIT;; +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 +SET DEBUG_SYNC= 'now SIGNAL continue'; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +SET DEBUG_SYNC= 'RESET'; +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 new file mode 100644 index 00000000000..41e693c2b19 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); +ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123);; +CREATE UNIQUE INDEX i1 ON t1(f2);; +INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 234); +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 3 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 3 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result new file mode 100644 index 00000000000..9dfa433d49f --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result @@ -0,0 +1,35 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +INSERT INTO t1 VALUES (2, 3); +ALTER TABLE t1 DROP COLUMN f2; +INSERT INTO t1 VALUES (4); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +SELECT * FROM t1 ORDER BY f1; +f1 +1 +2 +4 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +SELECT * FROM t1 ORDER BY f1; +f1 +1 +2 +4 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_toi_ftwrl.result b/mysql-test/suite/galera/r/galera_toi_ftwrl.result new file mode 100644 index 00000000000..594717c96ff --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_ftwrl.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +FLUSH TABLES WITH READ LOCK; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +UNLOCK TABLES; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result new file mode 100644 index 00000000000..eac50e8853c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (2); +ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=EXCLUSIVE; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (2, 2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (3, 3); +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE 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 new file mode 100644 index 00000000000..36c38860688 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_toi_lock_shared.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=SHARED; +INSERT INTO t1 VALUES (2, 2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (3, 3); +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_transaction_read_only.result b/mysql-test/suite/galera/r/galera_transaction_read_only.result new file mode 100644 index 00000000000..3cd1076a285 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_transaction_read_only.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +COMMIT; +wsrep_last_committed_diff +1 +START TRANSACTION READ ONLY; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COMMIT; +wsrep_last_committed_diff +1 +START TRANSACTION; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COMMIT; +wsrep_last_committed_diff +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_transaction_replay.result b/mysql-test/suite/galera/r/galera_transaction_replay.result new file mode 100644 index 00000000000..23ed87ffe22 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_transaction_replay.result @@ -0,0 +1,30 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; +f1 f2 +2 a +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_enter_sync'; +COMMIT;; +SET SESSION wsrep_sync_wait = 0; +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_enter_sync'; +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 +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; diff --git a/mysql-test/suite/galera/r/galera_truncate.result b/mysql-test/suite/galera/r/galera_truncate.result new file mode 100644 index 00000000000..eeeb6721d12 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_truncate.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +CREATE TABLE t2 (f1 VARCHAR(255)) Engine=InnoDB; +INSERT INTO t2 VALUES ('abc'); +TRUNCATE TABLE t2; +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +CREATE TABLE t3 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; +INSERT INTO t3 VALUES (DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT); +CREATE TABLE t4 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB AUTO_INCREMENT=1234; +INSERT INTO t4 VALUES (DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT); +TRUNCATE TABLE t3; +TRUNCATE TABLE t4; +SELECT AUTO_INCREMENT = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('t3', 't4'); +AUTO_INCREMENT = 1 +1 +1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/mysql-test/suite/galera/r/galera_truncate_temporary.result b/mysql-test/suite/galera/r/galera_truncate_temporary.result new file mode 100644 index 00000000000..0bdc4e3632a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_truncate_temporary.result @@ -0,0 +1,63 @@ +CREATE TEMPORARY TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT * FROM t1; +ERROR 42S02: Table 'test.t1' doesn't exist +DROP TABLE t1; +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); +SELECT f1 = 2 FROM t1; +f1 = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT f1 = 1 FROM t1; +f1 = 1 +1 +DROP TABLE t1; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT f1 = 1 FROM t1; +f1 = 1 +1 +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +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); +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT f1 = 2 FROM t1; +f1 = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP 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 cb348f8509f..212c6c65b67 100644 --- a/mysql-test/suite/galera/r/galera_unicode_identifiers.result +++ b/mysql-test/suite/galera/r/galera_unicode_identifiers.result @@ -6,7 +6,7 @@ CREATE TABLE `table with space` ( `column with space` INTEGER AUTO_INCREMENT PRIMARY KEY, `second column with space` INTEGER, UNIQUE `index name with space` (`second column with space`) -) ENGINE=INNODB; +); INSERT INTO `table with space` VALUES (DEFAULT, 1); CREATE DATABASE `база`; USE `база`; @@ -14,7 +14,7 @@ CREATE TABLE `таблица` ( `първа_колона` INTEGER PRIMARY KEY, `втора_колона` INTEGER, UNIQUE `индекÑ` (`втора_колона`) -) ENGINE=INNODB; +); INSERT INTO `таблица` VALUES (1, 1); CREATE DATABASE `втора база`; USE `втора база`; @@ -22,20 +22,20 @@ CREATE TABLE `втора таблица` ( `първа колона` INTEGER, `втора колона` INTEGER, KEY `първи индекÑ` (`първа колона`) -) ENGINE=INNODB; +); INSERT INTO `втора таблица` VALUES (1, 1); USE `database with space`; -SELECT * FROM `table with space`; -column with space second column with space -1 1 +SELECT `second column with space` FROM `table with space`; +second column with space +1 USE `база`; SELECT * FROM `таблица`; първа_колона втора_колона 1 1 USE `втора база`; -SELECT * FROM `втора таблица`; -първа колона втора колона -1 1 +SELECT `втора колона` FROM `втора таблица`; +втора колона +1 SET GLOBAL wsrep_sync_wait = (SELECT @@wsrep_sync_wait); DROP TABLE `database with space`.`table with space`; DROP TABLE `база`.`таблица`; diff --git a/mysql-test/suite/galera/r/galera_unicode_pk.result b/mysql-test/suite/galera/r/galera_unicode_pk.result new file mode 100644 index 00000000000..d59615b2542 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_unicode_pk.result @@ -0,0 +1,31 @@ +CREATE TABLE t1 ( +f1 VARCHAR(255) PRIMARY KEY +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('текÑÑ‚'); +SELECT f1 = 'текÑÑ‚' FROM t1; +f1 = 'текÑÑ‚' +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚2'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚3'; +COMMIT; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT f1 = 'текÑÑ‚2' FROM t1; +f1 = 'текÑÑ‚2' +1 +SELECT f1 = 'текÑÑ‚2' FROM t1 WHERE f1 = 'текÑÑ‚2'; +f1 = 'текÑÑ‚2' +1 +START TRANSACTION; +INSERT INTO t1 VALUES ('текÑÑ‚4'); +START TRANSACTION; +INSERT INTO t1 VALUES ('текÑÑ‚4'); +COMMIT; +COMMIT; +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 new file mode 100644 index 00000000000..c26eb1c29f6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_update_limit.result @@ -0,0 +1,17 @@ +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) Engine=InnoDB; +INSERT INTO t1 SELECT f1 FROM ten ORDER BY RAND(); +UPDATE IGNORE t1 SET f1 = FLOOR(1 + (RAND() * 10)) ORDER BY RAND() LIMIT 5; +sum_matches +1 +max_matches +1 +DROP TABLE t1; +CREATE TABLE t2 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t2 SELECT f1 FROM ten ORDER BY RAND(); +UPDATE IGNORE t2 SET f1 = FLOOR(1 + (RAND() * 10)) ORDER BY RAND() LIMIT 5; +sum_matches +1 +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_v1_row_events.result b/mysql-test/suite/galera/r/galera_v1_row_events.result new file mode 100644 index 00000000000..a6ab62350b1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_v1_row_events.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method.result b/mysql-test/suite/galera/r/galera_var_OSU_method.result index 8e47443184e..9a07873e1b9 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result @@ -11,4 +11,6 @@ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; COUNT(*) = 1 1 SET SESSION wsrep_OSU_method = "TOI"; +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; 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 67fc63ade74..08f2e6aa0d8 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method2.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result @@ -15,3 +15,5 @@ COUNT(*) = 2 INSERT INTO t1 VALUES (3,4); SET GLOBAL wsrep_OSU_method = "TOI"; DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC= 'RESET'; 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 87d6020d47c..92b69fbbaa7 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 @@ -58,10 +58,4 @@ f1 node SELECT * FROM t1; f1 node 1 node1 -SET GLOBAL wsrep_auto_increment_control = 1; -SET GLOBAL auto_increment_increment = 2; -SET GLOBAL auto_increment_offset = 1; -SET GLOBAL wsrep_auto_increment_control = 1; -SET GLOBAL auto_increment_increment = 2; -SET GLOBAL auto_increment_offset = 2; DROP TABLE t1; 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 953ae9f4d81..8859209cc0c 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,31 +1,17 @@ CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE=InnoDB; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) NOT NULL AUTO_INCREMENT, - `node` varchar(10) DEFAULT NULL, - PRIMARY KEY (`f1`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') 1 -SELECT @@auto_increment_offset = 1; -@@auto_increment_offset = 1 +SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +@@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 1 INSERT INTO t1 VALUES (DEFAULT, 'node1');; INSERT INTO t1 VALUES (DEFAULT, 'node2');; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) NOT NULL AUTO_INCREMENT, - `node` varchar(10) DEFAULT NULL, - PRIMARY KEY (`f1`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') 1 -SELECT @@auto_increment_offset = 2; -@@auto_increment_offset = 2 +SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +@@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 1 INSERT INTO t1 VALUES (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2');; INSERT INTO t1 VALUES (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1');; diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result new file mode 100644 index 00000000000..0d4795fb259 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -0,0 +1,60 @@ +SET GLOBAL wsrep_cluster_address = 'foo://'; +SET SESSION wsrep_sync_wait=0; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +ERROR 08S01: WSREP has not yet prepared node for application use +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SHOW STATUS LIKE 'wsrep_local_state'; +Variable_name Value +wsrep_local_state 0 +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Initialized +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 1 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SET GLOBAL wsrep_cluster_address = 'gcomm://192.0.2.1'; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +ERROR 08S01: WSREP has not yet prepared node for application use +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SHOW STATUS LIKE 'wsrep_local_state'; +Variable_name Value +wsrep_local_state 0 +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Initialized +SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +CALL mtr.add_suppression("WSREP: .*Backend not supported: foo.*"); +CALL mtr.add_suppression("WSREP: .*Failed to initialize backend using 'foo.*"); +CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'foo*"); +CALL mtr.add_suppression("WSREP: gcs connect failed: Socket type not supported"); +CALL mtr.add_suppression("WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: .*Failed to open backend connection: -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'gcomm://192\\.0\\.2\\.1': -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: gcs connect failed: Connection timed out"); +CALL mtr.add_suppression("WSREP: wsrep::connect\\(\\) failed: 7"); diff --git a/mysql-test/suite/galera/r/galera_var_desync_on.result b/mysql-test/suite/galera/r/galera_var_desync_on.result new file mode 100644 index 00000000000..0b5f34688b7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_desync_on.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; +SET GLOBAL wsrep_desync = TRUE; +FLUSH TABLES WITH READ LOCK; +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET GLOBAL wsrep_desync = FALSE; +UNLOCK TABLES; +SET SESSION wsrep_sync_wait = 1; +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +INSERT INTO t1 VALUES (11); +SELECT COUNT(*) = 11 FROM t1; +COUNT(*) = 11 +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..912e45a14b1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result @@ -0,0 +1,12 @@ +SET SESSION wsrep_sync_wait = 0; +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET GLOBAL innodb_disallow_writes=ON; +INSERT INTO t1 VALUES (1);; +SET GLOBAL innodb_disallow_writes=OFF; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..db145fd1561 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL wsrep_load_data_splitting = TRUE; +SELECT COUNT(*) = 95000 FROM t1; +COUNT(*) = 95000 +1 +wsrep_last_committed_diff +1 +SET GLOBAL wsrep_load_data_splitting = 1;; +DROP TABLE t1; 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 new file mode 100644 index 00000000000..81cc26916d3 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_max_ws_size.result @@ -0,0 +1,12 @@ +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.*'); +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 5 "Input/output error" during COMMIT +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_var_notify_cmd.result b/mysql-test/suite/galera/r/galera_var_notify_cmd.result new file mode 100644 index 00000000000..e9e4605e1bc --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_notify_cmd.result @@ -0,0 +1,10 @@ +SELECT COUNT(DISTINCT uuid) = 2 FROM mtr_wsrep_notify.membership; +COUNT(DISTINCT uuid) = 2 +1 +SELECT MAX(size) = 2 FROM mtr_wsrep_notify.status; +MAX(size) = 2 +1 +SELECT COUNT(DISTINCT idx) = 2 FROM mtr_wsrep_notify.status; +COUNT(DISTINCT idx) = 2 +1 +DROP SCHEMA mtr_wsrep_notify; 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 abaec56a2ad..73a0576048b 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,8 +1,78 @@ SET GLOBAL wsrep_replicate_myisam = TRUE; +SET GLOBAL wsrep_replicate_myisam = TRUE; CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=MyISAM; INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2), (3); +INSERT INTO t1 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(100)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1, 'abc'),(2,'abc'), (3, 'xxx'); +REPLACE INTO t1 VALUES (1, 'klm'), (2,'xyz'); +REPLACE INTO t1 SELECT 3, 'yyy' FROM DUAL; +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1 AND f2 = 'klm'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2 AND f2 = 'xyz'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3 AND f2 = 'yyy'; +COUNT(*) = 1 +1 +UPDATE t1 SET f2 = 'zzz' WHERE f2 = 'yyy'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'zzz'; +COUNT(*) = 1 +1 +DELETE FROM t1 WHERE f2 = 'zzz'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'zzz'; +COUNT(*) = 0 +1 +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +COMMIT; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 -SET GLOBAL wsrep_replicate_myisam = 0; +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +START TRANSACTION; +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (2); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 DROP TABLE t1; +DROP TABLE t2; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (f2 INTEGER PRIMARY KEY) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +COMMIT; +DROP TABLE t1; +DROP TABLE t2; +SET GLOBAL wsrep_replicate_myisam = 0; +SET GLOBAL wsrep_replicate_myisam = 0; diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result new file mode 100644 index 00000000000..6b84f03737b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result @@ -0,0 +1,106 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; +CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; +SET GLOBAL wsrep_slave_threads = 0; +Warnings: +Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' +SHOW WARNINGS; +Level Code Message +Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' +SELECT @@wsrep_slave_threads = 1; +@@wsrep_slave_threads = 1 +1 +SET GLOBAL wsrep_slave_threads = 1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 +1 +SET GLOBAL wsrep_slave_threads = 64; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = @@wsrep_slave_threads + 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 +1 +SET GLOBAL wsrep_slave_threads = 1; +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +SELECT COUNT(*) = 64 FROM t2; +COUNT(*) = 64 +1 +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = @@wsrep_slave_threads + 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 +1 +SET GLOBAL wsrep_slave_threads = 1; +DROP TABLE t1; +DROP TABLE t2; 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 new file mode 100644 index 00000000000..8b1c4ebf83b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result @@ -0,0 +1,19 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_on = FALSE; +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET GLOBAL wsrep_on = TRUE; +INSERT INTO t1 VALUES (3); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 2; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_wan.result b/mysql-test/suite/galera/r/galera_wan.result new file mode 100644 index 00000000000..6be32b291e5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wan.result @@ -0,0 +1,14 @@ +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 4 +1 +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (1); +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"); +SELECT VARIABLE_VALUE LIKE '%gmcast.segment = 3%' FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'; +VARIABLE_VALUE LIKE '%gmcast.segment = 3%' +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +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_wsrep_desync_wsrep_on.result b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result new file mode 100644 index 00000000000..06fc27ae7ed --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result @@ -0,0 +1,33 @@ +CREATE TABLE ten (f1 INTEGER); +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; +SET GLOBAL wsrep_desync = TRUE; +SET SESSION wsrep_on = FALSE; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on = TRUE; +SET GLOBAL wsrep_desync = FALSE; +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; +SELECT COUNT(*) = 200000 FROM t1; +COUNT(*) = 200000 +1 +SELECT MAX(f1) = 199999 FROM t1; +MAX(f1) = 199999 +1 +SELECT COUNT(*) = 200000 FROM t1; +COUNT(*) = 200000 +1 +SELECT MAX(f1) = 199999 FROM t1; +MAX(f1) = 199999 +1 +SET GLOBAL wsrep_desync = TRUE; +SET SESSION wsrep_on = FALSE; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on = TRUE; +SET GLOBAL wsrep_desync = FALSE; +INSERT INTO t1 (f1) VALUES (1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +INSERT INTO t1 (f1) VALUES (100); +ERROR 23000: Duplicate entry '100' for key 'PRIMARY' +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result new file mode 100644 index 00000000000..e3f2fa4046f --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result @@ -0,0 +1,36 @@ +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index'; +VARIABLE_VALUE = 0 +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index'; +VARIABLE_VALUE = 0 +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +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_wsrep_provider_unset_set.result b/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result new file mode 100644 index 00000000000..681e4606b38 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_provider='none'; +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_zero_length_column.result b/mysql-test/suite/galera/r/galera_zero_length_column.result new file mode 100644 index 00000000000..2e6119bd1ba --- /dev/null +++ b/mysql-test/suite/galera/r/galera_zero_length_column.result @@ -0,0 +1,38 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY , f2 VARCHAR(0)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 VARCHAR(0)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, ''); +INSERT INTO t2 VALUES (NULL); +INSERT INTO t2 VALUES (''); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT f2 IS NULL FROM t1 WHERE f1 = 1; +f2 IS NULL +1 +SELECT f2 = '' FROM t1 WHERE f1 = 2; +f2 = '' +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +SELECT f1 IS NULL FROM t2 WHERE f1 IS NULL; +f1 IS NULL +1 +SELECT f1 = '' FROM t2 WHERE f1 IS NOT NULL; +f1 = '' +1 +UPDATE t1 SET f2 = '' WHERE f1 = 1; +UPDATE t1 SET f2 = NULL WHERE f1 = 2; +UPDATE t2 SET f1 = '' WHERE f1 IS NULL; +SELECT f2 = '' FROM t1 WHERE f1 = 1; +f2 = '' +1 +SELECT f2 IS NULL FROM t1 WHERE f1 = 2; +f2 IS NULL +1 +SELECT COUNT(*) = 2 FROM t2 WHERE f1 = ''; +COUNT(*) = 2 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/lp1276424.result b/mysql-test/suite/galera/r/lp1276424.result new file mode 100644 index 00000000000..5f09ec9ea8b --- /dev/null +++ b/mysql-test/suite/galera/r/lp1276424.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (f1 INT DEFAULT NULL, UNIQUE KEY i1 (f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (NULL); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT f1 IS NULL FROM t1; +f1 IS NULL +1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/lp1347768.result b/mysql-test/suite/galera/r/lp1347768.result new file mode 100644 index 00000000000..c085059e014 --- /dev/null +++ b/mysql-test/suite/galera/r/lp1347768.result @@ -0,0 +1,17 @@ +CREATE TABLE `r8kmb_redirect_links` ( +`id` int(10) unsigned NOT NULL AUTO_INCREMENT, +`old_url` varchar(255) DEFAULT NULL, +`new_url` varchar(255) NOT NULL, +`referer` varchar(150) NOT NULL, +`comment` varchar(255) NOT NULL, +`published` tinyint(4) NOT NULL, +`created_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', +`modified_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (`id`), +UNIQUE KEY `idx_link_old` (`old_url`), +KEY `idx_link_modifed` (`modified_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO r8kmb_redirect_links VALUES (550,'http://mysite.com/images/download/ßуñûічýøù_ôþóþòір_þфõÑ.doc','','','',0,'2013-07-15 14:29:42','0000-00-00 00:00:00'); +Warnings: +Warning 1265 Data truncated for column 'old_url' at row 1 +DROP TABLE r8kmb_redirect_links; diff --git a/mysql-test/suite/galera/r/lp959512.result b/mysql-test/suite/galera/r/lp959512.result new file mode 100644 index 00000000000..55adfa360b0 --- /dev/null +++ b/mysql-test/suite/galera/r/lp959512.result @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS variable; +Warnings: +Note 1051 Unknown table 'test.variable' +DROP TABLE IF EXISTS foo; +Warnings: +Note 1051 Unknown table 'test.foo' +CREATE TABLE variable ( +name varchar(128) NOT NULL DEFAULT '' COMMENT 'The name of the variable.', +value longblob NOT NULL COMMENT 'The value of the variable.', +PRIMARY KEY (name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Named variable/value pairs created by Drupal core or any...'; +CREATE TABLE foo (a int); +INSERT INTO variable (name, value) VALUES ('menu_expanded', 'a:0:{}'); +START TRANSACTION; +SELECT 1 AS expression FROM variable variable +WHERE ( (name = 'menu_expanded') ) FOR UPDATE; +expression +1 +UPDATE variable SET value='a:0:{}' WHERE ( (name = 'menu_expanded') ); +COMMIT; +INSERT INTO foo VALUES (1); +UPDATE foo SET a = 2 WHERE a = 1; +DROP TABLE foo; +DROP TABLE variable; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#33.result b/mysql-test/suite/galera/r/mysql-wsrep#33.result new file mode 100644 index 00000000000..153d8084bec --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#33.result @@ -0,0 +1,103 @@ +Setting SST method to mysqldump ... +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:sst'; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +Performing State Transfer on a server that has been temporarily disconnected +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +Loading wsrep provider ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +DROP USER sst; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); +CALL mtr.add_suppression("InnoDB: New log files created"); +CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +CALL mtr.add_suppression("Can't open and lock time zone table"); +CALL mtr.add_suppression("Can't open and lock privilege tables"); +CALL mtr.add_suppression("Info table is not ready to be used"); +CALL mtr.add_suppression("Native table .* has the wrong structure"); +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 03bb2e85e81..47dd41c7601 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -34,6 +34,20 @@ push @::global_suppressions, qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, + qr(WSREP: Quorum: No node with complete state), + qr(WSREP: Initial position was provided by configuration or SST, avoiding override), + qr|WSREP: discarding established \(time wait\) .*|, + qr(WSREP: There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside. Will use that one.), + qr(WSREP: evs::proto.*), + qr|WSREP: Ignoring possible split-brain \(allowed by configuration\) from view:.*|, + qr(WSREP: no nodes coming from prim view, prim not possible), + qr(WSREP: Member .* requested state transfer from .* but it is impossible to select State Transfer donor: Resource temporarily unavailable), + qr(WSREP: user message in state LEAVING), + qr(WSREP: .* sending install message failed: Transport endpoint is not connected), + qr(WSREP: Maximum writeset size exceeded by .*), + qr(WSREP: transaction size exceeded), + qr(WSREP: RBR event .*), + qr(WSREP: Ignoring error for TO isolated action: .*), ); diff --git a/mysql-test/suite/galera/t/galera_account_management.test b/mysql-test/suite/galera/t/galera_account_management.test new file mode 100644 index 00000000000..357319ad106 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_account_management.test @@ -0,0 +1,101 @@ +# +# Test the account management statements - GRANT, REVOKE, etc. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# CREATE USER +# +--connection node_1 +CREATE USER user1, user2 IDENTIFIED BY 'password'; + +--connection node_2 +SELECT COUNT(*) = 2 FROM mysql.user WHERE user IN ('user1', 'user2'); + +# +# ALTER USER +# + +# LP bug 1376269 +# +#--connection node_1 +#ALTER USER user1 PASSWORD EXPIRE; +#SELECT password_expired = 'Y' FROM mysql.user WHERE user = 'user1'; +# +#--connection node_2 +#SELECT password_expired = 'Y' FROM mysql.user WHERE user = 'user1'; + +# +# RENAME USER +# + +--connection node_1 +RENAME USER user2 TO user3; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.user WHERE user = 'user2'; +SELECT COUNT(*) = 1 FROM mysql.user WHERE user = 'user3'; + +# +# SET PASSWORD +# + +--connection node_1 +SET PASSWORD FOR user3 = PASSWORD('foo'); + +--connection node_1 +SELECT password != '' FROM mysql.user WHERE user = 'user3'; + +# +# DROP USER +# +--connection node_1 +DROP USER user1, user3; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.user WHERE user IN ('user1', 'user2'); + +# +# GRANT +# + +--connection node_1 +GRANT ALL ON *.* TO user4 IDENTIFIED BY 'password'; + +--connection node_2 +SELECT COUNT(*) = 1 FROM mysql.user WHERE user = 'user4'; +SELECT Select_priv = 'Y' FROM mysql.user WHERE user = 'user4'; + +# +# GRANT PROXY ON +# +--connection node_1 +CREATE USER user5; +GRANT PROXY ON user4 TO user5; + +--connection node_2 +SELECT COUNT(*) = 1 FROM mysql.proxies_priv WHERE user = 'user5'; + +# +# REVOKE +# + +--connection node_1 +REVOKE ALL PRIVILEGES ON *.* FROM user4; + +--connection node_2 +SELECT Select_priv = 'N' FROM mysql.user WHERE user = 'user4'; + +# +# REVOKE PROXY +# + +--connection node_1 +REVOKE PROXY ON user4 FROM user5; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.proxies_priv WHERE user = 'user5'; + +DROP USER user4, user5; diff --git a/mysql-test/suite/galera/t/galera_alter_engine_innodb.test b/mysql-test/suite/galera/t/galera_alter_engine_innodb.test new file mode 100644 index 00000000000..bc914a38776 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_alter_engine_innodb.test @@ -0,0 +1,17 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test ALTER ENGINE from InnoDB to InnoDB +# + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +ALTER TABLE t1 ENGINE=InnoDB; + +--connection node_2 +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_alter_engine_myisam.test b/mysql-test/suite/galera/t/galera_alter_engine_myisam.test new file mode 100644 index 00000000000..6d41d276a17 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_alter_engine_myisam.test @@ -0,0 +1,25 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test ALTER ENGINE from MyISAM to InnoDB under wsrep_replicate_myisam +# + +--let $wsrep_replicate_myisam_orig = `SELECT @@wsrep_replicate_myisam` +SET GLOBAL wsrep_replicate_myisam = TRUE; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); + +ALTER TABLE t1 ENGINE=InnoDB; + +--connection node_2 +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_alter_table_force.test b/mysql-test/suite/galera/t/galera_alter_table_force.test new file mode 100644 index 00000000000..1fcc9d4bda5 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_alter_table_force.test @@ -0,0 +1,17 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test ALTER TABLE FORCE, a 5.6.3 feature that simply rebuilds the table +# + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +ALTER TABLE t1 FORCE; + +--connection node_2 +SELECT ENGINE = 'InnoDB' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_as_master.cnf b/mysql-test/suite/galera/t/galera_as_master.cnf new file mode 100644 index 00000000000..52fd3093931 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master.cnf @@ -0,0 +1 @@ +!include ../galera_2nodes_as_master.cnf diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test new file mode 100644 index 00000000000..c42dbbf9683 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master.test @@ -0,0 +1,38 @@ +# +# Test Galera as a master to a MySQL slave +# +# The galera/galera_2node_master.cnf describes the setup of the nodes +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--enable_query_log +START SLAVE; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +--connection node_2 +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 + +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +DROP TABLE t1; + +--connection node_3 +--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_master_gtid.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf new file mode 100644 index 00000000000..19517556331 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf @@ -0,0 +1,8 @@ +!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 new file mode 100644 index 00000000000..9db104b7cab --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master_gtid.test @@ -0,0 +1,70 @@ +# +# Test Galera as a master to a MySQL slave with GTID +# +# The galera/galera_2node_master.cnf describes the setup of the nodes +# +# We check that all transactions originating from within Galera use a UUID that is +# different from the server_uuid of either node +# +# + +--source include/have_innodb.inc +--source include/have_log_bin.inc +--source include/galera_cluster.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--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 TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +--let $effective_uuid = `SELECT LEFT(@@global.gtid_executed, 36)` +--disable_query_log +--eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match; +--enable_query_log + +--replace_result $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); + +--disable_query_log +--eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match; +--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match; +--enable_query_log + +--replace_result $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 + +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +--disable_query_log +--eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match; +--eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match; +--enable_query_log + +--replace_result $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; + +--connection node_3 +--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_master_gtid_change_master.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf new file mode 100644 index 00000000000..19517556331 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf @@ -0,0 +1,8 @@ +!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 new file mode 100644 index 00000000000..23606d7ac4c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test @@ -0,0 +1,54 @@ +# +# Test that a MySQL slave can use CHANGE MASTER MASTER_AUTO_POSITION to begin replicating +# from another Galera node +# +# The galera/galera_2node_master.cnf describes the setup of the nodes +# +# + +--source include/have_innodb.inc +--source include/have_log_bin.inc +--source include/galera_cluster.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--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 TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +--connection node_2 +INSERT INTO t1 VALUES(2); + +--connection node_3 +STOP SLAVE; +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_2, MASTER_AUTO_POSITION=1; +--enable_query_log +START SLAVE USER='root'; + +--connection node_1 +INSERT INTO t1 VALUES(3); + +--connection node_2 +INSERT INTO t1 VALUES(4); + +--connection node_3 +--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 + +--connection node_1 +DROP TABLE t1; + +--connection node_3 +--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.cnf b/mysql-test/suite/galera/t/galera_as_slave.cnf new file mode 100644 index 00000000000..9449ec9cf40 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave.cnf @@ -0,0 +1 @@ +!include ../galera_2nodes_as_slave.cnf diff --git a/mysql-test/suite/galera/t/galera_as_slave.test b/mysql-test/suite/galera/t/galera_as_slave.test new file mode 100644 index 00000000000..79b9e5071a3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave.test @@ -0,0 +1,47 @@ +# +# Test Galera as a slave to a MySQL master +# +# The galera/galera_2node_slave.cnf describes the setup of the nodes +# + +--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 + +--connection node_2 +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--enable_query_log +START SLAVE; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (2); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +SELECT COUNT(*) = 2 FROM t1; +INSERT INTO t1 VALUES (3); + +--connection node_2 +SELECT COUNT(*) = 3 FROM t1; + +--connection node_1 +DROP TABLE t1; + +--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.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid.cnf new file mode 100644 index 00000000000..01d2eb12630 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.cnf @@ -0,0 +1,6 @@ +!include ../galera_2nodes_as_slave.cnf + +[mysqld] +log-bin=mysqld-bin +log-slave-updates +binlog-format=ROW diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid.test b/mysql-test/suite/galera/t/galera_as_slave_gtid.test new file mode 100644 index 00000000000..c2331a2ae05 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.test @@ -0,0 +1,67 @@ +# +# Test Galera as a slave to a MariaDB master using GTIDs +# +# suite/galera/galera_2nodes_as_slave.cnf describes the setup of the nodes +# suite/galera/t/galera_as_slave_gtid.cnf has the GTID options +# +# In addition to performing DDL and DML, we check that the gtid of the master is preserved inside the cluster +# + +--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 + +--connection node_2 +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--enable_query_log +START SLAVE; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +SELECT LENGTH(@@global.gtid_binlog_state) > 1; +--let $gtid_binlog_state_node1 = `SELECT @@global.gtid_binlog_state;` + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +--disable_query_log +--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; +--enable_query_log + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +SELECT COUNT(*) = 1 FROM t1; + +--disable_query_log +--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; +--enable_query_log + +--connection node_1 +DROP TABLE t1; + +# +# 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_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/t/galera_bf_abort.test b/mysql-test/suite/galera/t/galera_bf_abort.test new file mode 100644 index 00000000000..69825ea4919 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (2); + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_for_update.test b/mysql-test/suite/galera/t/galera_bf_abort_for_update.test new file mode 100644 index 00000000000..24c29778e5d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_for_update.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one while it is running a SELECT FOR UPDATE +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_DEADLOCK +SELECT * FROM t1 FOR UPDATE; + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_ftwrl.test b/mysql-test/suite/galera/t/galera_bf_abort_ftwrl.test new file mode 100644 index 00000000000..44398e717d1 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_ftwrl.test @@ -0,0 +1,30 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# A local transaction running FLUSH TABLES WITH READ LOCK will not be aborted by a slave transaction +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +--send FLUSH TABLES WITH READ LOCK; + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--reap + +UNLOCK TABLES; + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +# No aborts should be registered on the counter +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 0 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test b/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test new file mode 100644 index 00000000000..72fc1c5b583 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one while it is running a GET_LOCK() +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +SELECT GET_LOCK("foo", 1000); + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +INSERT INTO t1 VALUES (1); +--send SELECT GET_LOCK("foo", 1000); + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_DEADLOCK +--reap + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +# Check that wsrep_local_bf_aborts has been incremented by exactly 1 +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_lock_table.test b/mysql-test/suite/galera/t/galera_bf_abort_lock_table.test new file mode 100644 index 00000000000..788427103a5 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_lock_table.test @@ -0,0 +1,33 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that a local LOCK TABLE will be broken by an incoming remote transaction against that table +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +LOCK TABLE t1 WRITE; + +# Issue a concurrent INSERT against the lock table that will block +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--send INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (2); + +# The concurent insert is allowed to complete because the LOCK TABLE is now broken +--connection node_2a +--error 0 +--reap + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_sleep.test b/mysql-test/suite/galera/t/galera_bf_abort_sleep.test new file mode 100644 index 00000000000..8d135dc7d42 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_sleep.test @@ -0,0 +1,30 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one while it is running a SLEEP() +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +INSERT INTO t1 VALUES (1); +--send SELECT SLEEP(1000); + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_DEADLOCK +--reap + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +# Check that wsrep_local_bf_aborts has been incremented by exactly 1 +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_binlog_cache_size.test b/mysql-test/suite/galera/t/galera_binlog_cache_size.test new file mode 100644 index 00000000000..6ce9072d412 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_cache_size.test @@ -0,0 +1,35 @@ +# +# Test that Galera, like the stock MySQL, returns an error on transactions +# larger than max_binlog_cache_size +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +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); + +--let $max_binlog_cache_size_orig = `SELECT @@max_binlog_cache_size` +--let $binlog_cache_size_orig = `SELECT @@binlog_cache_size` + +SET GLOBAL binlog_cache_size=4096; +SET GLOBAL max_binlog_cache_size=4096; + +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +SET AUTOCOMMIT=ON; +START TRANSACTION; +INSERT INTO t1 SELECT REPEAT('a', 767) FROM ten; +--error ER_TRANS_CACHE_FULL +INSERT INTO t1 SELECT REPEAT('a', 767) FROM ten; + +--disable_query_log +--eval SET GLOBAL max_binlog_cache_size = $max_binlog_cache_size_orig +--eval SET GLOBAL binlog_cache_size = $binlog_cache_size_orig +--enable_query_log + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_binlog_checksum-master.opt b/mysql-test/suite/galera/t/galera_binlog_checksum-master.opt new file mode 100644 index 00000000000..c8e53f07fc2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_checksum-master.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 --master-verify-checksum=1 --slave-sql-verify-checksum=1 diff --git a/mysql-test/suite/galera/t/galera_binlog_checksum.test b/mysql-test/suite/galera/t/galera_binlog_checksum.test new file mode 100644 index 00000000000..48669305242 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_checksum.test @@ -0,0 +1,22 @@ +# +# Test that Galera works with binary log checksums. +# The galera_binlog_checksum-master.opt file is used to enable checksums. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +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/t/galera_binlog_event_max_size_max-master.opt b/mysql-test/suite/galera/t/galera_binlog_event_max_size_max-master.opt new file mode 100644 index 00000000000..a36d21315a6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_event_max_size_max-master.opt @@ -0,0 +1 @@ +--binlog-row-event-max-size=4294967295 diff --git a/mysql-test/suite/galera/t/galera_binlog_event_max_size_max.test b/mysql-test/suite/galera/t/galera_binlog_event_max_size_max.test new file mode 100644 index 00000000000..600432ce0ca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_event_max_size_max.test @@ -0,0 +1,20 @@ +# +# Test that replication works event with the maximum value of binlog-row-event-max-size - 4294967295 (on 32-bit platforms) +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +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)); + +# Insert 10K records, 1K bytes each +INSERT INTO t1 SELECT REPEAT('x', 1000) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_2 +SELECT COUNT(*) = 10000 FROM t1; + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_binlog_event_max_size_min-master.opt b/mysql-test/suite/galera/t/galera_binlog_event_max_size_min-master.opt new file mode 100644 index 00000000000..22174756652 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_event_max_size_min-master.opt @@ -0,0 +1 @@ +--binlog-row-event-max-size=256 diff --git a/mysql-test/suite/galera/t/galera_binlog_event_max_size_min.test b/mysql-test/suite/galera/t/galera_binlog_event_max_size_min.test new file mode 100644 index 00000000000..00b55339770 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_event_max_size_min.test @@ -0,0 +1,15 @@ +# +# Test that replication works event with the minimum value of binlog-row-event-max-size - 256 +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 VARCHAR(1000)); +INSERT INTO t1 VALUES (REPEAT('x', 1000)); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = REPEAT('x', 1000); + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_binlog_row_image.test b/mysql-test/suite/galera/t/galera_binlog_row_image.test new file mode 100644 index 00000000000..70262ec44ca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_row_image.test @@ -0,0 +1,100 @@ +# +# Test the operation on the different values of the binlog_row_image option +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# binlog_row_image = minimal +# + +--connection node_1 +SET SESSION binlog_row_image=minimal; + +# Create a table with a PK, with a unique key and with no key +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL UNIQUE) ENGINE=InnoDB; +CREATE TABLE t3 (f1 VARCHAR(1)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t3 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t3 WHERE f1 = 1; + +--connection node_1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +UPDATE t2 SET f1 = 2 WHERE f1 = 1; +UPDATE t3 SET f1 = 2 WHERE f1 = 1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 2; +SELECT COUNT(*) = 1 FROM t3 WHERE f1 = 2; + +--connection node_1 +DELETE FROM t1; +DELETE FROM t2; +DELETE FROM t3; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; +SELECT COUNT(*) = 0 FROM t3; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +# +# binlog_row_image = noblob +# + +# A table with only a blob, and a table with a PK and a blob + +--connection node_1 +SET SESSION binlog_row_image=noblob; + +CREATE TABLE t1 (f1 BLOB, f2 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 BLOB) ENGINE=InnoDB; + +INSERT INTO t1 VALUES ('abc', 1); +INSERT INTO t2 VALUES ('abc'); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'abc'; +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 'abc'; + +--connection node_1 +UPDATE t1 SET f1 = 'xyz'; +UPDATE t2 SET f1 = 'xyz'; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'xyz'; +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = 'xyz'; + +--connection node_1 +UPDATE t1 SET f2 = 2 WHERE f2 = 1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 2; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'xyz'; + +--connection node_1 +DELETE FROM t1; +DELETE FROM t2; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; + +DROP TABLE t1; +DROP TABLE t2; + + + + diff --git a/mysql-test/suite/galera/t/galera_binlog_rows_query_log_events.test b/mysql-test/suite/galera/t/galera_binlog_rows_query_log_events.test new file mode 100644 index 00000000000..95bc85c4cab --- /dev/null +++ b/mysql-test/suite/galera/t/galera_binlog_rows_query_log_events.test @@ -0,0 +1,28 @@ +# +# Test that Galera continues to run even with binlog-rows-query-log-events=TRUE +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $binlog_rows_query_log_events_orig = `SELECT @@binlog_rows_query_log_events` + +SET GLOBAL binlog_rows_query_log_events=TRUE; + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +UPDATE t1 SET f1 = 2 WHERE f1 = 1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; + +--connection node_1 +--eval SET GLOBAL binlog_rows_query_log_events = $binlog_rows_query_log_events_orig + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_create_function.test b/mysql-test/suite/galera/t/galera_create_function.test new file mode 100644 index 00000000000..fd4903a7b83 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_function.test @@ -0,0 +1,57 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test CREATE FUNCTION +# + +--connection node_1 +CREATE USER 'user1'; + +CREATE +DEFINER = 'user1' +FUNCTION f1 (param INTEGER) +RETURNS VARCHAR(200) +COMMENT 'f1_comment' +LANGUAGE SQL +NOT DETERMINISTIC +MODIFIES SQL DATA +SQL SECURITY DEFINER +RETURN 'abc'; +GRANT EXECUTE ON FUNCTION f1 TO user1; + +CREATE +DEFINER = CURRENT_USER +FUNCTION f2 (param VARCHAR(100)) +RETURNS INTEGER +DETERMINISTIC +NO SQL +SQL SECURITY INVOKER +RETURN 123; + +--connection node_1 +SHOW CREATE FUNCTION f1; + +--connection node_2 +SHOW CREATE FUNCTION f1; + +--connection node_1 +SHOW CREATE FUNCTION f2; + +--connection node_2 +SHOW CREATE FUNCTION f2; + +SELECT f1(1) = 'abc'; +SELECT f2('abc') = 123; + +--connection node_1 +DROP FUNCTION f1; +DROP FUNCTION f2; + +DROP USER 'user1'; + + + + + + diff --git a/mysql-test/suite/galera/t/galera_create_procedure.test b/mysql-test/suite/galera/t/galera_create_procedure.test new file mode 100644 index 00000000000..30bc85fcea0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_procedure.test @@ -0,0 +1,52 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test CREATE PROCEDURE +# + +--connection node_1 +CREATE USER 'user1'; +CREATE TABLE t1 (f1 INTEGER); + +CREATE +DEFINER = 'user1' +PROCEDURE p1 (IN param1 INTEGER, OUT param2 INTEGER, INOUT param3 INTEGER) +COMMENT 'p1_comment' +LANGUAGE SQL +NOT DETERMINISTIC +MODIFIES SQL DATA +SQL SECURITY DEFINER +INSERT INTO t1 VALUES (1); +GRANT EXECUTE ON PROCEDURE p1 TO user1; + +CREATE +DEFINER = CURRENT_USER +PROCEDURE p2 (param VARCHAR(100)) +DETERMINISTIC +NO SQL +SQL SECURITY INVOKER BEGIN END ; + +--connection node_1 +SHOW CREATE PROCEDURE p1; + +--connection node_2 +# Perform causal wait +SELECT 1 FROM DUAL; +SHOW CREATE PROCEDURE p1; + +--connection node_1 +SHOW CREATE PROCEDURE p2; + +--connection node_2 +SHOW CREATE PROCEDURE p2; + +CALL p1(@a, @b, @c); +CALL p2('abc'); + +--connection node_1 +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +DROP USER 'user1'; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_create_table_like.test b/mysql-test/suite/galera/t/galera_create_table_like.test new file mode 100644 index 00000000000..0e0e8b0ffcf --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_table_like.test @@ -0,0 +1,50 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the various forms of CREATE TABLE LIKE ... , since Galera has special handling +# for them, especially when one of the tables is a temporary one. +# + +CREATE SCHEMA schema1; +CREATE SCHEMA schema2; + +USE schema1; +CREATE TABLE real_table (f1 INTEGER) ENGINE=InnoDB; +CREATE TEMPORARY TABLE temp_table (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE myisam_table (f1 INTEGER) ENGINE=MyISAM; + +USE schema2; +CREATE TABLE real_table1 LIKE schema1.real_table; +CREATE TABLE real_table2 LIKE schema1.temp_table; +CREATE TABLE real_table3 LIKE schema1.myisam_table; + +CREATE TEMPORARY TABLE temp_table1 LIKE schema1.real_table; +CREATE TEMPORARY TABLE temp_table2 LIKE schema1.temp_table; +CREATE TEMPORARY TABLE temp_table3 LIKE schema1.myisam_table; + +--connection node_2 +# Only the non-temporary tables are replicated, regardless of the type of table they are based on + +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table' AND TABLE_SCHEMA = 'schema1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'myisam_table' AND TABLE_SCHEMA = 'schema1'; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table' AND TABLE_SCHEMA = 'schema1'; + +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table1' AND TABLE_SCHEMA = 'schema2'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table2' AND TABLE_SCHEMA = 'schema2'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'real_table3' AND TABLE_SCHEMA = 'schema2'; + +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table1' AND TABLE_SCHEMA = 'schema2'; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table2' AND TABLE_SCHEMA = 'schema2'; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp_table3' AND TABLE_SCHEMA = 'schema2'; + +--connection node_1 +DROP TABLE schema1.real_table; +DROP TABLE schema1.myisam_table; + +DROP TABLE schema2.real_table1; +DROP TABLE schema2.real_table2; +DROP TABLE schema2.real_table3; + +DROP SCHEMA schema1; +DROP SCHEMA schema2; diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test new file mode 100644 index 00000000000..995e0b4c451 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_defaults.test @@ -0,0 +1,69 @@ +# +# The purpose of this test is to preserve the current state of the following: +# * SHOW VARIABLES LIKE 'wsrep%' +# * wsrep_provider_options +# * The names of the Galera status variables +# +# This way, if there is any change, inadvertent or not, the test will fail and the +# developer and QA will be alerted. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Make sure that the test is operating on the right version of galera library. +--disable_query_log +--let $galera_version=3.9 +source ../wsrep/include/check_galera_version.inc; +--enable_query_log + +# Global Variables + +SELECT COUNT(*) = 39 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; + +SELECT VARIABLE_NAME, VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME NOT IN ( + 'WSREP_PROVIDER_OPTIONS', + 'WSREP_SST_RECEIVE_ADDRESS', + 'WSREP_NODE_ADDRESS', + 'WSREP_NODE_NAME', + 'WSREP_PROVIDER', + 'WSREP_DATA_HOME_DIR', + 'WSREP_NODE_INCOMING_ADDRESS', + 'WSREP_START_POSITION' +) +ORDER BY VARIABLE_NAME; + +# wsrep_provider_options +# +# We replace the ones that vary from run to run with placeholders + +--let _WSREP_PROVIDER_OPTIONS = `SELECT @@wsrep_provider_options` +--perl + use strict; + my $wsrep_provider_options = $ENV{'_WSREP_PROVIDER_OPTIONS'}; + $wsrep_provider_options =~ s/base_dir = .*?;/;/sgio; + $wsrep_provider_options =~ s/base_host = .*?;/;/sgio; + $wsrep_provider_options =~ s/base_port = .*?;/;/sgio; + $wsrep_provider_options =~ s/gcache\.dir = .*?;/;/sgio; + $wsrep_provider_options =~ s/gcache\.name = .*?;/;/sgio; + $wsrep_provider_options =~ s/gmcast\.listen_addr = .*?;/;/sgio; + $wsrep_provider_options =~ s/ist\.recv_addr = .*?;/;/sgio; + $wsrep_provider_options =~ s/evs\.evict = .*?;/;/sgio; + $wsrep_provider_options =~ s/signal = .*?;\s*//sgio; + $wsrep_provider_options =~ s/dbug = .*?;\s*//sgio; + print $wsrep_provider_options."\n"; +EOF + +# Global Status + +SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; + +SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME LIKE 'wsrep_%' +AND VARIABLE_NAME != 'wsrep_debug_sync_waiters' +ORDER BY VARIABLE_NAME; diff --git a/mysql-test/suite/galera/t/galera_delete_limit.test b/mysql-test/suite/galera/t/galera_delete_limit.test new file mode 100644 index 00000000000..4cbadbd3ba0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_delete_limit.test @@ -0,0 +1,52 @@ +# +# DELETE LIMIT should not cause any issues with row-based Galera replication +# regardless of the order in which the rows were deleted +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# With a PK +# + +--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) Engine=InnoDB; +INSERT INTO t1 SELECT f1 FROM ten ORDER BY RAND(); + +--connection node_2 +DELETE FROM t1 ORDER BY RAND() LIMIT 5; +--let $sum_remaining = `SELECT SUM(f1) FROM t1` +--let $max_remaining = `SELECT MAX(f1) FROM t1` + +--connection node_1 +--disable_query_log +--eval SELECT (SELECT SUM(f1) FROM t1) = $sum_remaining AS sum_matches; +--eval SELECT f1 = $max_remaining AS max_matches FROM t1 WHERE f1 = $max_remaining; +--enable_query_log + +DROP TABLE t1; + +# +# Without a PK +# + +CREATE TABLE t2 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t2 SELECT f1 FROM ten ORDER BY RAND(); + +--connection node_2 +DELETE FROM t2 ORDER BY RAND() LIMIT 5; +--let $sum_remaining = `SELECT SUM(f1) FROM t2` +--let $max_remaining = `SELECT MAX(f1) FROM t2` + +--connection node_1 +--disable_query_log +--eval SELECT (SELECT SUM(f1) FROM t2) = $sum_remaining AS sum_matches; +--eval SELECT f1 = $max_remaining AS max_matches FROM t2 WHERE f1 = $max_remaining; +--enable_query_log + +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_enum.test b/mysql-test/suite/galera/t/galera_enum.test new file mode 100644 index 00000000000..ff5332486aa --- /dev/null +++ b/mysql-test/suite/galera/t/galera_enum.test @@ -0,0 +1,62 @@ +# +# Test the ENUM column type, as it is frequently an unwanted child +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# ENUM as key +# + +--connection node_1 +CREATE TABLE t1 (f1 ENUM('', 'one', 'two'), KEY (f1)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (''); +INSERT INTO t1 VALUES ('one'), ('two'); +INSERT INTO t1 VALUES (0), (1), (2); + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 2 FROM t1 where f1 = ''; +SELECT COUNT(*) = 2 FROM t1 where f1 = 'one'; + +DROP TABLE t1; + +# +# ENUM as PK +# + +--connection node_1 +CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (''), ('one'), ('two'); + +--connection node_2 +SELECT COUNT(*) = 3 FROM t1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; + +# Conflict + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'three' where f1 = ''; + +--connection node_2 +SET AUTOCOMMIt=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'four' where f1 = ''; + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +--connection node_1 + +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_events.test b/mysql-test/suite/galera/t/galera_events.test new file mode 100644 index 00000000000..ae9940fc694 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_events.test @@ -0,0 +1,53 @@ +# +# Test that the replication of MySQL events conforms to the behavior of stock MySQL replication as described here +# http://dev.mysql.com/doc/refman/5.6/en/replication-features-invoked.html +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $event_scheduler_orig = `SELECT @@event_scheduler;` + +# +# Events arrive on slave as SLAVESIDE_DISABLED +# + +--connection node_1 +CREATE EVENT event1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO SELECT 1; + +--connection node_2 +SELECT DEFINER= 'root@localhost', ORIGINATOR = 1, STATUS = 'SLAVESIDE_DISABLED', EVENT_TYPE = 'ONE TIME', ON_COMPLETION = 'NOT PRESERVE' FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; + +--connection node_1 +ALTER EVENT event1 DISABLE; + +--connection node_2 +# The definition on node 2 should still say SLAVESIDE_DISABLED +SELECT DEFINER= 'root@localhost', ORIGINATOR = 1, STATUS = 'SLAVESIDE_DISABLED', EVENT_TYPE = 'ONE TIME', ON_COMPLETION = 'NOT PRESERVE' FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; + +# +# Expired event should be dropped from the slave +# + +--connection node_2 +SET GLOBAL event_scheduler = ON; +CREATE EVENT event2 ON SCHEDULE AT CURRENT_TIMESTAMP ON COMPLETION NOT PRESERVE DO SELECT 1; +--sleep 1 + +--connection node_1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event2'; + +# +# DROP EVENT causes event to be dropped everywhere +# + +--connection node_1 +DROP EVENT event1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'event1'; + +# Cleanup + +--connection node_2 +--eval SET GLOBAL event_scheduler = $event_scheduler_orig; diff --git a/mysql-test/suite/galera/t/galera_fk_multicolumn.test b/mysql-test/suite/galera/t/galera_fk_multicolumn.test index fc00eadcf5f..ad42f65924d 100644 --- a/mysql-test/suite/galera/t/galera_fk_multicolumn.test +++ b/mysql-test/suite/galera/t/galera_fk_multicolumn.test @@ -8,21 +8,21 @@ CREATE TABLE t0 ( f1 INT PRIMARY KEY, f2 INT UNIQUE -) ENGINE=INNODB; +); CREATE TABLE t1 ( f1 INT PRIMARY KEY, FOREIGN KEY (f1) REFERENCES t0(f1) ON UPDATE CASCADE -) ENGINE=INNODB; +); CREATE TABLE t2 ( f2 INT PRIMARY KEY, FOREIGN KEY (f2) REFERENCES t0(f2) ON UPDATE CASCADE -) ENGINE=INNODB; +); INSERT INTO t0 VALUES (0, 0); INSERT INTO t1 VALUES (0); diff --git a/mysql-test/suite/galera/t/galera_fk_multitable.test b/mysql-test/suite/galera/t/galera_fk_multitable.test index e53757b051b..6adfb8195ec 100644 --- a/mysql-test/suite/galera/t/galera_fk_multitable.test +++ b/mysql-test/suite/galera/t/galera_fk_multitable.test @@ -7,7 +7,7 @@ CREATE TABLE t0 ( f0 INT PRIMARY KEY -) ENGINE=INNODB; +); CREATE TABLE t1 ( f1 INT PRIMARY KEY, @@ -15,7 +15,7 @@ CREATE TABLE t1 ( FOREIGN KEY (f0) REFERENCES t0(f0) ON DELETE CASCADE -) ENGINE=INNODB; +); INSERT INTO t0 VALUES (0), (1); INSERT INTO t1 VALUES (0, 0); diff --git a/mysql-test/suite/galera/t/galera_flush.test b/mysql-test/suite/galera/t/galera_flush.test index 21647a8328c..cd6b40b5b4e 100644 --- a/mysql-test/suite/galera/t/galera_flush.test +++ b/mysql-test/suite/galera/t/galera_flush.test @@ -34,7 +34,7 @@ FLUSH HOSTS; --connection node_1 SET GLOBAL wsrep_replicate_myisam = TRUE; -INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N'); +INSERT INTO mysql.user VALUES('localhost','user1',PASSWORD('pass1'), 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'mysql_native_password','','N','N'); FLUSH PRIVILEGES; --connect node_2a, 127.0.0.1, user1, pass1, test, $NODE_MYPORT_2 --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_ftwrl.test b/mysql-test/suite/galera/t/galera_ftwrl.test new file mode 100644 index 00000000000..db9bd132566 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ftwrl.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# At this time, issing a FLUSH TABLES WITH READ LOCK causes SELECT and SHOW to hang if +# casuality can not be ensured because another node issued a statement in the meantime +# which could not be applied because FTWRL blocks the applier as well +# +# See LP bug 1271177 +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options;` +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +FLUSH TABLES WITH READ LOCK; + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SHOW TABLES; + +--error ER_LOCK_WAIT_TIMEOUT +SELECT * FROM t1; + +UNLOCK TABLES; + +SHOW TABLES; +SELECT COUNT(*) = 1 FROM t1; + +--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/t/galera_fulltext.test b/mysql-test/suite/galera/t/galera_fulltext.test new file mode 100644 index 00000000000..aa93a336f92 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_fulltext.test @@ -0,0 +1,62 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# InnoDB FULLTEXT indexes +# + +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/t/galera_gcs_fc_limit.test b/mysql-test/suite/galera/t/galera_gcs_fc_limit.test new file mode 100644 index 00000000000..e15da0e35ad --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gcs_fc_limit.test @@ -0,0 +1,52 @@ +# +# Test that under gcs.fc_limit=1 on the slave, transactions on the master can not commit. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; + +# Block the slave applier thread +FLUSH TABLES WITH READ LOCK; + +--connection node_1 + +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); + +# This query will hang because flow control will kick in +--send +INSERT INTO t1 VALUES (5); +--sleep 1 + +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'query end' AND INFO = 'INSERT INTO t1 VALUES (5)'; + +--connection node_2 +# Unblock the slave applier thread +UNLOCK TABLES; + +--connection node_1 +--reap + +INSERT INTO t1 VALUES (6); + +--connection node_2 +# Replication catches up and continues normally +SELECT COUNT(*) = 6 FROM t1; + +--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/t/galera_gcs_max_packet_size.cnf b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf new file mode 100644 index 00000000000..aae3fee5904 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf @@ -0,0 +1,5 @@ +!include ../galera_2nodes.cnf +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcs.max_packet_size=64' +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcs.max_packet_size=64' diff --git a/mysql-test/suite/galera/t/galera_gcs_max_packet_size.test b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.test new file mode 100644 index 00000000000..cafd8acfdd9 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.test @@ -0,0 +1,25 @@ +# +# Test fragmentation by setting gcs.max_packet_size to a low value +# The actual setting is performed in galera_gcs_max_packet_size.cnf +# as gcs.max_packet_size is not a dynamic variable +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +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; +CREATE TABLE t2 (f1 VARCHAR(512) UNIQUE) ENGINE=InnoDB; + +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +INSERT INTO t2 VALUES (REPEAT('x', 512)); + +--connection node_2 +SELECT COUNT(*) = 10000 FROM t1; +SELECT LENGTH(f1) = 512 FROM t2 WHERE f1 = REPEAT('x', 512); + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_gtid-master.opt b/mysql-test/suite/galera/t/galera_gtid-master.opt new file mode 100644 index 00000000000..8a755e98b00 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gtid-master.opt @@ -0,0 +1 @@ +--log-bin --log-slave-updates diff --git a/mysql-test/suite/galera/t/galera_gtid.test b/mysql-test/suite/galera/t/galera_gtid.test new file mode 100644 index 00000000000..e8369be62e6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gtid.test @@ -0,0 +1,27 @@ +# +# Test GTID for basic Galera operations +# + +--source include/have_log_bin.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +UPDATE t1 SET f1 = 2; + +--let $gtid_binlog_state_node2 = `SELECT @@global.gtid_binlog_state;` + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; + +--disable_query_log +--eval SELECT '$gtid_binlog_state_node2' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_insert_ignore.test b/mysql-test/suite/galera/t/galera_insert_ignore.test new file mode 100644 index 00000000000..4b4b0a6e9fb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_insert_ignore.test @@ -0,0 +1,60 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_sync_wait_orig = (SELECT @@wsrep_sync_wait) +SET GLOBAL wsrep_sync_wait = 7; + +--connection node_2 +SET GLOBAL wsrep_sync_wait = 7; + + +# +# INSERT IGNORE with PRIMARY KEY +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +INSERT IGNORE INTO t1 VALUES (1), (2); +SELECT * FROM t1; + +--connection node_2 +SELECT * FROM t1; + +# +# INSERT IGNORE ... SELECT +# + +--connection node_2 +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (0), (2), (3); +INSERT IGNORE INTO t1 SELECT f1 FROM t2; + +SELECT * FROM t1; +--connection node_1 +SELECT * FROM t1; + +# +# INSERT IGNORE with UNIQUE + NULLs +# + +--connection node_2 +CREATE TABLE t3 (f1 INTEGER UNIQUE) Engine=InnoDB; +INSERT INTO t3 VALUES (NULL); + +--connection node_1 +INSERT IGNORE INTO t3 VALUES (1), (NULL), (2); +SELECT * FROM t3; + +--connection node_2 +SELECT * FROM t3; + +--eval SET GLOBAL wsrep_sync_wait = $wsrep_sync_wait_orig + +--connection node_1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +--eval SET GLOBAL wsrep_sync_wait = $wsrep_sync_wait_orig + diff --git a/mysql-test/suite/galera/t/galera_insert_multi.test b/mysql-test/suite/galera/t/galera_insert_multi.test new file mode 100644 index 00000000000..d62283aff69 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_insert_multi.test @@ -0,0 +1,122 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Multi-row INSERT with a PK +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); + +--connection node_2 +INSERT INTO t1 VALUES (3),(4); + +--connection node_1 +SELECT COUNT(*) = 4 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 4 FROM t1; + +DROP TABLE t1; + +# +# Multi-row INSERT without a PK +# + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER, KEY (f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(1); + +--connection node_1 +INSERT INTO t1 VALUES (2),(2); + +--connection node_2 +SELECT COUNT(*) = 4 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 4 FROM t1; + +DROP TABLE t1; + +# +# Error in the middle of a multi-row INSERT +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (1); + +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +DROP TABLE t1; + +# +# Deadlock +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET AUTOCOMMIT = OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2); + +--connection node_2 +SET AUTOCOMMIT = OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +# Workaround for mysql-wsrep#39 Transaction receives deadlock error twice in row +--error 0,ER_LOCK_DEADLOCK +ROLLBACK; + +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES (1), (2); + +DROP TABLE t1; + +# +# Rollback +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2); + +--connection node_2 +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); + +--connection node_1 +ROLLBACK; + +--connection node_2 +COMMIT; +SELECT COUNT(*) = 2 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; + + + + + + + diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf new file mode 100644 index 00000000000..85245ff464a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf @@ -0,0 +1,12 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=xtrabackup-v2 +innodb_flush_log_at_trx_commit=0 + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test new file mode 100644 index 00000000000..07838702deb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test @@ -0,0 +1,12 @@ +# +# This test performs server kill and IST while innodb_flush_logs_on_trx_commit = 0 +# This confirms that IST can properly catch up even in the face of relaxed single-node durability +# +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.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_ist_mysqldump.cnf b/mysql-test/suite/galera/t/galera_ist_mysqldump.cnf new file mode 100644 index 00000000000..db6b7d5e129 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mysqldump.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;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_mysqldump.test b/mysql-test/suite/galera/t/galera_ist_mysqldump.test new file mode 100644 index 00000000000..a9ff8c41f06 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mysqldump.test @@ -0,0 +1,17 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_sst_set_mysqldump.inc + +# mysql-wsrep#33 - nnoDB: Failing assertion: xid_seqno > trx_sys_cur_xid_seqno in trx_sys_update_wsrep_checkpoint with mysqldump IST +# --source suite/galera/include/galera_st_disconnect_slave.inc + +# We set the required mysqldump SST options here so that they are used every time the server is restarted during the test +--let $start_mysqld_params = --wsrep_sst_auth=sst:sst --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2 --skip-grant-tables + +--source suite/galera/include/galera_st_shutdown_slave.inc +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc + +--source suite/galera/include/galera_sst_restore.inc diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.cnf b/mysql-test/suite/galera/t/galera_ist_restart_joiner.cnf new file mode 100644 index 00000000000..10958aad9a8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test new file mode 100644 index 00000000000..69446f0f86a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test @@ -0,0 +1,106 @@ +# +# Test that a joiner performing IST can be killed and restarted with no adverse consequences. +# This is achieved by using the recv_IST_after_apply_trx Galera dbug sync point to block IST after +# one transaction has been applied. When IST blocks, we kill and restart the joiner +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source suite/galera/include/galera_have_debug_sync.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'a'),(6, 'a'); + +# Disconnect node #2 +--connection node_2 +--source suite/galera/include/galera_unload_provider.inc + +--connection node_1 +UPDATE t1 SET f2 = 'b' WHERE f1 > 1; + +# Wait until node #1 has left +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +UPDATE t1 SET f2 = 'c' WHERE f1 > 2; + +--connection node_2 +# Make sure IST will block ... +SET GLOBAL wsrep_provider_options = 'dbug=d,recv_IST_after_apply_trx'; +SET SESSION wsrep_sync_wait = 0; + + +# 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 + +--let KILL_NODE_PIDFILE = `SELECT @@pid_file` + +# ... and restart provider to force IST +--echo Loading wsrep_provider ... +--disable_query_log +--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +# We can not use a wait_condition on SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS as such queries are blocked during IST +# so we perform a simple sleep and SHOW instead + +--sleep 5 +SHOW STATUS LIKE 'wsrep_debug_sync_waiters'; + +--connection node_1 +# Perform DML and DDL while IST is in progress +--connection node_1 +UPDATE t1 SET f2 = 'd' WHERE f1 > 3; +CREATE TABLE t2 (f1 INTEGER); + +# Kill node #2 while IST is in progress +--connection node_2 + +# Kill the connected server +--disable_reconnect + +--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 + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Perform DML and DDL while node #2 is down +UPDATE t1 SET f2 = 'e' WHERE f1 > 4; +CREATE TABLE t3 (f1 INTEGER); + +--connection node_2 + +--let $galera_wsrep_recover_server_id=2 +--source suite/galera/include/galera_wsrep_recover.inc + +--echo Starting server ... +--source include/start_mysqld.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_1 +UPDATE t1 SET f2 = 'f' WHERE f1 > 5; +SELECT * FROM t1; + +--connection node_2 +SELECT * FROM t1; +SELECT COUNT(*) = 0 FROM t2; +SELECT COUNT(*) = 0 FROM t3; + +--connection node_1 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera/t/galera_ist_rsync.cnf b/mysql-test/suite/galera/t/galera_ist_rsync.cnf new file mode 100644 index 00000000000..bbe0f6047fb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_rsync.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_rsync.test b/mysql-test/suite/galera/t/galera_ist_rsync.test new file mode 100644 index 00000000000..41d1a0c1fc2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_rsync.test @@ -0,0 +1,8 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_st_disconnect_slave.inc +--source suite/galera/include/galera_st_shutdown_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_ist_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf new file mode 100644 index 00000000000..21e597445a8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=xtrabackup-v2 + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.test b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.test new file mode 100644 index 00000000000..8b399e77794 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.test @@ -0,0 +1,9 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_st_disconnect_slave.inc +--source suite/galera/include/galera_st_shutdown_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_kill_ddl.test b/mysql-test/suite/galera/t/galera_kill_ddl.test new file mode 100644 index 00000000000..3c2bce5b9c9 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_kill_ddl.test @@ -0,0 +1,39 @@ +# +# This test kill -9-s a slave while small updates have been performed on the master. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +# Enable the master to continue running during the split-brain situation that +# occurs when the slave is killed +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +--source include/start_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1 +--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/t/galera_kill_largechanges.test b/mysql-test/suite/galera/t/galera_kill_largechanges.test new file mode 100644 index 00000000000..e9a32ce813b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_kill_largechanges.test @@ -0,0 +1,43 @@ +# +# This test kill -9-s a slave while a large update has been performed on the master. SST is performed. +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +# Enable the master to continue running during the split-brain situation that +# occurs when the slave is killed +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 VARCHAR(128)) ENGINE=InnoDB; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +# We create a 128Mb (or so) transaction that is larger than gcache. The size of the gcache is not adjustable dynamically +INSERT INTO t1 SELECT REPEAT('a', 128) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6; + +--connection node_2 +--source include/start_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 1000000 FROM 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; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_kill_nochanges.test b/mysql-test/suite/galera/t/galera_kill_nochanges.test new file mode 100644 index 00000000000..1903df449e4 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_kill_nochanges.test @@ -0,0 +1,24 @@ +# +# This test kill -9-s a slave while no updates have been performed on the master. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--source include/kill_galera.inc +--source include/start_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 1 FROM t1; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_kill_smallchanges.test b/mysql-test/suite/galera/t/galera_kill_smallchanges.test new file mode 100644 index 00000000000..d998032cbc3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_kill_smallchanges.test @@ -0,0 +1,39 @@ +# +# This test kill -9-s a slave while small updates have been performed on the master. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +# Enable the master to continue running during the split-brain situation that +# occurs when the slave is killed +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--source include/start_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 1 FROM 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/t/galera_lock_table.test b/mysql-test/suite/galera/t/galera_lock_table.test new file mode 100644 index 00000000000..bd581842f6f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_lock_table.test @@ -0,0 +1,43 @@ +# +# Test that a LOCK TABLE on the slave will cause the applier thread to block, so no subsequent updates +# are replicated on the slave until UNLOCK TABLE is issued. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_sync_wait_orig = `SELECT @@wsrep_sync_wait` + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +LOCK TABLE t1 READ; + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +# We use a separate connection here so that we can SELECT from both tables +# without running into "table t2 was not locked" error. + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +SET SESSION wsrep_sync_wait=0; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; + +--connection node_2 +UNLOCK TABLES; + +--disable_query_log +--eval SET SESSION wsrep_sync_wait=$wsrep_sync_wait_orig; +--enable_query_log + +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 1 FROM t2; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_log_bin-master.opt b/mysql-test/suite/galera/t/galera_log_bin-master.opt new file mode 100644 index 00000000000..8a755e98b00 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_bin-master.opt @@ -0,0 +1 @@ +--log-bin --log-slave-updates diff --git a/mysql-test/suite/galera/t/galera_log_bin.test b/mysql-test/suite/galera/t/galera_log_bin.test new file mode 100644 index 00000000000..7d592d63ee3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_bin.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test Galera with --log-bin --log-slave-updates . +# This way the actual MySQL binary log is used, +# rather than Galera's own implementation +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (id INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 2 FROM t2; + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +FLUSH LOGS; +# Use pos 120 in order to skip the header that contains the MySQL version number. +# Otherwise, version number changes will cause the test to break +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' LIMIT 4,18; + +--connection node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' LIMIT 3,19; + +DROP TABLE t1; +DROP TABLE t2; + diff --git a/mysql-test/suite/galera/t/galera_log_output_csv-master.opt b/mysql-test/suite/galera/t/galera_log_output_csv-master.opt new file mode 100644 index 00000000000..2f71b140b65 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_output_csv-master.opt @@ -0,0 +1 @@ +--log-output=TABLE --log-queries-not-using-indexes --general-log --slow-query-log diff --git a/mysql-test/suite/galera/t/galera_log_output_csv.test b/mysql-test/suite/galera/t/galera_log_output_csv.test new file mode 100644 index 00000000000..00009396f6a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_output_csv.test @@ -0,0 +1,27 @@ +# +# Test that --log-output=FILE works with Galera. +# The relevant options are set using a -master.opt file +# wsrep_replicate_myisam is not used as it crashes in MTR with mysql-wsrep#14 +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SELECT COUNT(*) > 0 FROM mysql.general_log; + +SELECT 1 = 1 FROM t1; +SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 1 = 1 FROM t1'; + +--connection node_2 + +# CREATE TABLE from master is also present in the slave query log, but is logged twice, mysql-wsrep#44 +SELECT COUNT(*) > 0 FROM mysql.general_log WHERE argument = 'CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB'; + +SELECT 2 = 2 FROM t1; +SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 2 = 2 FROM t1'; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_many_columns.test b/mysql-test/suite/galera/t/galera_many_columns.test index 09bd9902e81..3f596179c01 100644 --- a/mysql-test/suite/galera/t/galera_many_columns.test +++ b/mysql-test/suite/galera/t/galera_many_columns.test @@ -2,20 +2,18 @@ --source include/galera_cluster.inc --source include/have_innodb.inc -CREATE TABLE t1 (f1017 VARCHAR(3) DEFAULT 'ABC') ENGINE=InnoDB; - ---let $count = 1016 +--disable_query_log +SET @create_var1 = ""; +--let $count = 1017 while ($count) { - --disable_query_log - --eval SET @ddl_var1 = CONCAT("ALTER TABLE t1 ADD COLUMN f", $count, " VARCHAR(3) DEFAULT 'ABC'") - --let $ddl_var = `SELECT @ddl_var1` - --enable_query_log - --eval $ddl_var + --eval SET @create_var1 = CONCAT(@create_var1, "f", $count, " VARCHAR(3) DEFAULT 'ABC', ") --dec $count } -ALTER TABLE t1 ADD PRIMARY KEY (f1, f1017); +--let $create_var = `SELECT @create_var1` +--eval CREATE TABLE t1 ($create_var PRIMARY KEY (f1, f1017)) ENGINE=InnoDB; +--enable_query_log INSERT INTO t1 (f1) VALUES (DEFAULT); diff --git a/mysql-test/suite/galera/t/galera_many_rows.test b/mysql-test/suite/galera/t/galera_many_rows.test index 5ec1af0a8bf..0f4c4c0db78 100644 --- a/mysql-test/suite/galera/t/galera_many_rows.test +++ b/mysql-test/suite/galera/t/galera_many_rows.test @@ -3,7 +3,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc -CREATE TABLE ten (f1 INTEGER) ENGINE=INNODB; +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; diff --git a/mysql-test/suite/galera/t/galera_many_tables_nopk.test b/mysql-test/suite/galera/t/galera_many_tables_nopk.test new file mode 100644 index 00000000000..2496d145c93 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_many_tables_nopk.test @@ -0,0 +1,103 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# This test forces 1K tables without a PK to participate in a single transaction +# + +# +# First, create 1K tables +# + +--connection node_1 + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("CREATE TABLE t", $count, " (f1 INTEGER) ENGINE=InnoDB")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("INSERT INTO t", $count, " VALUES (1234)")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +# +# Second, perform 1K updates +# + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("UPDATE t", $count, " SET f1 = 1")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +COMMIT; + +# Third, confirm that all the inserts have arrived on the second node +# + +--connection node_2 +CREATE TABLE sum_table (f1 INTEGER); + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("INSERT INTO sum_table SELECT COUNT(*) FROM t", $count)` + --eval $ddl_var + --enable_query_log + --dec $count +} + +SELECT SUM(f1) = 1000 FROM sum_table; + +# +# Fourth, create a deadlock +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("UPDATE t", $count, " SET f1 = 2")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1000 SET f1 = 3; + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +DROP SCHEMA test; +CREATE SCHEMA test; diff --git a/mysql-test/suite/galera/t/galera_many_tables_pk.test b/mysql-test/suite/galera/t/galera_many_tables_pk.test new file mode 100644 index 00000000000..886cb7c1a00 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_many_tables_pk.test @@ -0,0 +1,98 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# This test forces 1K tables with a PK to participate in a single transaction +# + +# +# First, create 1K tables and make sure the DDLs are all propagated +# + +--connection node_1 + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("CREATE TABLE t", $count, " (f1 INTEGER AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +--connection node_2 +SELECT COUNT(*) = 1000 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%'; + +# +# Second, create a transaction that uses all those tables +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("INSERT INTO t", $count, " VALUES (DEFAULT)")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +COMMIT; + +# +# Third, confirm that all the inserts have arrived on the second node +# + +--connection node_2 +CREATE TABLE sum_table (f1 INTEGER); + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("INSERT INTO sum_table SELECT COUNT(*) FROM t", $count)` + --eval $ddl_var + --enable_query_log + --dec $count +} + +SELECT SUM(f1) = 1000 FROM sum_table; + +# +# Fourth, create a deadlock +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--let $count = 1000 +while ($count) +{ + --disable_query_log + --let $ddl_var = `SELECT CONCAT("UPDATE t", $count, " SET f1 = 2")` + --eval $ddl_var + --enable_query_log + --dec $count +} + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1000 SET f1 = 3; + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +DROP SCHEMA test; +CREATE SCHEMA test; diff --git a/mysql-test/suite/galera/t/galera_migrate.cnf b/mysql-test/suite/galera/t/galera_migrate.cnf new file mode 100644 index 00000000000..47bdf53afef --- /dev/null +++ b/mysql-test/suite/galera/t/galera_migrate.cnf @@ -0,0 +1,59 @@ +# +# This .cnf file starts 4 servers without enabling Galera. +# The galera_migrate.test will set wsrep_provider and the other settings as needed. +# + +!include include/default_mysqld.cnf + +[mysqld] +binlog-format=row +innodb_autoinc_lock_mode=2 +innodb_flush_log_at_trx_commit=2 +log-bin=mysqld-bin + +wsrep_node_address=127.0.0.1 +wsrep_causal_reads=ON +wsrep_sync_wait = 7 + +[mysqld.1] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +[mysqld.2] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +[mysqld.3] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +[mysqld.4] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +NODE_MYSOCK_2= @mysqld.2.socket + +NODE_MYPORT_3= @mysqld.3.port +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/t/galera_migrate.test b/mysql-test/suite/galera/t/galera_migrate.test new file mode 100644 index 00000000000..873640b88d4 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_migrate.test @@ -0,0 +1,204 @@ +# +# Execute a migration from MariaDB replication to Galera replication. +# The test starts with 4 stand-alone servers defined by galera_migrate.cnf and then +# performs the following steps: +# +# 1. Begin with a single MySQL server +# 2. Establish traditional MySQL master-slave replication +# 3. Attach a new sever to serve as a MySQL replication slave +# 4. Enable Galera on the new slave and create a single-node Galera cluster +# 5. Attach a second Galera node +# 6. Turn off the traditional replication parts of the system +# 7. Continue replicating within Galera only +# + +--source include/big_test.inc +--source include/have_innodb.inc +--source include/have_log_bin.inc + +# +# Step #1 Begin with a single server +# + +--connect node_1, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# +# Step #2. Establish traditional MySQL replication +# + +--connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT = $NODE_MYPORT_1; +--enable_query_log +START SLAVE; + +--connection node_1 +INSERT INTO t1 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 t1; +--source include/wait_condition.inc + +# +# Step #3. Attach a second slave, later to be converted to Galera +# + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--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 +INSERT INTO t1 VALUES (3); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +# +# Step #4. Convert this MySQL slave into a Galera node +# + +--connection node_1 +INSERT INTO t1 VALUES (4); + +--connection node_3 +--disable_query_log +--eval SET GLOBAL wsrep_provider='$WSREP_PROVIDER' +--eval SET GLOBAL wsrep_provider_options='base_port=$NODE_GALERAPORT_3' +--enable_query_log +SET GLOBAL wsrep_cluster_address='gcomm://'; + +--connection node_1 +INSERT INTO t1 VALUES (5); + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--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 VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1 +INSERT INTO t1 VALUES (6); + +# +# Step #5. Attach a second Galera node using mysqldump SST +# + +--connection node_3 +# We need a user with a password for mysqldump SST +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:sst'; + +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 +GRANT ALL PRIVILEGES ON *.* TO 'sst' IDENTIFIED BY 'sst'; + +--disable_query_log +--eval SET GLOBAL wsrep_sst_method = 'mysqldump'; +--eval SET GLOBAL wsrep_provider='$WSREP_PROVIDER' +--eval SET GLOBAL wsrep_provider_options='base_port=$NODE_GALERAPORT_4' +--eval SET GLOBAL wsrep_sst_receive_address = '127.0.0.2:$NODE_MYPORT_4'; +--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_3' +--enable_query_log + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--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 VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +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'; + + +# +# Step #6. Turn off traditional replication +# + +--connection node_2 +STOP SLAVE; +RESET SLAVE ALL; + +--connection node_3 +STOP SLAVE; +RESET SLAVE ALL; + +# +# Step #7. Continue replicating within Galera only +# + +# We need fresh connections due to galera#191 + +--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3 +INSERT INTO t1 VALUES (7); + +--connect node_4a, 127.0.0.1, root, , test, $NODE_MYPORT_4 +INSERT INTO t1 VALUES (8); + +--connection node_4a +SELECT COUNT(*) = 8 FROM t1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +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'; + +--connection node_3a +SELECT COUNT(*) = 8 FROM t1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +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'; + +# +# Teardown +# + +--connection node_1 +DROP TABLE t1; + +--connection node_2 +DROP TABLE t1; + +--connection node_3 +SET GLOBAL wsrep_provider = 'none'; +SET GLOBAL wsrep_sst_auth = ''; +SET GLOBAL wsrep_provider_options = ''; +DROP TABLE t1; +DROP USER sst; + +--connection node_4 +SET GLOBAL wsrep_provider = 'none'; +SET GLOBAL wsrep_sst_method = 'rsync'; +SET GLOBAL wsrep_provider_options = ''; +SET GLOBAL wsrep_sst_receive_address = 'AUTO'; +DROP TABLE t1; +DROP USER sst; + +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); diff --git a/mysql-test/suite/galera/t/galera_multi_database.test b/mysql-test/suite/galera/t/galera_multi_database.test new file mode 100644 index 00000000000..6e06aaaa2c6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_multi_database.test @@ -0,0 +1,43 @@ +# +# Test that identical updates can be delivered to two separate +# databases without this causing a certification conflict +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE DATABASE d1; +CREATE TABLE d1.t1(f1 INTEGER) ENGINE=InnoDB; + +CREATE DATABASE d2; +CREATE TABLE d2.t1(f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO d1.t1 VALUES (1); + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO d2.t1 VALUES (1); + +--connection node_1 +COMMIT; + +--connection node_2 +COMMIT; + +SELECT COUNT(*) = 1 FROM d1.t1; +SELECT COUNT(*) = 1 FROM d2.t1; + +--connection node_1 + +SELECT COUNT(*) = 1 FROM d1.t1; +SELECT COUNT(*) = 1 FROM d2.t1; + +DROP TABLE d1.t1; +DROP TABLE d2.t1; + +DROP DATABASE d1; +DROP DATABASE d2; diff --git a/mysql-test/suite/galera/t/galera_myisam_autocommit.test b/mysql-test/suite/galera/t/galera_myisam_autocommit.test new file mode 100644 index 00000000000..b01b5dc07f7 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_myisam_autocommit.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# This tests simple autocommit replication of MyISAM tables. No updates arrive on the slave. +# + +# Without a PK + +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2), (3); +INSERT INTO t1 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; + +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2), (3); +INSERT INTO t2 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; + +# Error +--error ER_DUP_ENTRY +INSERT INTO t2 VALUES (6), (1); + +# UPDATE + +UPDATE t1 SET f1 = 9; +UPDATE t2 SET f1 = 9 WHERE f1 = 1; + +# DELETE + +DELETE FROM t1 WHERE f1 = 9; +DELETE FROM t2 WHERE f1 = 9; + +# TRUNCATE + +TRUNCATE TABLE t1; +TRUNCATE TABLE t1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_myisam_transactions.test b/mysql-test/suite/galera/t/galera_myisam_transactions.test new file mode 100644 index 00000000000..00e0bf3fdca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_myisam_transactions.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# This tests MyISAM tables in transactions. No MyISAM updates arrive on the slave, but InnoDB ones do. +# + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t3 (f1 INTEGER) ENGINE=MyISAM; + +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (NEW.f1); + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM t2; +SELECT COUNT(*) = 0 FROM t2; + +--connection node_1 +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +ROLLBACK; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM t2; +SELECT COUNT(*) = 0 FROM t2; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera/t/galera_nopk_unicode.test b/mysql-test/suite/galera/t/galera_nopk_unicode.test new file mode 100644 index 00000000000..e036e14ebe0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_nopk_unicode.test @@ -0,0 +1,43 @@ +# +# Test non-ascii data in table without a PK +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 ( + f1 VARCHAR(255), + KEY (f1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES ('текÑÑ‚'); + +--connection node_2 +SELECT f1 = 'текÑÑ‚' FROM t1; + +# +# Provoke a conflict +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚2'; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚3'; + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +SELECT f1 = 'текÑÑ‚2' FROM t1; +SELECT f1 = 'текÑÑ‚2' FROM t1 WHERE f1 = 'текÑÑ‚2'; + + +DROP TABLE t1; 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 new file mode 100644 index 00000000000..a071a1fab1b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test @@ -0,0 +1,51 @@ +# +# Test that a LOCK TABLE on the slave will cause all applier threads to block, +# Even though the two INSERTS are independent transactions, the fact that t1 is locked +# prevents the applier thread from committing the insert against t2, as commits are done +# in order. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 + +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +--let $wsrep_sync_wait_orig = `SELECT @@wsrep_sync_wait` + +SET GLOBAL wsrep_slave_threads = 2; +LOCK TABLE t1 READ; + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +# We use a separate connection here so that we can SELECT from both tables +# without running into "table t2 was not locked" error. + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--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 level lock%'; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; + +--connection node_2 +UNLOCK TABLES; + +--connection node_2a +--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 'closing tables'; + +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test new file mode 100644 index 00000000000..a192044754d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test @@ -0,0 +1,50 @@ +## +## 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 + +--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; +--connection node_2 +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +SET GLOBAL wsrep_slave_threads = 4; + +--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(*) = 5 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/t/galera_parallel_autoinc_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test new file mode 100644 index 00000000000..d67eba4d37c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test @@ -0,0 +1,53 @@ +## +## Tests the parallel application of many small-ish 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 + +--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; +--connection node_2 +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +SET GLOBAL wsrep_slave_threads = 4; + +--connection node_1 +--let $count = 1000 +while ($count) +{ + --disable_query_log + INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1; + --enable_query_log + --dec $count +} + +--connection node_2 +--let $count = 1000 +while ($count) +{ + --disable_query_log + INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1; + --enable_query_log + --dec $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 'closing tables'; + +--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/t/galera_parallel_simple.test b/mysql-test/suite/galera/t/galera_parallel_simple.test new file mode 100644 index 00000000000..a1429954980 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_parallel_simple.test @@ -0,0 +1,45 @@ +# +# Test that SHOW PROCESSLIST reports that two slave threads have been involved in applying +# two independent transactions +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` + +CREATE TABLE t1 (id INT) ENGINE=InnoDB; +CREATE TABLE t2 (id INT) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL wsrep_slave_threads = 2; + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +--connection node_2 + +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 6 FROM t2; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'closing tables'; + +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_pc_ignore_sb.test b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test new file mode 100644 index 00000000000..f63215ebe4a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test @@ -0,0 +1,49 @@ +# +# Test pc.ignore_sb=true wsrep_provider option . Killing one node should leave the other running. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Save original auto_increment_offset values. +--connection node_1 +let $auto_increment_offset_node_1 = `SELECT @@global.auto_increment_offset`; +--connection node_2 +let $auto_increment_offset_node_2 = `SELECT @@global.auto_increment_offset`; + +--connection node_1 +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` + +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +DROP TABLE t1; + +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; + +# Reset the master and restart the slave so that post-test checks can run + +SET GLOBAL wsrep_cluster_address = ''; +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +--connection node_2 +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +--disable_query_log +# Restore original auto_increment_offset values. +--connection node_1 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_1; +--connection node_2 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_2; +--enable_query_log diff --git a/mysql-test/suite/galera/t/galera_pk_bigint_signed.test b/mysql-test/suite/galera/t/galera_pk_bigint_signed.test new file mode 100644 index 00000000000..12a8a8f5d64 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_pk_bigint_signed.test @@ -0,0 +1,46 @@ +# +# PK that is a BIGINT SIGNED +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 BIGINT SIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES + (-9223372036854775808, 'min'), + (9223372036854775807, 'max') +; + +--connection node_2 +SELECT * FROM t1; + +UPDATE t1 SET f2 = CONCAT(f2, '_'); + +--connection node_1 +SELECT * FROM t1; + +# +# Deadlock +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'foo' WHERE f1 = -9223372036854775808; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'bar' WHERE f1 = -9223372036854775808; + +--connection node_1 +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; +SET AUTOCOMMIT=ON; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_pk_bigint_unsigned.test b/mysql-test/suite/galera/t/galera_pk_bigint_unsigned.test new file mode 100644 index 00000000000..2bb02d5ea4e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_pk_bigint_unsigned.test @@ -0,0 +1,45 @@ +# +# PK that is a BIGINT UNSIGNED +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 BIGINT UNSIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES + (18446744073709551615, 'max') +; + +--connection node_2 +SELECT f1 = 18446744073709551615 FROM t1; + +UPDATE t1 SET f2 = CONCAT(f2, '_'); + +--connection node_1 +SELECT f1 = 18446744073709551615 FROM t1; + +# +# Deadlock +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'foo' WHERE f1 = 18446744073709551615; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f2 = 'bar' WHERE f1 = 18446744073709551615; + +--connection node_1 +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; +SET AUTOCOMMIT=ON; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_query_cache-master.opt b/mysql-test/suite/galera/t/galera_query_cache-master.opt new file mode 100644 index 00000000000..cb983993b91 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache-master.opt @@ -0,0 +1,3 @@ +--query_cache_type=1 --query_cache_size=1355776 + + diff --git a/mysql-test/suite/galera/t/galera_query_cache.test b/mysql-test/suite/galera/t/galera_query_cache.test new file mode 100644 index 00000000000..900faba0e1b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache.test @@ -0,0 +1,67 @@ +--source include/have_query_cache.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Ensure that the query cache behaves properly with respect to Galera +# +# * in the absence of updates, the query cache does serve cached results +# * any cache-invalidating query on the remote node also causes the local cache to be invalidated +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +RESET QUERY CACHE; +FLUSH STATUS; + +# +# 1. Cache works +# + +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; + +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; + +# +# 2. Cache is invalidated by DML on remote node +# + +--connection node_1 +INSERT INTO t1 VALUES (2); + +--connection node_2 +FLUSH STATUS; + +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; + +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; + +# +# 3. Cache is invalidated by DDL on remote node +# + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +FLUSH STATUS; + +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Qcache_queries_in_cache'; + +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +SELECT COUNT(*) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_read_only.test b/mysql-test/suite/galera/t/galera_read_only.test new file mode 100644 index 00000000000..828f35d2ba3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_read_only.test @@ -0,0 +1,23 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Ensure that the read_only option does not apply to Galera appliers and that replication +# continues, the way MySQL replication would. +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL read_only=TRUE; + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +SET GLOBAL read_only=FALSE; + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_repl_key_format_flat16.test b/mysql-test/suite/galera/t/galera_repl_key_format_flat16.test new file mode 100644 index 00000000000..8749c20faed --- /dev/null +++ b/mysql-test/suite/galera/t/galera_repl_key_format_flat16.test @@ -0,0 +1,34 @@ +# +# Test repl.key_format = FLAT16 . Since it is very difficult to cause a collision on a 16-byte hash, +# we simply verify that the option is settable and that replication works. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'repl.key_format=FLAT16'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (123); + +CREATE TABLE t2 (f1 VARCHAR(256)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (REPEAT('a', 256)); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +UPDATE t1 SET f1 = 234; +UPDATE t2 SET f1 = REPEAT('b', 256); + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 234; +SELECT COUNT(*) = 1 FROM t2 WHERE f1 = REPEAT('b', 256); + + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_repl_max_ws_size.test b/mysql-test/suite/galera/t/galera_repl_max_ws_size.test new file mode 100644 index 00000000000..37a2f7d4ce3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_repl_max_ws_size.test @@ -0,0 +1,25 @@ +# +# Test repl.max_ws_size . A transaction larger than this size can not commit. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` + +CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB; + +SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512'; + +--error ER_ERROR_DURING_COMMIT +INSERT INTO t1 VALUES (REPEAT('a', 512)); + +SELECT COUNT(*) = 0 FROM t1; + +--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/t/galera_restart_nochanges.test b/mysql-test/suite/galera/t/galera_restart_nochanges.test new file mode 100644 index 00000000000..8eb7617b8a6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_restart_nochanges.test @@ -0,0 +1,23 @@ +# +# This test restarts a slave while no updates have been performed on the master. No SST is performed. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--source include/restart_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 1 FROM t1; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_rsu_add_pk.test b/mysql-test/suite/galera/t/galera_rsu_add_pk.test new file mode 100644 index 00000000000..7db990d7be1 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_rsu_add_pk.test @@ -0,0 +1,43 @@ +# +# ALTER TABLE ... ADD PRIMARY KEY under Rolling Schema Upgrade +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +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; + +--connection node_2 +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_OSU_method = "TOI"; + +# Insert values after the ALTER +INSERT INTO t1 (f1) SELECT 200000 + (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; + + +SELECT COUNT(*) = 300000 FROM t1; +SELECT MAX(f1) = 299999 FROM t1; + +--connection node_1 +--reap +SELECT COUNT(*) = 300000 FROM t1; +SELECT MAX(f1) = 299999 FROM t1; + +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_OSU_method = "TOI"; + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_rsu_drop_pk.test b/mysql-test/suite/galera/t/galera_rsu_drop_pk.test new file mode 100644 index 00000000000..e64259494d1 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_rsu_drop_pk.test @@ -0,0 +1,58 @@ +# +# ALTER TABLE ... DROP PRIMARY KEY under Rolling Schema Upgrade +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) 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; + +--connection node_2 +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 DROP PRIMARY KEY; +SET SESSION wsrep_OSU_method = "TOI"; + +# Insert even more data after the ALTER has completed +INSERT INTO t1 (f1) SELECT 200000 + (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; + +SELECT COUNT(*) = 300000 FROM t1; +SELECT MAX(f1) = 299999 FROM t1; + +--connection node_1 +--reap +SELECT COUNT(*) = 300000 FROM t1; +SELECT MAX(f1) = 299999 FROM t1; + +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 DROP PRIMARY KEY; +SET SESSION wsrep_OSU_method = "TOI"; + +# Insert some previously-conflicting values after the ALTER has been applied on all nodes. +--connection node_2 +INSERT INTO t1 (f1) VALUES (1); +INSERT INTO t1 (f1) VALUES (10); + +--connection node_1 +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 1; +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 10; + +INSERT INTO t1 (f1) VALUES (100); +INSERT INTO t1 (f1) VALUES (1000); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 100; +SELECT COUNT(*) = 2 FROM t1 WHERE f1 = 1000; + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_rsu_error.test b/mysql-test/suite/galera/t/galera_rsu_error.test new file mode 100644 index 00000000000..cad8154ac76 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_rsu_error.test @@ -0,0 +1,31 @@ +# +# Test DDL errors under Rolling Schema Upgrade +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t1 VALUES (1), (1); + +--connection node_2 +SET SESSION wsrep_OSU_method = "RSU"; +--error ER_DUP_ENTRY +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_OSU_method = "TOI"; + +# The ALTER has no effect +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 't1'; + +INSERT INTO t1 VALUES (1); + +--connection node_1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 3 FROM t1; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(3) = 4 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_rsu_simple.test b/mysql-test/suite/galera/t/galera_rsu_simple.test new file mode 100644 index 00000000000..5841dbd8006 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_rsu_simple.test @@ -0,0 +1,34 @@ +# +# Test Rolling Schema Upgrade +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +--connection node_2 +SET SESSION wsrep_OSU_method = "RSU"; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_1 +# The ALTER above is not visible on node_1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +# The INSERT above is now visible on node_2 +SELECT COUNT(*) = 1 FROM t1; + +INSERT INTO t1 (f1) VALUES (2); + +--connection node_1 +# The ALTER has not replicated +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +# However the INSERT above has +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_sbr.test b/mysql-test/suite/galera/t/galera_sbr.test new file mode 100644 index 00000000000..33f45c6b532 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sbr.test @@ -0,0 +1,27 @@ +# +# Test behavior if the user attempts to use statement-based replication +# +# SBR is not currently supported but we expect that no crashes or binlog-related assertions will be triggered. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--connection node_1 +#SET GLOBAL binlog_format = 'STATEMENT'; +SET SESSION binlog_format = 'STATEMENT'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION binlog_format = 'MIXED'; + +INSERT INTO t1 VALUES (2); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; + +--connection node_1 +SET GLOBAL binlog_format = 'ROW'; diff --git a/mysql-test/suite/galera/t/galera_sbr_binlog-master.opt b/mysql-test/suite/galera/t/galera_sbr_binlog-master.opt new file mode 100644 index 00000000000..beae84b3862 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sbr_binlog-master.opt @@ -0,0 +1 @@ +--log-bin diff --git a/mysql-test/suite/galera/t/galera_sbr_binlog.test b/mysql-test/suite/galera/t/galera_sbr_binlog.test new file mode 100644 index 00000000000..1291a4ff8a9 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sbr_binlog.test @@ -0,0 +1,28 @@ +# +# Test behavior if the user attempts to use statement-based replication +# +# SBR is not currently supported but we expect that no crashes or binlog-related assertions will be triggered. +# + +--source include/have_log_bin.inc +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--connection node_1 +#SET GLOBAL binlog_format = 'STATEMENT'; +SET SESSION binlog_format = 'STATEMENT'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION binlog_format = 'MIXED'; + +INSERT INTO t1 VALUES (2); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; + +--connection node_1 +SET GLOBAL binlog_format = 'ROW'; diff --git a/mysql-test/suite/galera/t/galera_split_brain.test b/mysql-test/suite/galera/t/galera_split_brain.test new file mode 100644 index 00000000000..c3e779618df --- /dev/null +++ b/mysql-test/suite/galera/t/galera_split_brain.test @@ -0,0 +1,53 @@ +# +# 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 +--source include/have_innodb.inc + +call mtr.add_suppression("WSREP: TO isolation failed for: "); + +--connection node_1 +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` + +# Save original auto_increment_offset values. +--connection node_1 +let $auto_increment_offset_node_1 = `SELECT @@global.auto_increment_offset`; +--connection node_2 +let $auto_increment_offset_node_2 = `SELECT @@global.auto_increment_offset`; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +--error ER_LOCK_DEADLOCK +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +# Reset the master and restart the slave so that post-test checks can run + +SET GLOBAL wsrep_cluster_address = ''; +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +--source include/start_mysqld.inc +--sleep 5 +--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 + +--sleep 5 + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--source include/wait_until_connected_again.inc + +# Restore original auto_increment_offset values. +--disable_query_log +--connection node_1 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_1; +--connection node_2a +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_2; +--enable_query_log + diff --git a/mysql-test/suite/galera/t/galera_sql_log_bin_zero.test b/mysql-test/suite/galera/t/galera_sql_log_bin_zero.test new file mode 100644 index 00000000000..b6965faa739 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sql_log_bin_zero.test @@ -0,0 +1,25 @@ +# +# Test SET SESSION sql_log_bin = 0 . We expect that unlogged updates will not be replicated +# to the slave and that there will be no assertions in the process. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION sql_log_bin = 0; + +INSERT INTO t1 VALUES (1); + +SET SESSION sql_log_bin = 1; + +INSERT INTO t1 VALUES (2); + + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ssl.cnf b/mysql-test/suite/galera/t/galera_ssl.cnf new file mode 100644 index 00000000000..1c22580cc15 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ssl.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M;socket.ssl=yes;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera-key.pem' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M;socket.ssl=yes;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera-key.pem' diff --git a/mysql-test/suite/galera/t/galera_ssl.test b/mysql-test/suite/galera/t/galera_ssl.test new file mode 100644 index 00000000000..8dc94dc1966 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ssl.test @@ -0,0 +1,24 @@ +# +# Test node connections over SSL. The accompanying galera_ssl.cnf has a customized +# wsrep_provider_options setting that enables SSL. +# +# At this time, the actual operation of SSL is not visible only in the error log and not in SHOW STATUS. +# So this test can only check that the cluster has formed and is replicating. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf new file mode 100644 index 00000000000..574ae28b54a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.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/t/galera_sst_mysqldump.test b/mysql-test/suite/galera/t/galera_sst_mysqldump.test new file mode 100644 index 00000000000..0b7171597dd --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.test @@ -0,0 +1,18 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_sst_set_mysqldump.inc + +--source suite/galera/include/galera_st_disconnect_slave.inc + +# We set the required mysqldump SST options here so that they are used every time the server is restarted during the test +--let $start_mysqld_params = --wsrep_sst_auth=sst:sst --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2 --skip-grant-tables + +--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 + +--source suite/galera/include/galera_sst_restore.inc diff --git a/mysql-test/suite/galera/t/galera_sst_rsync.cnf b/mysql-test/suite/galera/t/galera_sst_rsync.cnf new file mode 100644 index 00000000000..93981d9daa7 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync + +[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/t/galera_sst_rsync.test b/mysql-test/suite/galera/t/galera_sst_rsync.test new file mode 100644 index 00000000000..c6823795e59 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync.test @@ -0,0 +1,9 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_st_shutdown_slave.inc +--source suite/galera/include/galera_st_clean_slave.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf new file mode 100644 index 00000000000..47cb3e02292 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf @@ -0,0 +1,13 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=xtrabackup-v2 +wsrep_sst_auth="root:" +wsrep_debug=ON + +[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/t/galera_sst_xtrabackup-v2.test b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.test new file mode 100644 index 00000000000..c6823795e59 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.test @@ -0,0 +1,9 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--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_status_cluster.test b/mysql-test/suite/galera/t/galera_status_cluster.test new file mode 100644 index 00000000000..3299613d584 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_status_cluster.test @@ -0,0 +1,18 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# A simple test for the wsrep_cluster_* status variables +# + +--connection node_1 + +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'; + +--connection node_2 + +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'; + + diff --git a/mysql-test/suite/galera/t/galera_status_local_state.test b/mysql-test/suite/galera/t/galera_status_local_state.test new file mode 100644 index 00000000000..09cdb25f80c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_status_local_state.test @@ -0,0 +1,28 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test wsrep_local_state . We can not reliably produce all possible statuses in MTR, but +# we can at least test for the ones we can. +# + +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +SET GLOBAL wsrep_desync = 1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Donor/Desynced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +SET GLOBAL wsrep_desync = 0; + +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + + + + diff --git a/mysql-test/suite/galera/t/galera_suspend_slave.test b/mysql-test/suite/galera/t/galera_suspend_slave.test new file mode 100644 index 00000000000..acee3626f7a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_suspend_slave.test @@ -0,0 +1,51 @@ +## +## This test tests that transactions on the master will fail if the slave +## is made completely unresponsive by suspending the process. Resuming the +## process should allow replication to continue to run. +## + +--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 +--let NODE_2_PIDFILE = `SELECT @@pid_file` +--disconnect node_2 + +--connection node_1 +--echo Suspending node_2 ... +--perl + my $pid_filename = $ENV{'NODE_2_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -19 $mysqld_pid"); + exit(0); +EOF + +--error ER_UNKNOWN_COM_ERROR,ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (1); + +--echo Resuming node_2 ... +--perl + my $pid_filename = $ENV{'NODE_2_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -18 $mysqld_pid"); + exit(0); +EOF + +--sleep 10 +--source include/wait_until_ready.inc +INSERT INTO t1 VALUES (1); + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +--source include/wait_until_ready.inc +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_toi_alter_auto_increment.test b/mysql-test/suite/galera/t/galera_toi_alter_auto_increment.test new file mode 100644 index 00000000000..641d2101c80 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_alter_auto_increment.test @@ -0,0 +1,120 @@ + +# +# Test the operation of ALTER TABLE ... AUTO_INCREMENT +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--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; + +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +--connection node_2 +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +ALTER TABLE t1 AUTO_INCREMENT = 1000; +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +--connection node_1 +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +SELECT MIN(f1) >= 1000, COUNT(*) = 20, COUNT(DISTINCT f1) = 20 FROM t1 WHERE f1 >= 1000; + +--connection node_2 +SELECT MIN(f1) >= 1000, COUNT(*) = 20, COUNT(DISTINCT f1) = 20 FROM t1 WHERE f1 >= 1000; + +# +# AUTO_INCREMENT set to a value lower than the current one. +# The ALTER does nothing, the sequence continues from the current maximum. +# + +--connection node_1 +ALTER TABLE t1 AUTO_INCREMENT = 5; +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +--connection node_2 +INSERT INTO t1 (f2) SELECT 1 FROM ten; +SELECT MIN(f1) >= 1000, COUNT(*) = 40, COUNT(DISTINCT f1) = 40 FROM t1 WHERE f1 >= 1000; + +--connection node_1 +SELECT MIN(f1) >= 1000, COUNT(*) = 40, COUNT(DISTINCT f1) = 40 FROM t1 WHERE f1 >= 1000; + +DROP TABLE t1; + +# +# Under wsrep_auto_increment_control = OFF +# + +--connection node_1 +--let $auto_increment_control_orig = `SELECT @@wsrep_auto_increment_control` +--let $auto_increment_increment_node1 = `SELECT @@auto_increment_increment` +--let $auto_increment_offset_node1 = `SELECT @@auto_increment_offset` + +# Restore stock MySQL defaults +SET GLOBAL wsrep_auto_increment_control = OFF; +SET GLOBAL auto_increment_increment = 1; +SET GLOBAL auto_increment_offset = 1; + +#Open a fresh connection to node_1 so that the variables above take effect +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc + +--connection node_2 +--let $auto_increment_increment_node2 = `SELECT @@auto_increment_increment` +--let $auto_increment_offset_node2 = `SELECT @@auto_increment_offset` + +SET GLOBAL wsrep_auto_increment_control = OFF; +SET GLOBAL auto_increment_increment = 1; +SET GLOBAL auto_increment_offset = 1; + +#Open a fresh connection to node_2 +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc + +--connection node_1a + +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; + +--connection node_2a + +ALTER TABLE t1 AUTO_INCREMENT=100; + +--connection node_1a +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +--connection node_2a +INSERT INTO t1 (f2) SELECT 1 FROM ten; + +SELECT MIN(f1) = 100, MAX(f1) = 119, COUNT(f1) = 20, COUNT(DISTINCT f1) = 20 FROM t1; + +--connection node_1a +SELECT MIN(f1) = 100, MAX(f1) = 119, COUNT(f1) = 20, COUNT(DISTINCT f1) = 20 FROM t1; + +DROP TABLE t1; + +# +# Restore all variables as they were +# + +--disable_query_log + +--connection node_1 +--eval SET GLOBAL wsrep_auto_increment_control = $auto_increment_control_orig +--eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node1 +--eval SET GLOBAL auto_increment_offset = $auto_increment_offset_node1 + +--connection node_2 +--eval SET GLOBAL wsrep_auto_increment_control = $auto_increment_control_orig +--eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node2 +--eval SET GLOBAL auto_increment_offset = $auto_increment_offset_node2 + +--enable_query_log + +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_error.test b/mysql-test/suite/galera/t/galera_toi_ddl_error.test new file mode 100644 index 00000000000..c586d97bdb5 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ddl_error.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +# +# Test the operation of DDLs that fail partway through +# + +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 100K rows +INSERT INTO t1 (f1) SELECT (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 one duplicate value +INSERT INTO t1 (f1) SELECT MAX(f1) FROM t1; + +--connection node_2 +--error ER_DUP_ENTRY +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SHOW CREATE TABLE t1; + +--connection node_1 +SHOW CREATE TABLE t1; + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_fk_insert.test b/mysql-test/suite/galera/t/galera_toi_ddl_fk_insert.test new file mode 100644 index 00000000000..1f446938775 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ddl_fk_insert.test @@ -0,0 +1,70 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +# +# This test creates a new FK constraint while concurrent INSERTS are running +# + +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +CREATE TABLE parent ( + id INT PRIMARY KEY AUTO_INCREMENT, + f2 INTEGER, + KEY (id) +) ENGINE=InnoDB; + +CREATE TABLE child ( + id INT PRIMARY KEY AUTO_INCREMENT, + parent_id INT +) ENGINE=InnoDB; + +INSERT INTO parent VALUES (DEFAULT, 0); + +--connection node_2 +--send INSERT INTO child (parent_id) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +--send INSERT INTO parent (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +--send INSERT INTO parent (f2) SELECT 2 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--let $galera_connection_name = node_1b +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1b +--sleep 2 +--send ALTER TABLE child ADD FOREIGN KEY (parent_id) REFERENCES parent(id); + +--connection node_1a +--reap + +--connection node_1b +--reap + +--connection node_2 +--reap + +--connection node_2a +--reap + +--connection node_1 +SELECT COUNT(*) = 20001 FROM parent; +SELECT COUNT(*) = 10000 FROM child; + +--connection node_2 +SELECT COUNT(*) = 20001 FROM parent; +SELECT COUNT(*) = 10000 FROM child; + +DROP TABLE child; +DROP TABLE parent; + +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test new file mode 100644 index 00000000000..ebab030d9d6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test @@ -0,0 +1,76 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# +# Test that DDL indeed causes all nodes to block so even unrelated updates +# are not allowed to proceed. We block the DDL using DBUG_SYNC +# + +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 + +--let $galera_connection_name = node_1b +--let $galera_server_number = 1 +--source include/galera_connect.inc + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; + +# Allowed +SELECT COUNT(*) = 0 FROM t1; + +# Allowed +SELECT COUNT(*) = 0 FROM t2; + +# Not allowed +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (1); + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +# Allowed +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'; +SELECT COUNT(*) = 0 FROM t2; +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1a +--reap + +--connection node_1 +--reap +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 1 FROM t2; + +--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_toi_ddl_nonconflicting.test b/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test new file mode 100644 index 00000000000..821f7a6eb2c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ddl_nonconflicting.test @@ -0,0 +1,30 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# In this test, we simultaneously send two non-conflicting ALTER TABLE statements +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); + +--connection node_2 +--send ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123); + +--connection node_1 +--send CREATE UNIQUE INDEX i1 ON t1(f2); + +--connection node_2 +--reap +INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 234); + +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 2 FROM t1; + +--connection node_1 +--reap +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_sequential.test b/mysql-test/suite/galera/t/galera_toi_ddl_sequential.test new file mode 100644 index 00000000000..51eae7005df --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ddl_sequential.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# In this test, we send two ALTER TABLE statements that would only work if executed in the right order +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +INSERT INTO t1 VALUES (2, 3); + +--connection node_1 +ALTER TABLE t1 DROP COLUMN f2; +INSERT INTO t1 VALUES (4); + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 3 FROM t1; +SELECT * FROM t1 ORDER BY f1; + +--connection node_1 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 3 FROM t1; +SELECT * FROM t1 ORDER BY f1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_toi_ftwrl.test b/mysql-test/suite/galera/t/galera_toi_ftwrl.test new file mode 100644 index 00000000000..4d0edefda8e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_ftwrl.test @@ -0,0 +1,22 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# At this time, issing a FLUSH TABLES WITH READ LOCK on one node does not prevent DDLs from other nodes +# from proceeding. The locked node will apply the DDL after it has been unlocked +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +FLUSH TABLES WITH READ LOCK; + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +UNLOCK TABLES; +SHOW CREATE TABLE t1; + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_toi_lock_exclusive.test b/mysql-test/suite/galera/t/galera_toi_lock_exclusive.test new file mode 100644 index 00000000000..3c66286a3e6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_lock_exclusive.test @@ -0,0 +1,38 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Ensure that ALTER LOCK=EXCLUSIVE works under TOI. It is difficult to check that concurrent operations +# are truly not possible, but at least we expect no hangs or deadlocks +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Start a transaction that is concurrent to the DDL. This is not strictly necessary for this test +# but does put more locks into play. +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (2); + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=EXCLUSIVE; + +# In Galera, a concurrent transaction aborts in the face of ALTER +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +--connection node_1 +INSERT INTO t1 VALUES (2, 2); +SELECT COUNT(*) = 2 FROM t1; + +--connection node_2 +INSERT INTO t1 VALUES (3, 3); +SELECT COUNT(*) = 3 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_toi_lock_shared.test b/mysql-test/suite/galera/t/galera_toi_lock_shared.test new file mode 100644 index 00000000000..6857a0e08ca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_toi_lock_shared.test @@ -0,0 +1,23 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Ensure that ALTER LOCK=SHARED works under TOI. It is difficult to check that concurrent operations +# will be possible, but at least we expect no hangs or deadlocks +# + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=SHARED; + +--connection node_1 +INSERT INTO t1 VALUES (2, 2); +SELECT COUNT(*) = 2 FROM t1; + +--connection node_2 +INSERT INTO t1 VALUES (3, 3); +SELECT COUNT(*) = 3 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_transaction_read_only.test b/mysql-test/suite/galera/t/galera_transaction_read_only.test new file mode 100644 index 00000000000..386d73fd3ca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_transaction_read_only.test @@ -0,0 +1,58 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Ensure that transactions that do not write anything do not cause the wsrep_last_committed counter to advance +# + +# Empty transaction + +--connection node_1 +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--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 + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +COMMIT; + +--connection node_2 +--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 + +# START TRANSACTION READ ONLY + +--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 +START TRANSACTION READ ONLY; +SELECT COUNT(*) = 0 FROM t1; +COMMIT; + +--connection node_2 +--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 + +# Ordinary transaction with only SELECTs + +--connection node_1 +START TRANSACTION; +SELECT COUNT(*) = 0 FROM t1; +COMMIT; + +--connection node_2 +--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 + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_transaction_replay.test b/mysql-test/suite/galera/t/galera_transaction_replay.test new file mode 100644 index 00000000000..d2c74ab192b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_transaction_replay.test @@ -0,0 +1,63 @@ +# +# 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. +# + +--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 + +--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 +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_enter_sync'; + +--connection node_1 +--send COMMIT; + +# Wait until commit is blocked +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = 'apply_monitor_enter_sync' +--source include/wait_condition.inc + +# Issue a conflicting update on node #2 +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; + +# Unblock the commit +--connection node_1a +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_enter_sync'; + +# 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 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_truncate.test b/mysql-test/suite/galera/t/galera_truncate.test new file mode 100644 index 00000000000..79f9bad1f1b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_truncate.test @@ -0,0 +1,57 @@ +# +# Test TRUNCATE +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Simple case +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; + +# +# Table with no PK +# + +--connection node_2 +CREATE TABLE t2 (f1 VARCHAR(255)) Engine=InnoDB; +INSERT INTO t2 VALUES ('abc'); + +--connection node_1 +TRUNCATE TABLE t2; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t2; + +# +# Table with AUTO_INCREMENT. The AUTO_INCREMENT counter must be reset on all nodes +# + +--connection node_1 +CREATE TABLE t3 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; +INSERT INTO t3 VALUES (DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT); + +CREATE TABLE t4 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB AUTO_INCREMENT=1234; +INSERT INTO t4 VALUES (DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT),(DEFAULT); + +TRUNCATE TABLE t3; +TRUNCATE TABLE t4; + +--connection node_2 +SELECT AUTO_INCREMENT = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('t3', 't4'); + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/mysql-test/suite/galera/t/galera_truncate_temporary.test b/mysql-test/suite/galera/t/galera_truncate_temporary.test new file mode 100644 index 00000000000..3ad94eb9930 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_truncate_temporary.test @@ -0,0 +1,82 @@ +# +# Test TRUNCATE on TEMPORARY tables. It should not be replicated +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TEMPORARY TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +INSERT INTO t1 VALUES (1); + +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +--error ER_NO_SUCH_TABLE +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; + +# +# Test the case where a TEMPORARY table is masking an existing 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); + +SELECT f1 = 2 FROM t1; +SELECT COUNT(*) = 1 FROM t1; + +TRUNCATE TABLE t1; + +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT f1 = 1 FROM t1; + +--connection node_1 + +DROP TABLE t1; +SELECT COUNT(*) = 1 FROM t1; +SELECT f1 = 1 FROM t1; + +TRUNCATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +DROP TABLE t1; + +# +# Test the case where one node has a TEMPORARY table but the TRUNCATE arrives from another node +# + +--connection node_1 +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); + +--connection node_2 +TRUNCATE TABLE t1; + +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SELECT f1 = 2 FROM t1; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +SELECT COUNT(*) = 0 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_udf-master.opt b/mysql-test/suite/galera/t/galera_udf-master.opt new file mode 100644 index 00000000000..14dfe3e20bc --- /dev/null +++ b/mysql-test/suite/galera/t/galera_udf-master.opt @@ -0,0 +1,2 @@ +$UDF_EXAMPLE_LIB_OPT +--query_cache_type=1 diff --git a/mysql-test/suite/galera/t/galera_unicode_identifiers.test b/mysql-test/suite/galera/t/galera_unicode_identifiers.test index 4722d6d61a2..2f255e9a197 100644 --- a/mysql-test/suite/galera/t/galera_unicode_identifiers.test +++ b/mysql-test/suite/galera/t/galera_unicode_identifiers.test @@ -21,7 +21,7 @@ CREATE TABLE `table with space` ( `column with space` INTEGER AUTO_INCREMENT PRIMARY KEY, `second column with space` INTEGER, UNIQUE `index name with space` (`second column with space`) -) ENGINE=INNODB; +); INSERT INTO `table with space` VALUES (DEFAULT, 1); # Unicode identifiers @@ -32,7 +32,7 @@ CREATE TABLE `таблица` ( `първа_колона` INTEGER PRIMARY KEY, `втора_колона` INTEGER, UNIQUE `индекÑ` (`втора_колона`) -) ENGINE=INNODB; +); INSERT INTO `таблица` VALUES (1, 1); @@ -44,19 +44,19 @@ CREATE TABLE `втора таблица` ( `първа колона` INTEGER, `втора колона` INTEGER, KEY `първи индекÑ` (`първа колона`) -) ENGINE=INNODB; +); INSERT INTO `втора таблица` VALUES (1, 1); --connection node_2 USE `database with space`; -SELECT * FROM `table with space`; +SELECT `second column with space` FROM `table with space`; USE `база`; SELECT * FROM `таблица`; USE `втора база`; -SELECT * FROM `втора таблица`; +SELECT `втора колона` FROM `втора таблица`; --eval SET GLOBAL wsrep_sync_wait = $wsrep_sync_wait_orig diff --git a/mysql-test/suite/galera/t/galera_unicode_pk.test b/mysql-test/suite/galera/t/galera_unicode_pk.test new file mode 100644 index 00000000000..0d571f5cfd7 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_unicode_pk.test @@ -0,0 +1,64 @@ +# +# Test non-ascii data in table where the PK is unicode +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 ( + f1 VARCHAR(255) PRIMARY KEY +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES ('текÑÑ‚'); + +--connection node_2 +SELECT f1 = 'текÑÑ‚' FROM t1; + +# +# Provoke a conflict +# + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚2'; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +UPDATE t1 SET f1 = 'текÑÑ‚3'; + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +SELECT f1 = 'текÑÑ‚2' FROM t1; +SELECT f1 = 'текÑÑ‚2' FROM t1 WHERE f1 = 'текÑÑ‚2'; + +# +# Provoke a duplicate key error +# + +--connection node_2 +START TRANSACTION; +INSERT INTO t1 VALUES ('текÑÑ‚4'); + +--connection node_1 +START TRANSACTION; +INSERT INTO t1 VALUES ('текÑÑ‚4'); + +--connection node_2 +COMMIT; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +# Work around for mysql-wsrep#29 'Spurious deadlock error on a DROP TABLE' +--error 0,ER_LOCK_DEADLOCK +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_update_limit.test b/mysql-test/suite/galera/t/galera_update_limit.test new file mode 100644 index 00000000000..baacf2a60b2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_update_limit.test @@ -0,0 +1,55 @@ +# +# UPDATE LIMIT should not cause any issues with row-based Galera replication +# regardless of the order in which the rows were updated +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# With a PK +# + +--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) Engine=InnoDB; +INSERT INTO t1 SELECT f1 FROM ten ORDER BY RAND(); + +--connection node_2 +UPDATE IGNORE t1 SET f1 = FLOOR(1 + (RAND() * 10)) ORDER BY RAND() LIMIT 5; + +# Check that the sum of all elements and the max element are identical across nodes +# as this will indicate that the same UPDATE was applied to both nodes + +--let $sum_rows = `SELECT SUM(f1) FROM t1` +--let $max_row = `SELECT MAX(f1) FROM t1` + +--connection node_1 +--disable_query_log +--eval SELECT (SELECT SUM(f1) FROM t1) = $sum_rows AS sum_matches; +--eval SELECT f1 = $max_row AS max_matches FROM t1 WHERE f1 = $max_row; +--enable_query_log + +DROP TABLE t1; + +# +# Without a PK +# + +CREATE TABLE t2 (f1 INTEGER) Engine=InnoDB; +INSERT INTO t2 SELECT f1 FROM ten ORDER BY RAND(); + +--connection node_2 +UPDATE IGNORE t2 SET f1 = FLOOR(1 + (RAND() * 10)) ORDER BY RAND() LIMIT 5; + +--let $sum_rows = `SELECT SUM(f1) FROM t2` + +--connection node_1 +--disable_query_log +--eval SELECT (SELECT SUM(f1) FROM t2) = $sum_rows AS sum_matches; +--enable_query_log + +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_v1_row_events-master.opt b/mysql-test/suite/galera/t/galera_v1_row_events-master.opt new file mode 100644 index 00000000000..dc82542128e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_v1_row_events-master.opt @@ -0,0 +1 @@ +--log-bin-use-v1-row-events=1 diff --git a/mysql-test/suite/galera/t/galera_v1_row_events.test b/mysql-test/suite/galera/t/galera_v1_row_events.test new file mode 100644 index 00000000000..0c0a044510e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_v1_row_events.test @@ -0,0 +1,21 @@ +# +# Test that Galera 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; + +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +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/t/galera_var_OSU_method.test b/mysql-test/suite/galera/t/galera_var_OSU_method.test index 6190d5cec9a..fcf964c4f89 100644 --- a/mysql-test/suite/galera/t/galera_var_OSU_method.test +++ b/mysql-test/suite/galera/t/galera_var_OSU_method.test @@ -36,4 +36,10 @@ SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; --connection node_1 SET SESSION wsrep_OSU_method = "TOI"; +--connection node_1 +SET DEBUG_SYNC= 'RESET'; + +--connection node_1a +SET DEBUG_SYNC= 'RESET'; + DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_OSU_method2.test b/mysql-test/suite/galera/t/galera_var_OSU_method2.test index abc01ee3e0e..099e2cc6612 100644 --- a/mysql-test/suite/galera/t/galera_var_OSU_method2.test +++ b/mysql-test/suite/galera/t/galera_var_OSU_method2.test @@ -40,4 +40,8 @@ INSERT INTO t1 VALUES (3,4); --connection node_1 SET GLOBAL wsrep_OSU_method = "TOI"; DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; + +--connection node_1a +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/suite/galera/t/galera_var_auto_inc_control_off.test b/mysql-test/suite/galera/t/galera_var_auto_inc_control_off.test index 1ae08abc920..c0bbe5af8cf 100644 --- a/mysql-test/suite/galera/t/galera_var_auto_inc_control_off.test +++ b/mysql-test/suite/galera/t/galera_var_auto_inc_control_off.test @@ -88,6 +88,8 @@ SELECT * FROM t1; # Restore all variables as they were # +--disable_query_log + --connection node_1 --eval SET GLOBAL wsrep_auto_increment_control = $auto_increment_control_orig --eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node1 @@ -98,4 +100,6 @@ SELECT * FROM t1; --eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node2 --eval SET GLOBAL auto_increment_offset = $auto_increment_offset_node2 +--enable_query_log + DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test b/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test index 4d1b9af1573..59f2615b685 100644 --- a/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test +++ b/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test @@ -9,13 +9,11 @@ CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE=InnoDB; -SHOW CREATE TABLE t1; - # auto_increment_increment is equal to the number of nodes # auto_increment_offset is equal to the ID of the node SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); -SELECT @@auto_increment_offset = 1; +SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; # Expect no conflicts --send INSERT INTO t1 VALUES (DEFAULT, 'node1'); @@ -29,9 +27,8 @@ SELECT @@auto_increment_offset = 1; --connection node_2 --reap -SHOW CREATE TABLE t1; SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); -SELECT @@auto_increment_offset = 2; +SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; # Expect no conflicts --send INSERT INTO t1 VALUES (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'); diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test new file mode 100644 index 00000000000..f53986c49b8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -0,0 +1,105 @@ +# +# Check the handling of @@wsrep_cluster_address +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Set to invalid value +# + +--connection node_1 +--let $wsrep_cluster_address_node1 = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = 'foo://'; + +# With wsrep_sync_wait, this returns an error +#--error ER_LOCK_WAIT_TIMEOUT +#SHOW STATUS; + +SET SESSION wsrep_sync_wait=0; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; + +# Must return 'OFF' +SHOW STATUS LIKE 'wsrep_ready'; + +# Must return 'Non-primary' +SHOW STATUS LIKE 'wsrep_cluster_status'; + +# Must return 0 = 'Initialized' +SHOW STATUS LIKE 'wsrep_local_state'; +SHOW STATUS LIKE 'wsrep_local_state_comment'; + +--connection node_2 +--sleep 1 +# Node #2 thinks that it is now part of a single-node primary cluster +SELECT VARIABLE_VALUE = 1 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'; + +# +# Reset everything as it was +# + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node1'; +--enable_query_log + +--connection node_2 +SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; + +--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'; + +# +# Set to invalid host +# + +--connection node_1 +SET GLOBAL wsrep_cluster_address = 'gcomm://192.0.2.1'; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; + +# Must return 'OFF' +SHOW STATUS LIKE 'wsrep_ready'; + +# Must return 'Non-primary' +SHOW STATUS LIKE 'wsrep_cluster_status'; + +# Must return 0 = 'Initialized' +SHOW STATUS LIKE 'wsrep_local_state'; +SHOW STATUS LIKE 'wsrep_local_state_comment'; + +# +# Reset everything as it was +# + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node1'; +--enable_query_log + +--connection node_2 +SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +--sleep 1 + +--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'; + +CALL mtr.add_suppression("WSREP: .*Backend not supported: foo.*"); +CALL mtr.add_suppression("WSREP: .*Failed to initialize backend using 'foo.*"); +CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'foo*"); +CALL mtr.add_suppression("WSREP: gcs connect failed: Socket type not supported"); +CALL mtr.add_suppression("WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: .*Failed to open backend connection: -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'gcomm://192\\.0\\.2\\.1': -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("WSREP: gcs connect failed: Connection timed out"); +CALL mtr.add_suppression("WSREP: wsrep::connect\\(\\) failed: 7"); +#CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); diff --git a/mysql-test/suite/galera/t/galera_var_desync_on.test b/mysql-test/suite/galera/t/galera_var_desync_on.test new file mode 100644 index 00000000000..fb0fb9f762a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_desync_on.test @@ -0,0 +1,58 @@ +# +# Test wsrep_desync = ON . Node should temporarily not participate in flow control +# so even if fc_limit has been reached, the master should be able to continue to +# commit transactions. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; +SET GLOBAL wsrep_desync = TRUE; + +# Block the slave applier thread +FLUSH TABLES WITH READ LOCK; + +--connection node_1 + +# Without wsrep_desync = TRUE it would not be possible to perform 10 inserts on the master with gcs.fc_limit=1 +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +--sleep 1 + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +# No updates have arrived after the FLUSH TABLES +SELECT COUNT(*) = 1 FROM t1; + +# Resync the slave +SET GLOBAL wsrep_desync = FALSE; +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log +UNLOCK TABLES; + +SET SESSION wsrep_sync_wait = 1; +# The slave is now fully caught up +SELECT COUNT(*) = 10 FROM t1; + +--connection node_1 +INSERT INTO t1 VALUES (11); + +--connection node_2 +# Replication continues normally +SELECT COUNT(*) = 11 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test new file mode 100644 index 00000000000..c08483b63ad --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test @@ -0,0 +1,33 @@ +# +# This test checks that innodb_disallow_writes works as expected +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Open a separate connection to be used to run SHOW PROCESSLIST +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET GLOBAL innodb_disallow_writes=ON; +--send INSERT INTO t1 VALUES (1); + +--connection node_1a +let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t1 VALUES (1)' AND State = 'query end'; +--source include/wait_condition.inc + +SET GLOBAL innodb_disallow_writes=OFF; + +--connection node_1 +--reap +SELECT COUNT(*) = 1 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_load_data_splitting.test b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test new file mode 100644 index 00000000000..0783dc897f8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test @@ -0,0 +1,38 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting` + +# Create a file for LOAD DATA with 95K entries +--perl +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_var_load_data_splitting.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'` + +SET GLOBAL wsrep_load_data_splitting = TRUE; +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_var_load_data_splitting.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 +--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_max_ws_size.test b/mysql-test/suite/galera/t/galera_var_max_ws_size.test new file mode 100644 index 00000000000..720f9be8a99 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_max_ws_size.test @@ -0,0 +1,27 @@ +# +# This test sets wsrep_max_ws_size to a very low value and checks that the transaction is rejected +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--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.*'); + +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB; + +--let $wsrep_max_ws_size_orig = `SELECT @@wsrep_max_ws_size` +SET GLOBAL wsrep_max_ws_size = 1024; + +--error ER_ERROR_DURING_COMMIT +INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024)); +SELECT COUNT(*) = 0 FROM t1; + +--disable_query_log +--eval SET GLOBAL wsrep_max_ws_size = $wsrep_max_ws_size_orig +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt b/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt new file mode 100644 index 00000000000..70dfc98736b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt @@ -0,0 +1 @@ +--wsrep_notify_cmd=$MYSQL_TEST_DIR/std_data/wsrep_notify.sh --wsrep-sync-wait=0 diff --git a/mysql-test/suite/galera/t/galera_var_notify_cmd.test b/mysql-test/suite/galera/t/galera_var_notify_cmd.test new file mode 100644 index 00000000000..4fea69f62bb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_notify_cmd.test @@ -0,0 +1,14 @@ +# +# Test wsrep_notify_cmd. We use a version of the support-files/wsrep_notify.sh script that writes +# notifications into a table. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--connection node_1 +SELECT COUNT(DISTINCT uuid) = 2 FROM mtr_wsrep_notify.membership; +SELECT MAX(size) = 2 FROM mtr_wsrep_notify.status; +SELECT COUNT(DISTINCT idx) = 2 FROM mtr_wsrep_notify.status; + +DROP SCHEMA mtr_wsrep_notify; diff --git a/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test b/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test index f6838028e66..9cb0edf1810 100644 --- a/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test +++ b/mysql-test/suite/galera/t/galera_var_replicate_myisam_on.test @@ -5,17 +5,135 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--connection node_1 --let $wsrep_replicate_myisam_orig = `SELECT @@wsrep_replicate_myisam` +--connection node_1 +SET GLOBAL wsrep_replicate_myisam = TRUE; +--connection node_2 SET GLOBAL wsrep_replicate_myisam = TRUE; +# +# Simple INSERT +# + +--connection node_1 CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=MyISAM; INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2), (3); +INSERT INTO t1 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +DROP TABLE t1; + +# +# REPLACE +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(100)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1, 'abc'),(2,'abc'), (3, 'xxx'); +REPLACE INTO t1 VALUES (1, 'klm'), (2,'xyz'); +REPLACE INTO t1 SELECT 3, 'yyy' FROM DUAL; + +--connection node_2 +SELECT COUNT(*) = 3 FROM t1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1 AND f2 = 'klm'; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2 AND f2 = 'xyz'; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3 AND f2 = 'yyy'; + +# +# UPDATE +# + +--connection node_1 +UPDATE t1 SET f2 = 'zzz' WHERE f2 = 'yyy'; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'zzz'; + +# +# DELETE +# + +--connection node_1 +DELETE FROM t1 WHERE f2 = 'zzz'; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'zzz'; + +# +# TRUNCATE +# + +--connection node_1 +TRUNCATE TABLE t1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +DROP TABLE t1; + +# +# Transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +COMMIT; --connection node_2 SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 1 FROM t2; + +# +# Transaction rollback +# + +--connection node_1 +START TRANSACTION; +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (2); +ROLLBACK; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; +SELECT COUNT(*) = 1 FROM t2; + +DROP TABLE t1; +DROP TABLE t2; + +# +# Transaction conflict +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (f2 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +--connection node_2 +# The MyISAM update is replicated immediately, so a duplicate key error happens even before the COMMIT +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES (1); + +--connection node_1 +COMMIT; + +DROP TABLE t1; +DROP TABLE t2; --connection node_1 --eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig -DROP TABLE t1; +--connection node_2 +--eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test new file mode 100644 index 00000000000..a83924c13ce --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test @@ -0,0 +1,70 @@ +# +# This tests the very basic operations around wsrep-slave-threads +# More complex scenarios will be tested separately in the context of +# parallel replication +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` + +--connection node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; +CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; + +--connection node_2 + +# Setting wsrep_slave_threads to zero triggers a warning +SET GLOBAL wsrep_slave_threads = 0; +SHOW WARNINGS; +SELECT @@wsrep_slave_threads = 1; + +SET GLOBAL wsrep_slave_threads = 1; +# There is a separate wsrep_aborter thread at all times +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + +# +# Increase the number of slave threads. The change takes effect immediately +# + +SET GLOBAL wsrep_slave_threads = 64; +--sleep 0.5 + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + +# +# Reduce the number of slave threads. The change is not immediate -- a thread will only exit after a replication event +# + +SET GLOBAL wsrep_slave_threads = 1; + +--connection node_1 + +# Generate 64 replication events +--let $count = 64 +while ($count) +{ + INSERT INTO t2 VALUES (DEFAULT); + --dec $count +} + +--connection node_2 +SELECT COUNT(*) = 64 FROM t2; + +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + + +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test b/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test new file mode 100644 index 00000000000..783b78792e6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test @@ -0,0 +1,32 @@ +# +# Test wsrep_on = OFF. Some events will not be replicated +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_on = FALSE; + +# This statement will not be replicated +INSERT INTO t1 VALUES (2); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +SET GLOBAL wsrep_on = TRUE; +INSERT INTO t1 VALUES (3); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +# Middle insert is not replicated +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 2; + +# Final insert is replicated +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3; + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_wan.cnf b/mysql-test/suite/galera/t/galera_wan.cnf new file mode 100644 index 00000000000..0effd59403b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wan.cnf @@ -0,0 +1,14 @@ +!include ../galera_4nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M;gmcast.segment=1' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M;gmcast.segment=1' + +[mysqld.3] +wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M;gmcast.segment=2' + +[mysqld.4] +wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M;gmcast.segment=3' + diff --git a/mysql-test/suite/galera/t/galera_wan.test b/mysql-test/suite/galera/t/galera_wan.test new file mode 100644 index 00000000000..a8fd351b168 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wan.test @@ -0,0 +1,30 @@ +# +# Test WAN replication and the gmcast.segment functionality. +# The galera_wan.cnf file partitions 4 Galera nodes into 3 WAN segments +# +# We can not test any of the actual WAN optimizations from inside MTR and no +# status variables are provided. So we only check that simple replication works. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +INSERT INTO t1 VALUES (1); +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"); + +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connection node_4 +SELECT VARIABLE_VALUE LIKE '%gmcast.segment = 3%' FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'; + +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +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/t/galera_wsrep_desync_wsrep_on.test b/mysql-test/suite/galera/t/galera_wsrep_desync_wsrep_on.test new file mode 100644 index 00000000000..3c7988a4924 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_desync_wsrep_on.test @@ -0,0 +1,57 @@ +# +# Test the wsrep_desync + wsrep_on method for schema upgrades discussed at +# http://www.slideshare.net/Severalnines/schema-upgrades-codershippresodec2013 , slide 30 +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +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; + +--connection node_2 +SET GLOBAL wsrep_desync = TRUE; +SET SESSION wsrep_on = FALSE; + +ALTER TABLE t1 ADD PRIMARY KEY (f1); + +SET SESSION wsrep_on = TRUE; +SET GLOBAL wsrep_desync = FALSE; + +# Insert even more data after the ALTER has completed +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; + +SELECT COUNT(*) = 200000 FROM t1; +SELECT MAX(f1) = 199999 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 200000 FROM t1; +SELECT MAX(f1) = 199999 FROM t1; + +SET GLOBAL wsrep_desync = TRUE; +SET SESSION wsrep_on = FALSE; + +ALTER TABLE t1 ADD PRIMARY KEY (f1); + +SET SESSION wsrep_on = TRUE; +SET GLOBAL wsrep_desync = FALSE; + +# Insert some conflicting values after the ALTER has been applied on all nodes. + +--connection node_2 +--error ER_DUP_ENTRY +INSERT INTO t1 (f1) VALUES (1); + +--connection node_1 +--error ER_DUP_ENTRY +INSERT INTO t1 (f1) VALUES (100); + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_wsrep_new_cluster-master.opt b/mysql-test/suite/galera/t/galera_wsrep_new_cluster-master.opt new file mode 100644 index 00000000000..c31150c46af --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_new_cluster-master.opt @@ -0,0 +1 @@ +--wsrep-new-cluster diff --git a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test new file mode 100644 index 00000000000..6ba8ce786c8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test @@ -0,0 +1,24 @@ +# +# Test the --wsrep-new-cluster option by putting it in the galera_wsrep_new_cluster-master.opt file +# +# In MTR, running two nodes, the result is two separate clusters of size 1 +# + +--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'; +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +--connection node_2 + +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'; +SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; diff --git a/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test b/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test new file mode 100644 index 00000000000..fe4c358bd89 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_provider_unset_set.test @@ -0,0 +1,41 @@ +# +# Test that wsrep_provider can be unset and then set back to its original value +# and replication will continue except for any updates made while the value was 'none' +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--let $wsrep_provider_orig = `SELECT @@wsrep_provider` +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` + +SET GLOBAL wsrep_provider='none'; +INSERT INTO t1 VALUES (2); + +--connection node_1 +INSERT INTO t1 VALUES (3); + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +INSERT INTO t1 VALUES (4); + +# Node #2 has all the inserts +SELECT COUNT(*) = 4 FROM t1; + +--connection node_1 +# Node #1 is missing the insert made while Node #2 was not replicated +SELECT COUNT(*) = 3 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_zero_length_column.test b/mysql-test/suite/galera/t/galera_zero_length_column.test new file mode 100644 index 00000000000..6ae81a83271 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_zero_length_column.test @@ -0,0 +1,41 @@ +# +# Test columns with size zero. This is known to have tripped other storage engines. +# Keys are not allowed on such columns +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY , f2 VARCHAR(0)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 VARCHAR(0)) ENGINE=InnoDB; + + +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, ''); + +INSERT INTO t2 VALUES (NULL); +INSERT INTO t2 VALUES (''); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; +SELECT f2 IS NULL FROM t1 WHERE f1 = 1; +SELECT f2 = '' FROM t1 WHERE f1 = 2; + +SELECT COUNT(*) = 2 FROM t2; +SELECT f1 IS NULL FROM t2 WHERE f1 IS NULL; +SELECT f1 = '' FROM t2 WHERE f1 IS NOT NULL; + +UPDATE t1 SET f2 = '' WHERE f1 = 1; +UPDATE t1 SET f2 = NULL WHERE f1 = 2; + +UPDATE t2 SET f1 = '' WHERE f1 IS NULL; + +--connection node_1 +SELECT f2 = '' FROM t1 WHERE f1 = 1; +SELECT f2 IS NULL FROM t1 WHERE f1 = 2; + +SELECT COUNT(*) = 2 FROM t2 WHERE f1 = ''; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/lp1276424.test b/mysql-test/suite/galera/t/lp1276424.test new file mode 100644 index 00000000000..a37e950b6a1 --- /dev/null +++ b/mysql-test/suite/galera/t/lp1276424.test @@ -0,0 +1,17 @@ +# +# LP:1276424 Deadlock with insertion of NULL unique ke +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT DEFAULT NULL, UNIQUE KEY i1 (f1)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (NULL); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; +SELECT f1 IS NULL FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/lp1347768.test b/mysql-test/suite/galera/t/lp1347768.test new file mode 100644 index 00000000000..96d42867c6a --- /dev/null +++ b/mysql-test/suite/galera/t/lp1347768.test @@ -0,0 +1,24 @@ +# +# LP:1347768 Assertion failure in file ha_innodb.cc line 6759 +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE `r8kmb_redirect_links` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `old_url` varchar(255) DEFAULT NULL, + `new_url` varchar(255) NOT NULL, + `referer` varchar(150) NOT NULL, + `comment` varchar(255) NOT NULL, + `published` tinyint(4) NOT NULL, + `created_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `modified_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_link_old` (`old_url`), + KEY `idx_link_modifed` (`modified_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO r8kmb_redirect_links VALUES (550,'http://mysite.com/images/download/ßуñûічýøù_ôþóþòір_þфõÑ.doc','','','',0,'2013-07-15 14:29:42','0000-00-00 00:00:00'); + +DROP TABLE r8kmb_redirect_links; diff --git a/mysql-test/suite/galera/t/lp959512.test b/mysql-test/suite/galera/t/lp959512.test new file mode 100644 index 00000000000..bcc0db24ea7 --- /dev/null +++ b/mysql-test/suite/galera/t/lp959512.test @@ -0,0 +1,26 @@ +# +# LP#959512 IO cache not reset at trx cleanup if write set was empty Edit +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +DROP TABLE IF EXISTS variable; +DROP TABLE IF EXISTS foo; +CREATE TABLE variable ( + name varchar(128) NOT NULL DEFAULT '' COMMENT 'The name of the variable.', + value longblob NOT NULL COMMENT 'The value of the variable.', + PRIMARY KEY (name) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Named variable/value pairs created by Drupal core or any...'; +CREATE TABLE foo (a int); +INSERT INTO variable (name, value) VALUES ('menu_expanded', 'a:0:{}'); +START TRANSACTION; +SELECT 1 AS expression FROM variable variable + WHERE ( (name = 'menu_expanded') ) FOR UPDATE; +UPDATE variable SET value='a:0:{}' WHERE ( (name = 'menu_expanded') ); +COMMIT; +INSERT INTO foo VALUES (1); +UPDATE foo SET a = 2 WHERE a = 1; + +DROP TABLE foo; +DROP TABLE variable; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#33.cnf b/mysql-test/suite/galera/t/mysql-wsrep#33.cnf new file mode 100644 index 00000000000..f1c3d802e4b --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#33.cnf @@ -0,0 +1,8 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/mysql-wsrep#33.test b/mysql-test/suite/galera/t/mysql-wsrep#33.test new file mode 100644 index 00000000000..acc7c735849 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#33.test @@ -0,0 +1,18 @@ + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_sst_set_mysqldump.inc + +--source suite/galera/include/galera_st_disconnect_slave.inc + +--source suite/galera/include/galera_sst_restore.inc + +--connection node_2 +# We have to manually restore global_log and slow_query_log due to mysql-wsrep#108 +# Otherwise MTR's check_testcases complains + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def new file mode 100644 index 00000000000..ec02e73b4a3 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -0,0 +1,2 @@ +galera_garbd : Fix the test case +galera_evs_suspect_timeout : TODO: investigate diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf new file mode 100644 index 00000000000..689fd4db26c --- /dev/null +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -0,0 +1,58 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb +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=7 + +[mysqld.1] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +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' + +[mysqld.2] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='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' + +[mysqld.3] +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='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' + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +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_3nodes/include/galera_suspend.inc b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc new file mode 100644 index 00000000000..3495ad2342b --- /dev/null +++ b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc @@ -0,0 +1,14 @@ +# +# This macro suspends the current node +# + +--let _SUSPEND_NODE_PIDFILE = `SELECT @@pid_file` +--echo Suspending node ... + +--perl + my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -19 $mysqld_pid"); + exit(0); +EOF diff --git a/mysql-test/suite/galera_3nodes/my.cnf b/mysql-test/suite/galera_3nodes/my.cnf new file mode 100644 index 00000000000..bb25b95ceea --- /dev/null +++ b/mysql-test/suite/galera_3nodes/my.cnf @@ -0,0 +1 @@ +!include galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result new file mode 100644 index 00000000000..96a2bec0d7f --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 3 +1 +SET GLOBAL wsrep_cluster_address = ''; +INSERT INTO t1 VALUES (2); +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +COMMIT; +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; 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 new file mode 100644 index 00000000000..9dc735d5d3d --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +COMMIT; +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_3nodes/r/galera_evs_suspect_timeout.result b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result new file mode 100644 index 00000000000..1464222a079 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result @@ -0,0 +1,19 @@ +SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +Suspending node ... +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); +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 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +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 new file mode 100644 index 00000000000..616c9d33303 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_garbd.result @@ -0,0 +1,14 @@ +Killing node #3 to free ports for garbd ... +Starting garbd ... +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +Killing garbd ... +INSERT INTO t1 VALUES (2); +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; +Restarting node #3 to satisfy MTR's end-of-test checks 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 new file mode 100644 index 00000000000..1ecea5db5ab --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result @@ -0,0 +1,46 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +INSERT INTO t1 VALUES (01), (02), (03), (04), (05); +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +INSERT INTO t1 VALUES (11), (12), (13), (14), (15); +INSERT INTO t1 VALUES (21), (22), (23), (24), (25); +SET GLOBAL wsrep_provider_options = 'dbug=d,ist_sender_send_after_get_buffers'; +INSERT INTO t1 VALUES (31), (32), (33), (34), (35); +SHOW STATUS LIKE 'wsrep_debug_sync_waiters'; +Variable_name Value +wsrep_debug_sync_waiters ist_sender_send_after_get_buffers ist_sender_send_after_get_buffers +INSERT INTO t1 VALUES (41), (42), (43), (44), (45); +CREATE TABLE t2 (f1 LONGTEXT); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); +SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; +SET GLOBAL wsrep_provider_options = 'dbug='; +INSERT INTO t1 VALUES (51), (52), (53), (54), (55); +SELECT COUNT(*) = 30 FROM t1; +COUNT(*) = 30 +1 +SELECT COUNT(*) = 3 FROM t2; +COUNT(*) = 3 +1 +SELECT LENGTH(f1) = 512 * 1024 FROM t2; +LENGTH(f1) = 512 * 1024 +1 +1 +1 +CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); +SELECT COUNT(*) = 30 FROM t1; +COUNT(*) = 30 +1 +SELECT COUNT(*) = 3 FROM t2; +COUNT(*) = 3 +1 +SELECT LENGTH(f1) = 512 * 1024 FROM t2; +LENGTH(f1) = 512 * 1024 +1 +1 +1 +CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); +DROP TABLE t1, t2; 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 new file mode 100644 index 00000000000..1d0da8bf50c --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_slave_threads = 2; +UPDATE t1 SET f1 = f1 + 10;; +UPDATE t1 SET f1 = f1 + 100;; +SELECT f1 = 111 FROM t1; +f1 = 111 +1 +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'closing tables'; +COUNT(*) IN (1, 2) +1 +SET GLOBAL wsrep_slave_threads = 1;; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result new file mode 100644 index 00000000000..ca051436491 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result @@ -0,0 +1,118 @@ +SET GLOBAL wsrep_provider_options = 'pc.weight=3'; +Suspending node ... +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_size'; +Variable_name Value +wsrep_cluster_size 2 +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SHOW STATUS LIKE 'wsrep_connected'; +Variable_name Value +wsrep_connected ON +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_local_state'; +Variable_name Value +wsrep_local_state 0 +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Initialized +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_size'; +Variable_name Value +wsrep_cluster_size 2 +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SHOW STATUS LIKE 'wsrep_connected'; +Variable_name Value +wsrep_connected ON +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_local_state'; +Variable_name Value +wsrep_local_state 0 +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Initialized +Resuming node ... +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 1 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 3 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 3 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 3 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +VARIABLE_VALUE = 'ON' +1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +VARIABLE_VALUE = 4 +1 +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Synced' +1 +CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1'); +CALL mtr.add_suppression('WSREP: user message in state LEAVING'); +CALL mtr.add_suppression('sending install message failed: Transport endpoint is not connected'); diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm new file mode 100644 index 00000000000..1f00e37bdc3 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -0,0 +1,52 @@ +package My::Suite::GALERA_3NODES; +use File::Basename; +use My::Find; + +@ISA = qw(My::Suite); + +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/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"; + +return "No wsrep provider library" unless -f $provider; + +$ENV{WSREP_PROVIDER} = $provider; + +my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; +return "No SST scripts" unless $spath; + +my ($epath) = grep { -f "$_/my_print_defaults"; } "$::bindir/extra", $::path_client_bindir; +return "No my_print_defaults" unless $epath; + +push @::global_suppressions, + ( + qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), + qr(WSREP: Could not open saved state file for reading: ), + qr(WSREP: Gap in state sequence. Need state transfer.), + qr(WSREP: Failed to prepare for incremental state transfer:), + qr(WSREP:.*down context.*), + qr(WSREP: Failed to send state UUID:), + qr(WSREP: last inactive check more than .* skipping check), + qr(WSREP: SQL statement was ineffective), + qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), + qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, + qr(WSREP: Quorum: No node with complete state), + qr(WSREP: Initial position was provided by configuration or SST, avoiding override), + qr|WSREP: discarding established \(time wait\) .*|, + qr(WSREP: There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside. Will use that one.), + qr(WSREP: evs::proto.*), + qr|WSREP: Ignoring possible split-brain (allowed by configuration) from view:.*|, + qr(WSREP: Could not find peer:), + qr(WSREP: Protocol violation. JOIN message sender .*), + ); + + +$ENV{PATH}="$epath:$ENV{PATH}"; +$ENV{PATH}="$spath:$ENV{PATH}" unless $epath eq $spath; + +bless { }; + diff --git a/mysql-test/suite/galera_3nodes/t/galera_certification_ccc.test b/mysql-test/suite/galera_3nodes/t/galera_certification_ccc.test new file mode 100644 index 00000000000..e19169a350c --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_certification_ccc.test @@ -0,0 +1,60 @@ +# +# Test that a cluster configuration change during a transaction does not cause a failure +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +# Save original auto_increment_offset values. +--connection node_1 +let $auto_increment_offset_node_1 = `SELECT @@global.auto_increment_offset`; +--connection node_2 +let $auto_increment_offset_node_2 = `SELECT @@global.auto_increment_offset`; +--connection node_3 +let $auto_increment_offset_node_3 = `SELECT @@global.auto_increment_offset`; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_3 +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; +--sleep 5 + +--connection node_1 +INSERT INTO t1 VALUES (2); +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +--connection node_3 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log +--sleep 5 +--source include/wait_until_ready.inc + +--connection node_1 +DROP TABLE t1; + +# Restore original auto_increment_offset values. +--disable_query_log +--connection node_1 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_1; +--connection node_2 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_2; +--connection node_3 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_3; +--enable_query_log + 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 new file mode 100644 index 00000000000..a2ad0765028 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test @@ -0,0 +1,33 @@ +# +# This test creates a transaction whose certification will fail on two separate nodes +# for two different reasons. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_3 +INSERT INTO t2 VALUES (1); + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +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 new file mode 100644 index 00000000000..a87f19ac94e --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test @@ -0,0 +1,67 @@ +# +# Test the operation of evs.suspect_timeout. +# +# We set evs.inactive_timeout to a very high value so that evs.suspect_timeout can kick in instead. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +--let $wsrep_provider_options_node1 = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; + +--connection node_2 +--source include/wait_until_connected_again.inc +--let $wsrep_provider_options_node2 = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +--source include/wait_until_connected_again.inc +--let $wsrep_cluster_address_node3 = `SELECT @@wsrep_cluster_address` + +# Suspend node #3 + +--source include/galera_suspend.inc +--sleep 5 + +# Confirm that the other nodes have booted it out + +--connection node_1 +--source include/wait_until_connected_again.inc +SET SESSION wsrep_sync_wait = 0; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node1'; +--enable_query_log + +--source include/wait_until_connected_again.inc +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'; +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node2'; +--enable_query_log + +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 1 FROM t1; +DROP TABLE t1; + +# Reconnect node #3 so that MTR's end-of-test checks can run + +--connection node_3 +--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 diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd.test b/mysql-test/suite/galera_3nodes/t/galera_garbd.test new file mode 100644 index 00000000000..3f58783ad31 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test @@ -0,0 +1,50 @@ +# +# A very basic test for the galera arbitrator. We shut down node #3 and use its port allocation to start garbd. +# As MTR does not allow multiple servers to be down at the same time, we are limited as to what we can test. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +--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 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--echo Starting garbd ... +--exec `dirname $WSREP_PROVIDER`/garb/garbd --address "gcomm://127.0.0.1:$NODE_GALERAPORT_1" --group my_wsrep_cluster --options 'base_port=$NODE_GALERAPORT_3' > $MYSQL_TMP_DIR/garbd.log 2>&1 & + +--sleep 5 + +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--echo Killing garbd ... +--exec pkill --oldest --full garbd.*$NODE_GALERAPORT_3 + +--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 + +INSERT INTO t1 VALUES (2); + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; + +--echo Restarting node #3 to satisfy MTR's end-of-test checks +--connection node_3 +--source include/start_mysqld.inc diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf new file mode 100644 index 00000000000..821175220ac --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf @@ -0,0 +1,11 @@ +!include ../galera_3nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true;gcache.size=1M' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true;gcache.size=1M' + +[mysqld.3] +wsrep_provider_options='base_port=@mysqld.3.#galera_port;pc.ignore_sb=true;gcache.size=1M' + 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 new file mode 100644 index 00000000000..0668c246624 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test @@ -0,0 +1,98 @@ +# +# Test that if the gcache rolls over while IST is in progress, IST will still complete. +# This is achieved by using the ist_sender_send_after_get_buffers Galera dbug sync point to block the donor after +# the first gcache buffer has been locked for IST. +# +# After IST blocks, we roll over the gcache and resume IST to confirm that it completes successfully. +# +# Two nodes perform IST at the same time in order to make the test more stressfull +# + +--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 + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +INSERT INTO t1 VALUES (01), (02), (03), (04), (05); + +# Disconnect nodes #2 and #3 +--connection node_2 +--source suite/galera/include/galera_unload_provider.inc + +--connection node_3 +--source suite/galera/include/galera_unload_provider.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +INSERT INTO t1 VALUES (11), (12), (13), (14), (15); + +# Wait until nodes #2 and #3 have left +--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 (21), (22), (23), (24), (25); + +# Make sure IST will block ... +SET GLOBAL wsrep_provider_options = 'dbug=d,ist_sender_send_after_get_buffers'; + +# ... and restart providers to force IST +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +--connection node_1 +INSERT INTO t1 VALUES (31), (32), (33), (34), (35); + +--connection node_3 +--disable_query_log +--eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; +--enable_query_log + +--connection node_1 +--sleep 2 +SHOW STATUS LIKE 'wsrep_debug_sync_waiters'; + +INSERT INTO t1 VALUES (41), (42), (43), (44), (45); + +# Roll over gcache by writing a lot of information to it + +CREATE TABLE t2 (f1 LONGTEXT); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); +INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); + +# Unlock IST and wait for it to complete +SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; +SET GLOBAL wsrep_provider_options = 'dbug='; + +INSERT INTO t1 VALUES (51), (52), (53), (54), (55); + +--connection node_2 +--source include/wait_until_connected_again.inc + +--connection node_3 +--source include/wait_until_connected_again.inc + +# Final checks +--connection node_2 +SELECT COUNT(*) = 30 FROM t1; +SELECT COUNT(*) = 3 FROM t2; +SELECT LENGTH(f1) = 512 * 1024 FROM t2; +CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); + +# Final checks +--connection node_3 +SELECT COUNT(*) = 30 FROM t1; +SELECT COUNT(*) = 3 FROM t2; +SELECT LENGTH(f1) = 512 * 1024 FROM t2; +CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); + +DROP TABLE t1, t2; 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 new file mode 100644 index 00000000000..ef5eb8aca4a --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test @@ -0,0 +1,38 @@ +# +# This test performs two dependent updates on two nodes and checks the results on the third where +# parallel apply is enabled. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_3 +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +SET GLOBAL wsrep_slave_threads = 2; + +--connection node_1 +--send UPDATE t1 SET f1 = f1 + 10; + +--connection node_2 +--send UPDATE t1 SET f1 = f1 + 100; + +--connection node_1 +--reap + +--connection node_2 +--reap + +--connection node_3 +SELECT f1 = 111 FROM t1; +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'closing tables'; + +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test new file mode 100644 index 00000000000..8956bae98ec --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test @@ -0,0 +1,110 @@ +# +# 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 + +--let $wsrep_provider_options_node1 = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.weight=3'; + +--source include/wait_until_connected_again.inc +--source include/galera_suspend.inc +--sleep 10 + +--connection node_2 +# Do not wait for causality as we are no longer in the primary component +SET SESSION wsrep_sync_wait=0; +--source include/wait_until_connected_again.inc + +# We can not use SELECT queries here, as only SHOW is allowed to run. +# For nodes #2 and #3, we expect a non-primary component of size 2 + +SHOW STATUS LIKE 'wsrep_cluster_size'; +SHOW STATUS LIKE 'wsrep_cluster_status'; +SHOW STATUS LIKE 'wsrep_connected'; +SHOW STATUS LIKE 'wsrep_ready'; +SHOW STATUS LIKE 'wsrep_local_state'; +SHOW STATUS LIKE 'wsrep_local_state_comment'; + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +SET SESSION wsrep_sync_wait=0; +--source include/wait_until_connected_again.inc + +SHOW STATUS LIKE 'wsrep_cluster_size'; +SHOW STATUS LIKE 'wsrep_cluster_status'; +SHOW STATUS LIKE 'wsrep_connected'; +SHOW STATUS LIKE 'wsrep_ready'; +SHOW STATUS LIKE 'wsrep_local_state'; +SHOW STATUS LIKE 'wsrep_local_state_comment'; + +--connection node_1 +--source include/galera_resume.inc +--sleep 5 +--source include/wait_until_connected_again.inc + +# For Node #1, we expect a primary component of size 1 + +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +# Restore the cluster by resetting wsrep_cluster_address on nodes #1 and #2 + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +--enable_query_log + +SET SESSION wsrep_sync_wait=0; +--source include/wait_until_connected_again.inc + +--connection node_3 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +--enable_query_log + +SET SESSION wsrep_sync_wait=0; +--source include/wait_until_connected_again.inc + +# On all nodes, we now expect a Primary component of size 3, Synced and ready + +--connection node_1 +--source include/wait_until_connected_again.inc +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +--connection node_2 +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +--connection node_3 +SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; +SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; +SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; + +--connection node_1 +CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1'); + +--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'); diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index bd6f0d4adb7..9c047177ca8 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -35,8 +35,12 @@ wsrep_local_commits # wsrep_local_cert_failures # wsrep_local_replays # wsrep_local_send_queue # +wsrep_local_send_queue_max # +wsrep_local_send_queue_min # wsrep_local_send_queue_avg # wsrep_local_recv_queue # +wsrep_local_recv_queue_max # +wsrep_local_recv_queue_min # wsrep_local_recv_queue_avg # wsrep_local_cached_downto # wsrep_flow_control_paused_ns # @@ -86,8 +90,12 @@ wsrep_local_commits # wsrep_local_cert_failures # wsrep_local_replays # wsrep_local_send_queue # +wsrep_local_send_queue_max # +wsrep_local_send_queue_min # wsrep_local_send_queue_avg # wsrep_local_recv_queue # +wsrep_local_recv_queue_max # +wsrep_local_recv_queue_min # wsrep_local_recv_queue_avg # wsrep_local_cached_downto # wsrep_flow_control_paused_ns # diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index ec405969eba..6922e2d1444 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -28,7 +28,7 @@ CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*") --disable_query_log eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---let $galera_version=25.3.5 +--let $galera_version=3.9 source include/check_galera_version.inc; --enable_query_log diff --git a/sql/sql_table.cc b/sql/sql_table.cc index cf3f588b323..c6647962af5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8332,6 +8332,17 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, DEBUG_SYNC(thd, "alter_opened_table"); +#ifdef WITH_WSREP + DBUG_EXECUTE_IF("sync.alter_opened_table", + { + const char act[]= + "now " + "wait_for signal.alter_opened_table"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); +#endif // WITH_WSREP + if (error) DBUG_RETURN(true); From e69fbd4e38d36853b7e72a9d6a3afe7210874436 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 21 Apr 2015 13:22:08 -0400 Subject: [PATCH 273/294] Post-merge fix --- sql/log.cc | 10 +++++++++- sql/wsrep_hton.cc | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index 8ea84ac189d..f042b1ab756 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -569,7 +569,15 @@ void thd_binlog_trx_reset(THD * thd) { binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - if (cache_mngr) cache_mngr->reset(false, true); + if (cache_mngr) + { + cache_mngr->reset(false, true); + if (!cache_mngr->stmt_cache.empty()) + { + WSREP_DEBUG("pending events in stmt cache, sql: %s", thd->query()); + cache_mngr->stmt_cache.reset(); + } + } } thd->clear_binlog_table_maps(); } diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 144196aab2e..03bf072edcc 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -99,6 +99,14 @@ void wsrep_register_hton(THD* thd, bool all) */ void wsrep_post_commit(THD* thd, bool all) { + /* + TODO: It can perhaps be fixed in a more elegant fashion by turning off + wsrep_emulate_binlog if wsrep_on=0 on server start. + https://github.com/codership/mysql-wsrep/issues/112 + */ + if (!WSREP_ON) + return; + switch (thd->wsrep_exec_mode) { case LOCAL_COMMIT: From 99f496ae65a56d587e24c88df85aae7e7cfce70e Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 28 Apr 2015 11:53:57 -0400 Subject: [PATCH 274/294] Fix for some failing tests --- .../galera/r/galera_var_cluster_address.result | 9 --------- .../suite/galera/r/galera_var_max_ws_size.result | 4 ---- mysql-test/suite/galera/suite.pm | 13 ++++++++++++- .../suite/galera/t/galera_restart_nochanges.test | 15 +++++++++++++++ .../suite/galera/t/galera_suspend_slave.test | 15 +++++++++++++++ .../galera/t/galera_var_cluster_address.test | 10 ---------- .../suite/galera/t/galera_var_max_ws_size.test | 4 ---- 7 files changed, 42 insertions(+), 28 deletions(-) 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 0d4795fb259..f8bd869f8fe 100644 --- a/mysql-test/suite/galera/r/galera_var_cluster_address.result +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -49,12 +49,3 @@ VARIABLE_VALUE = 'Primary' SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 1 -CALL mtr.add_suppression("WSREP: .*Backend not supported: foo.*"); -CALL mtr.add_suppression("WSREP: .*Failed to initialize backend using 'foo.*"); -CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'foo*"); -CALL mtr.add_suppression("WSREP: gcs connect failed: Socket type not supported"); -CALL mtr.add_suppression("WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: .*Failed to open backend connection: -110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'gcomm://192\\.0\\.2\\.1': -110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: gcs connect failed: Connection timed out"); -CALL mtr.add_suppression("WSREP: wsrep::connect\\(\\) failed: 7"); 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 81cc26916d3..5a1b5cf621a 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,7 +1,3 @@ -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.*'); 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)); diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 47dd41c7601..101614f2def 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -45,9 +45,20 @@ push @::global_suppressions, qr(WSREP: user message in state LEAVING), qr(WSREP: .* sending install message failed: Transport endpoint is not connected), qr(WSREP: Maximum writeset size exceeded by .*), - qr(WSREP: transaction size exceeded), + qr(WSREP: transaction size exceeded.*), qr(WSREP: RBR event .*), qr(WSREP: Ignoring error for TO isolated action: .*), + qr(WSREP: transaction size limit .*), + qr(WSREP: rbr write fail, .*), + qr(WSREP: .*Backend not supported: foo.*), + qr(WSREP: .*Failed to initialize backend using .*), + qr(WSREP: .*Failed to open channel 'my_wsrep_cluster' at .*), + qr(WSREP: gcs connect failed: Socket type not supported), + qr(WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 .*), + qr(WSREP: .*Failed to open backend connection: -110 .*), + qr(WSREP: .*Failed to open channel 'my_wsrep_cluster' at .*), + qr(WSREP: gcs connect failed: Connection timed out), + qr|WSREP: wsrep::connect\(\) failed: 7|, ); diff --git a/mysql-test/suite/galera/t/galera_restart_nochanges.test b/mysql-test/suite/galera/t/galera_restart_nochanges.test index 8eb7617b8a6..4021ab39cc0 100644 --- a/mysql-test/suite/galera/t/galera_restart_nochanges.test +++ b/mysql-test/suite/galera/t/galera_restart_nochanges.test @@ -5,6 +5,12 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +# Save original auto_increment_offset values. +--connection node_1 +let $auto_increment_offset_node_1 = `SELECT @@global.auto_increment_offset`; +--connection node_2 +let $auto_increment_offset_node_2 = `SELECT @@global.auto_increment_offset`; + --connection node_1 CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); @@ -21,3 +27,12 @@ SELECT COUNT(*) = 1 FROM t1; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; DROP TABLE t1; + +--disable_query_log +# Restore original auto_increment_offset values. +--connection node_1 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_1; +--connection node_2a +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_2; +--enable_query_log + diff --git a/mysql-test/suite/galera/t/galera_suspend_slave.test b/mysql-test/suite/galera/t/galera_suspend_slave.test index acee3626f7a..ac3fdf0ef40 100644 --- a/mysql-test/suite/galera/t/galera_suspend_slave.test +++ b/mysql-test/suite/galera/t/galera_suspend_slave.test @@ -7,6 +7,12 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +# Save original auto_increment_offset values. +--connection node_1 +let $auto_increment_offset_node_1 = `SELECT @@global.auto_increment_offset`; +--connection node_2 +let $auto_increment_offset_node_2 = `SELECT @@global.auto_increment_offset`; + --connection node_1 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; @@ -49,3 +55,12 @@ INSERT INTO t1 VALUES (1); SELECT COUNT(*) = 1 FROM t1; DROP TABLE t1; + +--disable_query_log +# Restore original auto_increment_offset values. +--connection node_1 +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_1; +--connection node_2a +--eval SET @@global.auto_increment_offset = $auto_increment_offset_node_2; +--enable_query_log + 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 f53986c49b8..17e77a9b5af 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_address.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -93,13 +93,3 @@ SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; 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'; -CALL mtr.add_suppression("WSREP: .*Backend not supported: foo.*"); -CALL mtr.add_suppression("WSREP: .*Failed to initialize backend using 'foo.*"); -CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'foo*"); -CALL mtr.add_suppression("WSREP: gcs connect failed: Socket type not supported"); -CALL mtr.add_suppression("WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: .*Failed to open backend connection: -110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: .*Failed to open channel 'my_wsrep_cluster' at 'gcomm://192\\.0\\.2\\.1': -110 \\(Connection timed out\\)"); -CALL mtr.add_suppression("WSREP: gcs connect failed: Connection timed out"); -CALL mtr.add_suppression("WSREP: wsrep::connect\\(\\) failed: 7"); -#CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); diff --git a/mysql-test/suite/galera/t/galera_var_max_ws_size.test b/mysql-test/suite/galera/t/galera_var_max_ws_size.test index 720f9be8a99..b66ef2d5ee2 100644 --- a/mysql-test/suite/galera/t/galera_var_max_ws_size.test +++ b/mysql-test/suite/galera/t/galera_var_max_ws_size.test @@ -6,10 +6,6 @@ --source include/have_innodb.inc --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.*'); CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB; From e1868fd61335129d648794389258de2ac021eb91 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 7 May 2015 22:18:34 +0200 Subject: [PATCH 275/294] MDEV-8115 mysql_upgrade crashes the server with REPAIR VIEW on REPAIR don't do table-specific stuff for views (because even if the view has a temp table opened for it, it's not opened all the way down the engine. In particular, Aria crashes in maria_status() because MARIA_HA* info - that is table->table->file->file - is NULL) --- mysql-test/r/repair.result | 7 +++++++ mysql-test/t/repair.test | 9 +++++++++ sql/sql_admin.cc | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 52ae9c38792..51c3374602d 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -207,3 +207,10 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +create table t1 (a blob); +create view v1 as select * from t1; +repair view v1; +Table Op Msg_type Msg_text +test.v1 repair status OK +drop view v1; +drop table t1; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 337b73f37d1..f625965090a 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -208,3 +208,12 @@ repair table t1 use_frm; select count(*) from t1; check table t1; drop table t1; + +# +# MDEV-8115 mysql_upgrade crashes the server with REPAIR VIEW +# +create table t1 (a blob); +create view v1 as select * from t1; +repair view v1; +drop view v1; +drop table t1; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 6c50a221c90..8909e5ae05d 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -901,7 +901,7 @@ send_result_message: break; } } - if (table->table) + if (table->table && !table->view) { if (table->table->s->tmp_table) { From 048039e0b2052cec0b72e6a442ef73e6b118437a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 11 May 2015 15:42:20 -0400 Subject: [PATCH 276/294] Fix for build failure. --- sql/sql_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 47b238715ac..f40053f6b49 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -858,7 +858,7 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, view->db, view->table_name); DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); } - sql_print_information("View %`s.%`s: the version is set to %llu%s%s", + sql_print_information("View %s.%s: the version is set to %llu%s%s", view->db, view->table_name, view->mariadb_version, (wrong_checksum ? ", checksum corrected" : ""), (swap_alg ? From c6c9a69ccee3325cfdd77d0dcd49259a574363b0 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 12 May 2015 16:56:06 -0400 Subject: [PATCH 277/294] Fix for some more test failures. --- mysql-test/suite/galera/disabled.def | 3 ++- mysql-test/suite/galera/r/galera_defaults.result | 2 +- mysql-test/suite/galera/r/galera_unicode_identifiers.result | 2 +- mysql-test/suite/galera/suite.pm | 3 +++ mysql-test/suite/galera/t/galera_defaults.test | 1 + mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf | 4 ++-- mysql-test/suite/galera/t/galera_unicode_identifiers.test | 2 +- mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result | 3 ++- mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test | 1 - mysql-test/suite/wsrep/disabled.def | 1 + 10 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/wsrep/disabled.def diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 397bf8e75c5..0a4e85686cb 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -15,4 +15,5 @@ galera_as_master_gtid : Needs to be re-worked galera_as_master_gtid_change_master : Needs to be re-worked galera_migrate : query 'let $success= `$wait_condition`' failed: 1146 galera_var_notify_cmd : Result content mismatch - +query_cache : Fails intermittently due to content mismatch. Needs to be investigated +basic : Fails intermittently without providing any output. Needs to be investigated diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index 4493a5df9ff..c2814dbcea2 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -47,7 +47,7 @@ WSREP_SST_DONOR WSREP_SST_DONOR_REJECTS_QUERIES OFF WSREP_SST_METHOD rsync WSREP_SYNC_WAIT 7 -; ; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; ; gcache.keep_pages_size = 0; gcache.mem_size = 0; ; gcache.page_size = 128M; gcache.size = 10M; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; gcs.recv_q_hard_limit = 9223372036854775807; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; ; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; ; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = P30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT30S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; +; ; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; ; gcache.keep_pages_size = 0; gcache.mem_size = 0; ; gcache.page_size = 128M; gcache.size = 10M; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; ; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; ; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; ; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = P30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT30S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_%' AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; diff --git a/mysql-test/suite/galera/r/galera_unicode_identifiers.result b/mysql-test/suite/galera/r/galera_unicode_identifiers.result index 212c6c65b67..8bea105c77e 100644 --- a/mysql-test/suite/galera/r/galera_unicode_identifiers.result +++ b/mysql-test/suite/galera/r/galera_unicode_identifiers.result @@ -7,7 +7,7 @@ CREATE TABLE `table with space` ( `second column with space` INTEGER, UNIQUE `index name with space` (`second column with space`) ); -INSERT INTO `table with space` VALUES (DEFAULT, 1); +INSERT INTO `table with space` VALUES (1, 1); CREATE DATABASE `база`; USE `база`; CREATE TABLE `таблица` ( diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 101614f2def..cf2299f6935 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -44,6 +44,7 @@ push @::global_suppressions, qr(WSREP: Member .* requested state transfer from .* but it is impossible to select State Transfer donor: Resource temporarily unavailable), qr(WSREP: user message in state LEAVING), qr(WSREP: .* sending install message failed: Transport endpoint is not connected), + qr(WSREP: .* sending install message failed: Resource temporarily unavailable), qr(WSREP: Maximum writeset size exceeded by .*), qr(WSREP: transaction size exceeded.*), qr(WSREP: RBR event .*), @@ -59,6 +60,8 @@ push @::global_suppressions, qr(WSREP: .*Failed to open channel 'my_wsrep_cluster' at .*), qr(WSREP: gcs connect failed: Connection timed out), qr|WSREP: wsrep::connect\(\) failed: 7|, + qr(WSREP: SYNC message from member .* in non-primary configuration. Ignored.), + qr(WSREP: Could not find peer:), ); diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test index 995e0b4c451..9897d0d55dc 100644 --- a/mysql-test/suite/galera/t/galera_defaults.test +++ b/mysql-test/suite/galera/t/galera_defaults.test @@ -50,6 +50,7 @@ ORDER BY VARIABLE_NAME; $wsrep_provider_options =~ s/gcache\.dir = .*?;/;/sgio; $wsrep_provider_options =~ s/gcache\.name = .*?;/;/sgio; $wsrep_provider_options =~ s/gmcast\.listen_addr = .*?;/;/sgio; + $wsrep_provider_options =~ s/gcs\.recv_q_hard_limit = .*?;/;/sgio; $wsrep_provider_options =~ s/ist\.recv_addr = .*?;/;/sgio; $wsrep_provider_options =~ s/evs\.evict = .*?;/;/sgio; $wsrep_provider_options =~ s/signal = .*?;\s*//sgio; diff --git a/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf index aae3fee5904..6bb11e5957a 100644 --- a/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf +++ b/mysql-test/suite/galera/t/galera_gcs_max_packet_size.cnf @@ -1,5 +1,5 @@ !include ../galera_2nodes.cnf [mysqld.1] -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcs.max_packet_size=64' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcs.max_packet_size=64;gcache.size=10M' [mysqld.2] -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcs.max_packet_size=64' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcs.max_packet_size=64;gcache.size=10M' diff --git a/mysql-test/suite/galera/t/galera_unicode_identifiers.test b/mysql-test/suite/galera/t/galera_unicode_identifiers.test index 2f255e9a197..9adac1aa555 100644 --- a/mysql-test/suite/galera/t/galera_unicode_identifiers.test +++ b/mysql-test/suite/galera/t/galera_unicode_identifiers.test @@ -22,7 +22,7 @@ CREATE TABLE `table with space` ( `second column with space` INTEGER, UNIQUE `index name with space` (`second column with space`) ); -INSERT INTO `table with space` VALUES (DEFAULT, 1); +INSERT INTO `table with space` VALUES (1, 1); # Unicode identifiers diff --git a/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result b/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result index 95b59e62adc..10f1d654c12 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_osu_method_basic.result @@ -10,7 +10,8 @@ TOI # scope SELECT @@session.wsrep_osu_method; -ERROR HY000: Variable 'wsrep_OSU_method' is a GLOBAL variable +@@session.wsrep_osu_method +TOI SET @@global.wsrep_osu_method=TOI; SELECT @@global.wsrep_osu_method; @@global.wsrep_osu_method diff --git a/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test b/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test index d6d461075a5..ce3a3def88b 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_osu_method_basic.test @@ -12,7 +12,6 @@ SELECT @@global.wsrep_osu_method; --echo --echo # scope ---error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@session.wsrep_osu_method; SET @@global.wsrep_osu_method=TOI; SELECT @@global.wsrep_osu_method; diff --git a/mysql-test/suite/wsrep/disabled.def b/mysql-test/suite/wsrep/disabled.def new file mode 100644 index 00000000000..605f063f967 --- /dev/null +++ b/mysql-test/suite/wsrep/disabled.def @@ -0,0 +1 @@ +foreign_key : MDEV-7915 From 18fee8b8f8b7cdf3d58075c9734e9ace23e2dbec Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 12 May 2015 17:05:41 -0400 Subject: [PATCH 278/294] Revert last commit. --- sql/sql_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f40053f6b49..47b238715ac 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -858,7 +858,7 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, view->db, view->table_name); DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); } - sql_print_information("View %s.%s: the version is set to %llu%s%s", + sql_print_information("View %`s.%`s: the version is set to %llu%s%s", view->db, view->table_name, view->mariadb_version, (wrong_checksum ? ", checksum corrected" : ""), (swap_alg ? From 014fe12c03a2fdcbd2eb6bab39118de1cee02693 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 12 May 2015 14:19:30 -0400 Subject: [PATCH 279/294] Fix for debug build failure Do not use format function attribute for sql_print_xxx() family of functions as they use a MariaDB-specific extension of printf instead of one provided by the system. --- sql/log.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sql/log.h b/sql/log.h index ed33ace7405..4abefc55b90 100644 --- a/sql/log.h +++ b/sql/log.h @@ -881,11 +881,9 @@ uint purge_log_get_error_code(int res); int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); void sql_print_error(const char *format, ...); -void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); -void sql_print_information(const char *format, ...) - ATTRIBUTE_FORMAT(printf, 1, 2); -typedef void (*sql_print_message_func)(const char *format, ...) - ATTRIBUTE_FORMAT_FPTR(printf, 1, 2); +void sql_print_warning(const char *format, ...); +void sql_print_information(const char *format, ...); +typedef void (*sql_print_message_func)(const char *format, ...); extern sql_print_message_func sql_print_message_handlers[]; int error_log_print(enum loglevel level, const char *format, From 7003776e739d2f49cba4bb39cceaea184dcfc38f Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Tue, 12 May 2015 03:44:10 +0300 Subject: [PATCH 280/294] MDEV-8144 percona.innodb_sys_index test fails Restoring the line affected by 5.5=>10.0 merge --- mysql-test/suite/percona/innodb_sys_index.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/percona/innodb_sys_index.result b/mysql-test/suite/percona/innodb_sys_index.result index 1f1bd814886..7573720f5ee 100644 --- a/mysql-test/suite/percona/innodb_sys_index.result +++ b/mysql-test/suite/percona/innodb_sys_index.result @@ -1,6 +1,6 @@ drop table if exists t1; Warnings: -Note 1051 Unknown table 't1' +Note 1051 Unknown table 'test.t1' SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; CREATE TABLE test.t1 ( `a` SERIAL NOT NULL , `b` VARCHAR( 255 ) NOT NULL , INDEX ( `b` ) ) ENGINE = InnoDB ; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; From c9c8e0554f43154775c8a3b755a329a5a6035664 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 12 May 2015 23:43:06 -0400 Subject: [PATCH 281/294] Update galera/disabled.def & some more test fixes. --- mysql-test/suite/galera/disabled.def | 2 -- mysql-test/suite/galera/r/galera_ist_rsync.result | 3 ++- .../suite/galera/r/galera_var_auto_inc_control_on.result | 8 ++++---- .../suite/galera/t/galera_var_auto_inc_control_on.test | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 0a4e85686cb..9e0949ef015 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -5,8 +5,6 @@ galera_toi_ddl_fk_insert : qa#39 galera_toi_ddl_fk_insert fails sporadically galera_binlog_row_image : MDEV-7471 - Enable binlog_row_image parameter in MariaDB galera_binlog_rows_query_log_events : Unknown system variable 'binlog_rows_query_log_events' (see annotate_rows_log_event) -galera_sbr : MDEV-7995 - DMLs not getting replicated with log-bin=OFF & binlog-format != ROW -galera_create_trigger : MDEV-7996 - CURRENT_USER definer does not replicate for triggers galera_ist_mysqldump : Lost connection to MySQL server during query galera_ist_xtrabackup-v2 : mysqltest failed but provided no output galera_ist_innodb_flush_logs : mysqltest failed but provided no output diff --git a/mysql-test/suite/galera/r/galera_ist_rsync.result b/mysql-test/suite/galera/r/galera_ist_rsync.result index 175e7443a4d..0b25a299b24 100644 --- a/mysql-test/suite/galera/r/galera_ist_rsync.result +++ b/mysql-test/suite/galera/r/galera_ist_rsync.result @@ -276,7 +276,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; -SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ALTER TABLE t1 ADD COLUMN f2 INTEGER; SET wsrep_sync_wait = 0; Killing server ... @@ -355,3 +355,4 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result index 8859209cc0c..c1bb065975b 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 @@ -2,16 +2,16 @@ CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') 1 -SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; -@@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 +SELECT @@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +@@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 1 INSERT INTO t1 VALUES (DEFAULT, 'node1');; INSERT INTO t1 VALUES (DEFAULT, 'node2');; SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') 1 -SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; -@@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 +SELECT @@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +@@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1 1 INSERT INTO t1 VALUES (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2');; INSERT INTO t1 VALUES (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1'), (DEFAULT, 'node1');; diff --git a/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test b/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test index 59f2615b685..d65a35be4d1 100644 --- a/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test +++ b/mysql-test/suite/galera/t/galera_var_auto_inc_control_on.test @@ -13,7 +13,7 @@ CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE # auto_increment_offset is equal to the ID of the node SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); -SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +SELECT @@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; # Expect no conflicts --send INSERT INTO t1 VALUES (DEFAULT, 'node1'); @@ -28,7 +28,7 @@ SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA. --reap SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); -SELECT @@auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; +SELECT @@global.auto_increment_offset = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_index') + 1; # Expect no conflicts --send INSERT INTO t1 VALUES (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'), (DEFAULT, 'node2'); From 8fdf8f00c714471d499c0e9206940f3f2e8a22f3 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 14 May 2015 14:25:02 -0400 Subject: [PATCH 282/294] mysql-wsrep#38 : wsrep_sst_xtrabackup-v2 script causes innobackupex to ..print a false positive stack trace into the log Suppress the stacktrace that innobackupex dumps on receiving SIGPIPE. --- scripts/wsrep_sst_xtrabackup-v2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 1a191a6ad6b..9af5c758a17 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -550,7 +550,7 @@ setup_ports get_stream get_transfer -if ${INNOBACKUPEX_BIN} /tmp --help | grep -q -- '--version-check'; then +if ${INNOBACKUPEX_BIN} /tmp --help | grep -- '--version-check' >/dev/null ; then disver="--no-version-check" fi From 14b816a5c8899e9c7cbccf7dd394032af0896223 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 14 May 2015 21:48:54 -0400 Subject: [PATCH 283/294] Disabling some more sporadically failing galera tests. --- mysql-test/suite/galera/disabled.def | 4 ++++ mysql-test/suite/galera/suite.pm | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 9e0949ef015..9c38c1296fe 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -15,3 +15,7 @@ galera_migrate : query 'let $success= `$wait_condition`' failed: 1146 galera_var_notify_cmd : Result content mismatch query_cache : Fails intermittently due to content mismatch. Needs to be investigated basic : Fails intermittently without providing any output. Needs to be investigated +galera_var_auto_inc_control_on : Failing sporadically with content mismatch +galera_parallel_simple : Failing sporadically +galera_bf_abort : Failing sporadically +galera_log_output_csv : Failing sporadically diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index cf2299f6935..e8ab313b8ca 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -62,6 +62,10 @@ push @::global_suppressions, qr|WSREP: wsrep::connect\(\) failed: 7|, qr(WSREP: SYNC message from member .* in non-primary configuration. Ignored.), qr(WSREP: Could not find peer:), + qr(WSREP: TO isolation failed for: .*), + qr|WSREP: gcs_caused\(\) returned .*|, + qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|, + qr(WSREP: Action message in non-primary configuration from member [0-9]*), ); From 0bfae356d4f774c939a5642cd19ee6bfc682b8e7 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 16 May 2015 11:11:26 -0400 Subject: [PATCH 284/294] MDEV-8166 : Adding index on new table from select crashes Galera cluster In wsrep, CTAS should be handled like a regular transaction. Added a test case. --- mysql-test/suite/galera/r/create.result | 31 +++++++++++++++++++++++++ mysql-test/suite/galera/t/create.test | 24 +++++++++++++++++++ sql/sql_parse.cc | 9 +------ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index 2c31ed76d1e..d32a0378eb6 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -24,5 +24,36 @@ SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; # MDEV-7673: CREATE TABLE SELECT fails on Galera cluster # CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; +SELECT * FROM t1; +i +1 +SELECT * FROM t1; +i +1 DROP TABLE t1; +# +# MDEV-8166 : Adding index on new table from select crashes Galera +# cluster +# +CREATE TABLE t1(i int(11) NOT NULL DEFAULT '0') ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1(i) VALUES (1), (2), (3); +CREATE TABLE t2 (i INT) SELECT i FROM t1; +ALTER TABLE t2 ADD INDEX idx(i); +SELECT * FROM t2; +i +1 +2 +3 +SELECT * FROM t2; +i +1 +2 +3 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `i` int(11) DEFAULT NULL, + KEY `idx` (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; # End of tests diff --git a/mysql-test/suite/galera/t/create.test b/mysql-test/suite/galera/t/create.test index 38c793e33b6..fb9b0935288 100644 --- a/mysql-test/suite/galera/t/create.test +++ b/mysql-test/suite/galera/t/create.test @@ -25,10 +25,34 @@ SET @@GLOBAL.wsrep_forced_binlog_format=@wsrep_forced_binlog_format_saved; --echo # --echo # MDEV-7673: CREATE TABLE SELECT fails on Galera cluster --echo # +--connection node_1 CREATE TABLE t1 (i INT) ENGINE=INNODB DEFAULT CHARSET=utf8 SELECT 1 as i; +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; # Cleanup DROP TABLE t1; +--echo # +--echo # MDEV-8166 : Adding index on new table from select crashes Galera +--echo # cluster +--echo # +--connection node_1 +CREATE TABLE t1(i int(11) NOT NULL DEFAULT '0') ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1(i) VALUES (1), (2), (3); + +CREATE TABLE t2 (i INT) SELECT i FROM t1; +ALTER TABLE t2 ADD INDEX idx(i); + +SELECT * FROM t2; + +--connection node_2 +SELECT * FROM t2; +SHOW CREATE TABLE t2; + +# Cleanup +DROP TABLE t1, t2; + --echo # End of tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1b965b080e0..a0b98ec5601 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2917,17 +2917,10 @@ case SQLCOM_PREPARE: if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->variables.option_bits|= OPTION_KEEP_LOG; -#ifdef WITH_WSREP - if (WSREP(thd) && - (!thd->is_current_stmt_binlog_format_row() || - !(create_info.options & HA_LEX_CREATE_TMP_TABLE))) - WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, - NULL) -#endif - /* select_create is currently not re-execution friendly and needs to be created for every execution of a PS/SP. + Note: In wsrep-patch, CTAS is handled like a regular transaction. */ if ((result= new select_create(create_table, &create_info, From 9eff9ed5c58e782abf383a52a7e691a55b4798a2 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 24 May 2015 13:30:49 -0400 Subject: [PATCH 285/294] MDEV-8208 : Sporadic SEGFAULT on startup During server start, as wsrep initialization happens before plugin_init(), segfault may occur if wsrep THDs try to access the uninitialized maria_hton. --- sql/mysqld.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6bffc8343a1..2008fc54245 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4497,6 +4497,12 @@ will be ignored as the --log-bin option is not defined."); set_ports(); // this is also called in network_init() later but we need // to know mysqld_port now - lp:1071882 #endif /* !EMBEDDED_LIBRARY */ + + /* + Plugin initialization (plugin_init()) hasn't happened yet, set + maria_hton to 0. + */ + maria_hton= 0; wsrep_init_startup(true); } } From 6050ab658696925f2a031b901eb398fff65fa92a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 18 Jun 2015 09:59:09 -0400 Subject: [PATCH 286/294] MDEV-6829 : SELinux/AppArmor policies for Galera server Add SELinux policy and AppArmor profile under policy/. --- policy/apparmor/README | 5 + policy/apparmor/usr.sbin.mysqld | 150 ++++++++++++++++++++++++++ policy/apparmor/usr.sbin.mysqld.local | 4 + policy/selinux/README | 18 ++++ policy/selinux/mariadb-server.fc | 10 ++ policy/selinux/mariadb-server.te | 91 ++++++++++++++++ 6 files changed, 278 insertions(+) create mode 100644 policy/apparmor/README create mode 100644 policy/apparmor/usr.sbin.mysqld create mode 100644 policy/apparmor/usr.sbin.mysqld.local create mode 100644 policy/selinux/README create mode 100644 policy/selinux/mariadb-server.fc create mode 100644 policy/selinux/mariadb-server.te diff --git a/policy/apparmor/README b/policy/apparmor/README new file mode 100644 index 00000000000..271655f1e37 --- /dev/null +++ b/policy/apparmor/README @@ -0,0 +1,5 @@ +Note: The included AppArmor profiles can be used for MariaDB Galera cluster. +However, since these profiles had been tested for a limited set of scenarios, +it is highly recommended to run them in "complain" mode and report any denials +on mariadb.org/jira. + diff --git a/policy/apparmor/usr.sbin.mysqld b/policy/apparmor/usr.sbin.mysqld new file mode 100644 index 00000000000..307872c0fff --- /dev/null +++ b/policy/apparmor/usr.sbin.mysqld @@ -0,0 +1,150 @@ +# Last Modified: Fri Mar 1 18:55:47 2013 +# Based on usr.sbin.mysqld packaged in mysql-server in Ubuntu. +# This AppArmor profile has been copied under BSD License from +# Percona XtraDB Cluster, along with some additions. + +#include + +/usr/sbin/mysqld flags=(complain) { + #include + #include + #include + #include + #include + + capability chown, + capability dac_override, + capability setgid, + capability setuid, + capability sys_rawio, + capability sys_resource, + + network tcp, + + /bin/dash rcx, + /dev/dm-0 r, + /etc/gai.conf r, + /etc/group r, + /etc/hosts.allow r, + /etc/hosts.deny r, + /etc/ld.so.cache r, + /etc/mtab r, + /etc/my.cnf r, + /etc/mysql/*.cnf r, + /etc/mysql/*.pem r, + /etc/mysql/conf.d/ r, + /etc/mysql/conf.d/* r, + /etc/nsswitch.conf r, + /etc/passwd r, + /etc/services r, + /run/mysqld/mysqld.pid w, + /run/mysqld/mysqld.sock w, + /sys/devices/system/cpu/ r, + owner /tmp/** lk, + /tmp/** rw, + /usr/lib/mysql/plugin/ r, + /usr/lib/mysql/plugin/*.so* mr, + /usr/sbin/mysqld mr, + /usr/share/mysql/** r, + /var/lib/mysql/ r, + /var/lib/mysql/** rwk, + /var/log/mysql.err rw, + /var/log/mysql.log rw, + /var/log/mysql/ r, + /var/log/mysql/* rw, + /var/run/mysqld/mysqld.pid w, + /var/run/mysqld/mysqld.sock w, + + + profile /bin/dash flags=(complain) { + #include + #include + #include + #include + #include + + + + /bin/cat rix, + /bin/dash rix, + /bin/date rix, + /bin/grep rix, + /bin/nc.openbsd rix, + /bin/netstat rix, + /bin/ps rix, + /bin/rm rix, + /bin/sed rix, + /bin/sleep rix, + /bin/tar rix, + /bin/which rix, + /dev/tty rw, + /etc/ld.so.cache r, + /etc/my.cnf r, + /proc/ r, + /proc/*/cmdline r, + /proc/*/fd/ r, + /proc/*/net/dev r, + /proc/*/net/if_inet6 r, + /proc/*/net/tcp r, + /proc/*/net/tcp6 r, + /proc/*/stat r, + /proc/*/status r, + /proc/sys/kernel/pid_max r, + /proc/tty/drivers r, + /proc/uptime r, + /proc/version r, + /sbin/ifconfig rix, + /sys/devices/system/cpu/ r, + /tmp/** rw, + /usr/bin/cut rix, + /usr/bin/dirname rix, + /usr/bin/gawk rix, + /usr/bin/innobackupex rix, + /usr/bin/mysql rix, + /usr/bin/perl rix, + /usr/bin/seq rix, + /usr/bin/wsrep_sst* rix, + /usr/bin/wsrep_sst_common r, + /usr/bin/xtrabackup* rix, + /var/lib/mysql/ r, + /var/lib/mysql/** rw, + /var/lib/mysql/*.log w, + /var/lib/mysql/*.err w, + +# MariaDB additions + ptrace peer=@{profile_name}, + + /bin/hostname rix, + /bin/ip rix, + /bin/mktemp rix, + /bin/ss rix, + /bin/sync rix, + /bin/touch rix, + /bin/uname rix, + /etc/mysql/*.cnf r, + /etc/mysql/conf.d/ r, + /etc/mysql/conf.d/* r, + /proc/*/attr/current r, + /proc/*/fdinfo/* r, + /proc/*/net/* r, + /proc/locks r, + /proc/sys/net/ipv4/ip_local_port_range r, + /run/mysqld/mysqld.sock rw, + /sbin/ip rix, + /usr/bin/basename rix, + /usr/bin/du rix, + /usr/bin/find rix, + /usr/bin/lsof rix, + /usr/bin/my_print_defaults rix, + /usr/bin/mysqldump rix, + /usr/bin/pv rix, + /usr/bin/rsync rix, + /usr/bin/socat rix, + /usr/bin/tail rix, + /usr/bin/timeout rix, + /usr/bin/xargs rix, + /usr/bin/xbstream rix, + } + # Site-specific additions and overrides. See local/README for details. + #include +} diff --git a/policy/apparmor/usr.sbin.mysqld.local b/policy/apparmor/usr.sbin.mysqld.local new file mode 100644 index 00000000000..a0b8a0279de --- /dev/null +++ b/policy/apparmor/usr.sbin.mysqld.local @@ -0,0 +1,4 @@ +# Site-specific additions and overrides for usr.sbin.mysqld.. +# For more details, please see /etc/apparmor.d/local/README. +# This AppArmor profile has been copied under BSD License from +# Percona XtraDB Cluster, along with some additions. diff --git a/policy/selinux/README b/policy/selinux/README new file mode 100644 index 00000000000..a8c11c71a0b --- /dev/null +++ b/policy/selinux/README @@ -0,0 +1,18 @@ +Note: The included SELinux policy files can be used for MariaDB Galera cluster. +However, since these policies had been tested for a limited set of scenarios, +it is highly recommended to run SELinux in "permissive" mode even with these +policies installed and report any denials on mariadb.org/jira. + + +How to generate and load the policy module of MariaDB Galera cluster ? + +* Generate the SELinux policy module. + # cd /policy/selinux/ + # make -f /usr/share/selinux/devel/Makefile mariadb-server.pp + +* Load the generated policy module. + # semodule -i /path/to/mariadb-server.pp + +* Lastly, run the following command to allow 4568. + # semanage port -a -t mysqld_port_t -p tcp 4568 + diff --git a/policy/selinux/mariadb-server.fc b/policy/selinux/mariadb-server.fc new file mode 100644 index 00000000000..1a69ecc2c40 --- /dev/null +++ b/policy/selinux/mariadb-server.fc @@ -0,0 +1,10 @@ +# This SELinux file contexts (.fc) file has been copied under BSD License from +# Percona XtraDB Cluster. + +/etc/init\.d/rc\.d/mysql -- gen_context(system_u:object_r:mysqld_initrc_exec_t,s0) +/var/lib/mysql/.*\.log -- gen_context(system_u:object_r:mysqld_log_t,s0) +/var/lib/mysql/.*\.err -- gen_context(system_u:object_r:mysqld_log_t,s0) +/var/lib/mysql/.*\.pid -- gen_context(system_u:object_r:mysqld_var_run_t,s0) +/var/lib/mysql/.*\.cnf -- gen_context(system_u:object_r:mysqld_etc_t,s0) +/usr/bin/xtrabackup.* -- gen_context(system_u:object_r:mysqld_exec_t,s0) +/usr/bin/wsrep.* -- gen_context(system_u:object_r:mysqld_safe_exec_t,s0) diff --git a/policy/selinux/mariadb-server.te b/policy/selinux/mariadb-server.te new file mode 100644 index 00000000000..9c0319c83f5 --- /dev/null +++ b/policy/selinux/mariadb-server.te @@ -0,0 +1,91 @@ +# This SELinux type enforcement (.te) file has been copied under BSD License +# from Percona XtraDB Cluster, along with some additions. + +module mariadb-server 1.0; + +require { + type user_tmp_t; + type kerberos_port_t; + type mysqld_safe_t; + type tmp_t; + type tmpfs_t; + type hostname_exec_t; + type ifconfig_exec_t; + type sysctl_net_t; + type proc_net_t; + type port_t; + type mysqld_t; + type var_lib_t; + type rsync_exec_t; + type bin_t; + type shell_exec_t; + type anon_inodefs_t; + type fixed_disk_device_t; + class lnk_file read; + class process { getattr signull }; + class unix_stream_socket connectto; + class capability { sys_resource sys_nice }; + class tcp_socket { name_bind name_connect }; + class file { execute setattr read create getattr execute_no_trans write ioctl open append unlink }; + class sock_file { create unlink getattr }; + class blk_file { read write open }; + class dir { write search getattr add_name read remove_name open }; + +# MariaDB additions + type tram_port_t; + class process setpgid; + class netlink_tcpdiag_socket { create nlmsg_read }; +} + + +#============= mysqld_safe_t ============== +allow mysqld_safe_t mysqld_t:process signull; +allow mysqld_safe_t self:capability { sys_resource sys_nice }; +allow mysqld_safe_t tmp_t:file { create read write open getattr unlink ioctl setattr }; +allow mysqld_safe_t tmp_t:dir { write remove_name add_name }; +allow mysqld_safe_t tmp_t:sock_file { getattr unlink }; +allow mysqld_safe_t user_tmp_t:sock_file { getattr unlink }; +allow mysqld_safe_t var_lib_t:dir { write add_name }; +allow mysqld_safe_t var_lib_t:file { write ioctl setattr create open getattr append unlink }; + +#============= mysqld_t ============== +allow mysqld_t anon_inodefs_t:file write; +allow mysqld_t tmp_t:sock_file { create unlink }; +allow mysqld_t tmpfs_t:dir { write search read remove_name open add_name }; +allow mysqld_t tmpfs_t:file { write getattr read create unlink open }; +allow mysqld_t fixed_disk_device_t:blk_file { read write open }; +allow mysqld_t ifconfig_exec_t:file { read execute open execute_no_trans getattr }; + +#This rule allows connecting on 4444 +allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; + +allow mysqld_t mysqld_safe_t:dir { getattr search }; +allow mysqld_t mysqld_safe_t:file { read open }; +allow mysqld_t self:unix_stream_socket connectto; +allow mysqld_t port_t:tcp_socket { name_bind name_connect }; +allow mysqld_t proc_net_t:file { read getattr open }; +allow mysqld_t sysctl_net_t:dir search; +allow mysqld_t var_lib_t:file { getattr open append }; +allow mysqld_t var_lib_t:sock_file { create unlink getattr }; +allow mysqld_t rsync_exec_t:file { read getattr open execute execute_no_trans }; +allow mysqld_t self:process getattr; +allow mysqld_t hostname_exec_t:file { read getattr execute open execute_no_trans }; +allow mysqld_t user_tmp_t:dir { write add_name }; +allow mysqld_t user_tmp_t:file create; +allow mysqld_t bin_t:lnk_file read; +allow mysqld_t tmp_t:file { append create read write open getattr unlink setattr }; + +# Allows too much leeway - the xtrabackup/wsrep rules in fc should fix it, but +# keep for the moment. +allow mysqld_t shell_exec_t:file { execute_no_trans getattr read execute open }; +allow mysqld_t bin_t:file { getattr read execute open execute_no_trans ioctl }; + +# MariaDB additions +allow mysqld_t self:process setpgid; +# This rule allows port 4567 +allow mysqld_t tram_port_t:tcp_socket name_bind; + +# Rules related to XtraBackup +allow mysqld_t self:netlink_tcpdiag_socket { create nlmsg_read }; +allow mysqld_t sysctl_net_t:file { read getattr open }; + From 8c44fd63ac61161e92e7feb55d693d72aebac68d Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 19 Jun 2015 00:17:25 -0400 Subject: [PATCH 287/294] MDEV-8239 : Idle threads post-execution end up in closing tables state Set thd's state to 'committed' only after it has done closing tables (called indirectly by relay_group_info::cleanup_context()). --- .../r/galera_parallel_apply_lock_table.result | 2 +- .../r/galera_parallel_autoinc_manytrx.result | 2 +- .../t/galera_parallel_apply_lock_table.test | 2 +- .../t/galera_parallel_autoinc_manytrx.test | 2 +- .../r/galera_parallel_apply_3nodes.result | 2 +- .../t/galera_parallel_apply_3nodes.test | 2 +- sql/wsrep_applier.cc | 16 ++++++++-------- 7 files changed, 14 insertions(+), 14 deletions(-) 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 b9718026828..db4528ac22d 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 @@ -25,7 +25,7 @@ COUNT(*) = 1 SELECT COUNT(*) = 1 FROM t2; COUNT(*) = 1 1 -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'closing tables'; +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_manytrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result index d7ee754f695..05ce328228a 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result @@ -8,7 +8,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 'closing tables'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; COUNT(*) = 4 1 DROP TABLE t1; 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 a071a1fab1b..febb91a9725 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 @@ -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 'closing tables'; +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_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test index d67eba4d37c..cf984f92b2f 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test @@ -41,7 +41,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 'closing tables'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; --disable_query_log --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; 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 1d0da8bf50c..ec97d392c0f 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 @@ -6,7 +6,7 @@ UPDATE t1 SET f1 = f1 + 100;; SELECT f1 = 111 FROM t1; f1 = 111 1 -SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'closing tables'; +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/t/galera_parallel_apply_3nodes.test b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test index ef5eb8aca4a..7d80d8036a1 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 'closing tables'; +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/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 9fdc3952f3f..4d95b38a371 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -295,14 +295,6 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd, wsrep_cb_status_t const rcode(trans_commit(thd) ? WSREP_CB_FAILURE : WSREP_CB_SUCCESS); -#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 */ - if (WSREP_CB_SUCCESS == rcode) { thd->wsrep_rgi->cleanup_context(thd, false); @@ -312,6 +304,14 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd, // TODO: mark snapshot with global_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; } From fc716dc5a5abd6997310256a1f846e39ea5bf312 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 19 Jun 2015 19:25:15 -0400 Subject: [PATCH 288/294] MDEV-8260 : Issues related to concurrent CTAS * Wait for aborted thd (victim) to release MDL locks * Skip aborting an already aborted thd * Defer setting OK status in case of CTAS * Minor cosmetic changes * Added a test case --- .../galera/r/galera_concurrent_ctas.result | 1 + .../galera/t/galera_concurrent_ctas.test | 57 +++++++++++++++ sql/mdl.cc | 12 +++- sql/sql_class.h | 2 + sql/sql_insert.cc | 71 +++++++++++++------ sql/wsrep_mysqld.cc | 11 +++ sql/wsrep_thd.cc | 11 +++ 7 files changed, 142 insertions(+), 23 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_concurrent_ctas.result create mode 100644 mysql-test/suite/galera/t/galera_concurrent_ctas.test diff --git a/mysql-test/suite/galera/r/galera_concurrent_ctas.result b/mysql-test/suite/galera/r/galera_concurrent_ctas.result new file mode 100644 index 00000000000..8b0a4c07ac2 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_concurrent_ctas.result @@ -0,0 +1 @@ +# End of test diff --git a/mysql-test/suite/galera/t/galera_concurrent_ctas.test b/mysql-test/suite/galera/t/galera_concurrent_ctas.test new file mode 100644 index 00000000000..f0dcf8e4900 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_concurrent_ctas.test @@ -0,0 +1,57 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--write_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +DROP table t1; +CREATE table t1 as SELECT SLEEP(0); +CREATE table t2 as SELECT SLEEP(0); +CREATE table t3 as SELECT SLEEP(0); +CREATE table t4 as SELECT SLEEP(0); +CREATE table t5 as SELECT SLEEP(0); +CREATE table t6 as SELECT SLEEP(0); +CREATE table t7 as SELECT SLEEP(0); +CREATE table t8 as SELECT SLEEP(0); +CREATE table t9 as SELECT SLEEP(0); +DROP table t1; +DROP table t2; +DROP table t3; +DROP table t4; +DROP table t5; +DROP table t6; +DROP table t7; +DROP table t8; +DROP table t9; +EOF + +let $run=10; + +while($run) +{ + --error 0,1 + exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test + < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & + $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test + < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql; + dec $run; +} + +--remove_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql + +--source include/galera_end.inc +--echo # End of test + diff --git a/sql/mdl.cc b/sql/mdl.cc index 56f005d0eeb..5183a9806c9 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1199,6 +1199,13 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, while (!m_wait_status && !thd->killed && wait_result != ETIMEDOUT && wait_result != ETIME) { +#ifdef WITH_WSREP + if (wsrep_thd_is_BF(thd, true)) + { + wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status); + } + else +#endif wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status, abs_timeout); } @@ -1283,12 +1290,15 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", wsrep_thd_thread_id(waiting->get_ctx()->get_thd()), wsrep_thd_query(waiting->get_ctx()->get_thd())); + /* Insert the ticket before the first non-BF waiting thd. */ m_list.insert_after(prev, ticket); added= true; } prev= waiting; } - if (!added) m_list.push_back(ticket); + + /* Otherwise, insert the ticket at the back of the waiting list. */ + if (!added) m_list.push_back(ticket); while ((granted= itg++)) { diff --git a/sql/sql_class.h b/sql/sql_class.h index 1ecb6719ad4..c51d0f8dcc3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3486,6 +3486,8 @@ class select_insert :public select_result_interceptor { virtual void store_values(List &values); virtual bool can_rollback_data() { return 0; } void send_error(uint errcode,const char *err); + bool prepare_eof(); + bool send_ok_packet(); bool send_eof(); virtual void abort_result_set(); /* not implemented: select_insert is never re-used in prepared statements */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e8f3c91cc70..a6505e0cc69 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3650,14 +3650,14 @@ void select_insert::send_error(uint errcode,const char *err) } -bool select_insert::send_eof() +bool select_insert::prepare_eof() { int error; bool const trans_table= table->file->has_transactions(); - ulonglong id, row_count; bool changed; killed_state killed_status= thd->killed; - DBUG_ENTER("select_insert::send_eof"); + + DBUG_ENTER("select_insert::prepare_eof"); DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", trans_table, table->file->table_type())); @@ -3699,11 +3699,10 @@ bool select_insert::send_eof() */ #ifdef WITH_WSREP if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) && - (!error || thd->transaction.stmt.modified_non_trans_table)) #else if (mysql_bin_log.is_open() && - (!error || thd->transaction.stmt.modified_non_trans_table)) #endif + (!error || thd->transaction.stmt.modified_non_trans_table)) { int errcode= 0; if (!error) @@ -3715,7 +3714,7 @@ bool select_insert::send_eof() trans_table, FALSE, FALSE, errcode)) { table->file->ha_release_auto_increment(); - DBUG_RETURN(1); + DBUG_RETURN(true); } } table->file->ha_release_auto_increment(); @@ -3723,27 +3722,49 @@ bool select_insert::send_eof() if (error) { table->file->print_error(error,MYF(0)); - DBUG_RETURN(1); + DBUG_RETURN(true); } - char buff[160]; + + DBUG_RETURN(false); +} + +bool select_insert::send_ok_packet() { + char message[160]; /* status message */ + ulong row_count; /* rows affected */ + ulong id; /* last insert-id */ + + DBUG_ENTER("select_insert::send_ok_packet"); + if (info.ignore) - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.records - info.copied), - (ulong) thd->warning_info->statement_warn_count()); + my_snprintf(message, sizeof(message), ER(ER_INSERT_INFO), + (ulong) info.records, (ulong) (info.records - info.copied), + (ulong) thd->warning_info->statement_warn_count()); else - sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.deleted+info.updated), - (ulong) thd->warning_info->statement_warn_count()); + my_snprintf(message, sizeof(message), ER(ER_INSERT_INFO), + (ulong) info.records, (ulong) (info.deleted + info.updated), + (ulong) thd->warning_info->statement_warn_count()); + row_count= info.copied + info.deleted + - ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? - info.touched : info.updated); + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); + id= (thd->first_successful_insert_id_in_cur_stmt > 0) ? thd->first_successful_insert_id_in_cur_stmt : (thd->arg_of_last_insert_id_function ? thd->first_successful_insert_id_in_prev_stmt : (info.copied ? autoinc_value_of_last_inserted_row : 0)); - ::my_ok(thd, row_count, id, buff); - DBUG_RETURN(0); + + ::my_ok(thd, row_count, id, message); + + DBUG_RETURN(false); +} + +bool select_insert::send_eof() +{ + bool res; + DBUG_ENTER("select_insert::send_eof"); + res= (prepare_eof() || send_ok_packet()); + DBUG_RETURN(res); } void select_insert::abort_result_set() { @@ -4240,9 +4261,12 @@ void select_create::send_error(uint errcode,const char *err) bool select_create::send_eof() { - bool tmp=select_insert::send_eof(); - if (tmp) + DBUG_ENTER("select_create::send_eof"); + if (prepare_eof()) + { abort_result_set(); + DBUG_RETURN(true); + } else { /* @@ -4262,7 +4286,7 @@ bool select_create::send_eof() thd->thread_id, thd->wsrep_conflict_state, thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); abort_result_set(); - return TRUE; + DBUG_RETURN(true); } mysql_mutex_unlock(&thd->LOCK_wsrep_thd); #endif /* WITH_WSREP */ @@ -4270,6 +4294,9 @@ bool select_create::send_eof() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); + + send_ok_packet(); + if (m_plock) { mysql_unlock_tables(thd, *m_plock); @@ -4277,7 +4304,7 @@ bool select_create::send_eof() m_plock= NULL; } } - return tmp; + DBUG_RETURN(false); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a48e28b73f6..ef804fb7c5f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1476,10 +1476,21 @@ void wsrep_to_isolation_end(THD *thd) gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ gra->command, gra->lex->sql_command, gra->query()); +/** + Check if request for the metadata lock should be granted to the requester. + + @param requestor_ctx The MDL context of the requestor + @param ticket MDL ticket for the requested lock + + @retval TRUE Lock request can be granted + @retval FALSE Lock request cannot be granted +*/ + bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, MDL_ticket *ticket ) { + /* Fallback to the non-wsrep behaviour */ if (!WSREP_ON) return FALSE; THD *request_thd = requestor_ctx->get_thd(); diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 53684935f99..50e8a09706b 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -495,6 +495,17 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && 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_wsrep_abort_transaction(bf_thd, victim_thd, signal); From 41d40029875bfd7f4cd6a5255e05a3c93103220f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 21 Jun 2015 23:09:10 -0400 Subject: [PATCH 289/294] Remove duplicate script added due to bad merge. --- scripts/wsrep_sst_common.sh | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index e23afc94511..46f4076111f 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -124,32 +124,6 @@ else MY_PRINT_DEFAULTS=$(which my_print_defaults) fi -# try to use my_print_defaults, mysql and mysqldump that come with the sources -# (for MTR suite) -SCRIPTS_DIR="$(cd $(dirname "$0"); pwd -P)" -EXTRA_DIR="$SCRIPTS_DIR/../extra" -CLIENT_DIR="$SCRIPTS_DIR/../client" - -if [ -x "$CLIENT_DIR/mysql" ]; then - MYSQL_CLIENT="$CLIENT_DIR/mysql" -else - MYSQL_CLIENT=$(which mysql) -fi - -if [ -x "$CLIENT_DIR/mysqldump" ]; then - MYSQLDUMP="$CLIENT_DIR/mysqldump" -else - MYSQLDUMP=$(which mysqldump) -fi - -if [ -x "$SCRIPTS_DIR/my_print_defaults" ]; then - MY_PRINT_DEFAULTS="$SCRIPTS_DIR/my_print_defaults" -elif [ -x "$EXTRA_DIR/my_print_defaults" ]; then - MY_PRINT_DEFAULTS="$EXTRA_DIR/my_print_defaults" -else - MY_PRINT_DEFAULTS=$(which my_print_defaults) -fi - # For Bug:1200727 if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then From 71d1f35847a575239deff856590bf6f13afd74ed Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 23 Jun 2015 13:48:39 -0400 Subject: [PATCH 290/294] Update SELinux policy to allow UDP for multicast repl in galera. --- policy/selinux/README | 22 ++++++++++++---------- policy/selinux/mariadb-server.te | 28 ++++++++++++++++++---------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/policy/selinux/README b/policy/selinux/README index a8c11c71a0b..3f695dc27a3 100644 --- a/policy/selinux/README +++ b/policy/selinux/README @@ -1,18 +1,20 @@ Note: The included SELinux policy files can be used for MariaDB Galera cluster. However, since these policies had been tested for a limited set of scenarios, -it is highly recommended to run SELinux in "permissive" mode even with these -policies installed and report any denials on mariadb.org/jira. +it is highly recommended that you run mysqld in "permissive" mode even with +these policies installed and report any denials on mariadb.org/jira. How to generate and load the policy module of MariaDB Galera cluster ? + * Generate the SELinux policy module. + # cd /policy/selinux/ + # make -f /usr/share/selinux/devel/Makefile mariadb-server.pp -* Generate the SELinux policy module. - # cd /policy/selinux/ - # make -f /usr/share/selinux/devel/Makefile mariadb-server.pp + * Load the generated policy module. + # semodule -i /path/to/mariadb-server.pp -* Load the generated policy module. - # semodule -i /path/to/mariadb-server.pp - -* Lastly, run the following command to allow 4568. - # semanage port -a -t mysqld_port_t -p tcp 4568 + * Lastly, run the following command to allow tcp/4568 and udp/4567. + # semanage port -a -t mysqld_port_t -p tcp 4568 + # semanage port -a -t mysqld_port_t -p udp 4567 +How to run mysqld in permissve mode ? + # semanage permissive -a mysqld_t diff --git a/policy/selinux/mariadb-server.te b/policy/selinux/mariadb-server.te index 9c0319c83f5..34d79326b10 100644 --- a/policy/selinux/mariadb-server.te +++ b/policy/selinux/mariadb-server.te @@ -4,25 +4,25 @@ module mariadb-server 1.0; require { - type user_tmp_t; - type kerberos_port_t; + type user_tmp_t; + #type kerberos_master_port_t; type mysqld_safe_t; - type tmp_t; - type tmpfs_t; - type hostname_exec_t; + type tmp_t; + type tmpfs_t; + type hostname_exec_t; type ifconfig_exec_t; type sysctl_net_t; type proc_net_t; type port_t; type mysqld_t; type var_lib_t; - type rsync_exec_t; + type rsync_exec_t; type bin_t; type shell_exec_t; type anon_inodefs_t; type fixed_disk_device_t; class lnk_file read; - class process { getattr signull }; + class process { getattr signull }; class unix_stream_socket connectto; class capability { sys_resource sys_nice }; class tcp_socket { name_bind name_connect }; @@ -32,7 +32,10 @@ require { class dir { write search getattr add_name read remove_name open }; # MariaDB additions + type kerberos_port_t; type tram_port_t; + type mysqld_port_t; + class udp_socket name_bind; class process setpgid; class netlink_tcpdiag_socket { create nlmsg_read }; } @@ -56,8 +59,8 @@ allow mysqld_t tmpfs_t:file { write getattr read create unlink open }; allow mysqld_t fixed_disk_device_t:blk_file { read write open }; allow mysqld_t ifconfig_exec_t:file { read execute open execute_no_trans getattr }; -#This rule allows connecting on 4444 -allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; +#This rule allows connecting on 4444/4567/4568 +#allow mysqld_t kerberos_master_port_t:tcp_socket { name_bind name_connect }; allow mysqld_t mysqld_safe_t:dir { getattr search }; allow mysqld_t mysqld_safe_t:file { read open }; @@ -82,8 +85,13 @@ allow mysqld_t bin_t:file { getattr read execute open execute_no_trans ioctl }; # MariaDB additions allow mysqld_t self:process setpgid; -# This rule allows port 4567 +# This rule allows port tcp/4444 +allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; +# This rule allows port tcp/4567 (tram_port_t may not be available on +# older versions) allow mysqld_t tram_port_t:tcp_socket name_bind; +# This rule allows port udp/4567 (see README) +allow mysqld_t mysqld_port_t:udp_socket name_bind; # Rules related to XtraBackup allow mysqld_t self:netlink_tcpdiag_socket { create nlmsg_read }; From 0f4478105f5027ce589a0f08c6019d906d632029 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 24 Jun 2015 17:02:33 -0400 Subject: [PATCH 291/294] Add close-on-exec flag to open(), socket(), accept() & fopen(). --- configure.cmake | 1 + include/my_global.h | 6 ++++++ include/mysql/psi/mysql_socket.h | 24 +++++++++++++++++++++++- mysys/my_create.c | 2 +- mysys/my_fopen.c | 8 +++++--- mysys/my_open.c | 4 ++-- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/configure.cmake b/configure.cmake index a6b1d76e1ff..603a17e7177 100644 --- a/configure.cmake +++ b/configure.cmake @@ -315,6 +315,7 @@ ENDIF() # # Tests for functions # +CHECK_FUNCTION_EXISTS (accept4 HAVE_ACCEPT4) CHECK_FUNCTION_EXISTS (access HAVE_ACCESS) #CHECK_FUNCTION_EXISTS (aiowait HAVE_AIOWAIT) CHECK_FUNCTION_EXISTS (aio_read HAVE_AIO_READ) diff --git a/include/my_global.h b/include/my_global.h index e9a472e686e..b3deba3c565 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -609,6 +609,12 @@ typedef SOCKET_SIZE_TYPE size_socket; #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif /* additional file share flags for win32 */ #ifdef __WIN__ diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h index e1d56539f85..6f37e012f1f 100644 --- a/include/mysql/psi/mysql_socket.h +++ b/include/mysql/psi/mysql_socket.h @@ -553,7 +553,7 @@ inline_mysql_socket_socket int domain, int type, int protocol) { MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET; - mysql_socket.fd= socket(domain, type, protocol); + mysql_socket.fd= socket(domain, type | SOCK_CLOEXEC, protocol); #ifdef HAVE_PSI_SOCKET_INTERFACE if (likely(mysql_socket.fd != INVALID_SOCKET)) @@ -1013,6 +1013,8 @@ inline_mysql_socket_accept #endif MYSQL_SOCKET socket_listen, struct sockaddr *addr, socklen_t *addr_len) { + int flags; + MYSQL_SOCKET socket_accept= MYSQL_INVALID_SOCKET; socklen_t addr_length= (addr_len != NULL) ? *addr_len : 0; @@ -1026,7 +1028,17 @@ inline_mysql_socket_accept (&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line); /* Instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, &addr_length, + SOCK_CLOEXEC); +#else socket_accept.fd= accept(socket_listen.fd, addr, &addr_length); + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } +#endif /* Instrumentation end */ if (locker != NULL) @@ -1036,7 +1048,17 @@ inline_mysql_socket_accept #endif { /* Non instrumented code */ +#ifdef HAVE_ACCEPT4 + socket_accept.fd= accept4(socket_listen.fd, addr, &addr_length, + SOCK_CLOEXEC); +#else socket_accept.fd= accept(socket_listen.fd, addr, &addr_length); + flags= fcntl(socket_accept.fd, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(socket_accept.fd, F_SETFD, flags); + } +#endif } #ifdef HAVE_PSI_SOCKET_INTERFACE diff --git a/mysys/my_create.c b/mysys/my_create.c index 51de343d4a1..6a3bcd63557 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -43,7 +43,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, #if defined(_WIN32) fd= my_win_open(FileName, access_flags | O_CREAT); #else - fd= open((char *) FileName, access_flags | O_CREAT, + fd= open((char *) FileName, access_flags | O_CREAT | O_CLOEXEC, CreateFlags ? CreateFlags : my_umask); #endif diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index ede434f2c32..409f1bfc9dd 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -42,7 +42,7 @@ static void make_ftype(char * to,int flag); FILE *my_fopen(const char *filename, int flags, myf MyFlags) { FILE *fd; - char type[5]; + char type[10]; DBUG_ENTER("my_fopen"); DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %lu", filename, flags, MyFlags)); @@ -351,9 +351,11 @@ static void make_ftype(register char * to, register int flag) else *to++= 'r'; -#if FILE_BINARY /* If we have binary-files */ if (flag & FILE_BINARY) *to++='b'; -#endif + + if (O_CLOEXEC) + *to++= 'e'; + *to='\0'; } /* make_ftype */ diff --git a/mysys/my_open.c b/mysys/my_open.c index 5263ba4b5c8..b6d8f08bfc1 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -46,9 +46,9 @@ File my_open(const char *FileName, int Flags, myf MyFlags) #if defined(_WIN32) fd= my_win_open(FileName, Flags); #elif !defined(NO_OPEN_3) - fd = open(FileName, Flags, my_umask); /* Normal unix */ + fd = open(FileName, Flags | O_CLOEXEC, my_umask); /* Normal unix */ #else - fd = open((char *) FileName, Flags); + fd = open((char *) FileName, Flags | O_CLOEXEC); #endif fd= my_register_filename(fd, FileName, FILE_BY_OPEN, From 9f00950d2ad9be5533e66a5fa87a795a9574585f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 24 Jun 2015 23:25:22 -0400 Subject: [PATCH 292/294] MDEV-7631 : Invalid WSREP_SST rows appear in mysqld-bin.index file Try not to release 0 (STDIN_FILENO) file descriptor as it can incorrectly get reused by streams opened later. --- sql/mysqld.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c297367b1af..a2fe4ade42b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6278,7 +6278,14 @@ int mysqld_main(int argc, char **argv) (char*) "" : mysqld_unix_port), mysqld_port, MYSQL_COMPILATION_COMMENT); - fclose(stdin); + + // try to keep fd=0 busy + if (!freopen(IF_WIN("NUL","/dev/null"), "r", stdin)) + { + // fall back on failure + fclose(stdin); + } + #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) Service.SetRunning(); #endif From 5467b12dc3894c36eba092430a785806e0d008c9 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 24 Jun 2015 23:28:42 -0400 Subject: [PATCH 293/294] MDEV-7903 : xtrabackup SST failing with maria-10.0-galera Remove master-bin.state file on joiner node during SST. --- scripts/wsrep_sst_xtrabackup-v2.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 71e25f0d57c..d5916b81a53 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -785,6 +785,7 @@ then wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ rm $binlog_dir/*.index || true + rm $binlog_dir/*.state || true fi fi @@ -870,7 +871,7 @@ then mv $DATA/${BINLOG_FILENAME}.* $BINLOG_DIRNAME/ 2>/dev/null || true pushd $BINLOG_DIRNAME &>/dev/null - for bfiles in $(ls -1 ${BINLOG_FILENAME}.*);do + for bfiles in $(ls -1 ${BINLOG_FILENAME}.[0-9]*);do echo ${BINLOG_DIRNAME}/${bfiles} >> ${BINLOG_FILENAME}.index done popd &> /dev/null From 6771b818a38a72e89d318eb9f1f3a2b8a64f0d5f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 10 Jul 2015 19:06:42 -0400 Subject: [PATCH 294/294] MDEV-8383 : "GRANT role TO user" does not replicate Enable replication of GRANT/REVOKE ROLE commands across galera nodes. --- mysql-test/suite/galera/r/galera_roles.result | 156 ++++++++++++++++ mysql-test/suite/galera/t/galera_roles.test | 167 ++++++++++++++++++ sql/sql_parse.cc | 1 + 3 files changed, 324 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_roles.result create mode 100644 mysql-test/suite/galera/t/galera_roles.test diff --git a/mysql-test/suite/galera/r/galera_roles.result b/mysql-test/suite/galera/r/galera_roles.result new file mode 100644 index 00000000000..c0cdbc0e338 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_roles.result @@ -0,0 +1,156 @@ +# +# Testing CREATE/GRANT role +# + +# On node_1 +CREATE DATABASE test1; +CREATE TABLE test1.t1 (a int, b int); +CREATE TABLE test1.t2 (a int, b int); +INSERT INTO test1.t1 values (1,2),(3,4); +INSERT INTO test1.t2 values (5,6),(7,8); +CREATE PROCEDURE test1.pr1() SELECT "pr1"; +CREATE USER foo@localhost; +CREATE ROLE role1; +GRANT role1 TO foo@localhost; +GRANT RELOAD ON *.* TO role1; +GRANT SELECT ON mysql.* TO role1; +GRANT EXECUTE ON PROCEDURE test1.pr1 TO role1; +GRANT SELECT ON test1.t1 TO role1; +GRANT SELECT (a) ON test1.t2 TO role1; +# Open connections to the 2 nodes using 'foo' user. + +# Connect with foo_node_1 +SHOW GRANTS; +Grants for foo@localhost +GRANT role1 TO 'foo'@'localhost' +GRANT USAGE ON *.* TO 'foo'@'localhost' +FLUSH TABLES; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SHOW TABLES FROM test1; +ERROR 42000: Access denied for user 'foo'@'localhost' to database 'test1' +SET ROLE role1; +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option +localhost foo role1 N +localhost root role1 Y +SHOW TABLES FROM test1; +Tables_in_test1 +t1 +t2 +SELECT * FROM test1.t1; +a b +1 2 +3 4 +SELECT * FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SELECT a FROM test1.t2; +a +5 +7 +CALL test1.pr1(); +pr1 +pr1 + +# Connect with foo_node_2 +SHOW GRANTS; +Grants for foo@localhost +GRANT role1 TO 'foo'@'localhost' +GRANT USAGE ON *.* TO 'foo'@'localhost' +FLUSH TABLES; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SHOW TABLES FROM test1; +ERROR 42000: Access denied for user 'foo'@'localhost' to database 'test1' +SET ROLE role1; +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option + role1 Y +localhost foo role1 N +SHOW TABLES FROM test1; +Tables_in_test1 +t1 +t2 +SELECT * FROM test1.t1; +a b +1 2 +3 4 +SELECT * FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SELECT a FROM test1.t2; +a +5 +7 +CALL test1.pr1(); +pr1 +pr1 +# +# Testing REVOKE role +# +# +# Connect with node_1 +REVOKE EXECUTE ON PROCEDURE test1.pr1 FROM role1; + +# Connect with foo_node_1 +CALL test1.pr1(); +ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test1.pr1' + +# Connect with foo_node_2 +CALL test1.pr1(); +ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test1.pr1' +# +# Testing DROP role +# + +# Connect with node_1 +DROP ROLE role1; + +# Connect with foo_node_1 +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SELECT * FROM test1.t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +SELECT a FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SHOW GRANTS; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT CURRENT_ROLE(); +CURRENT_ROLE() +role1 + +# Connect with foo_node_2 +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SELECT * FROM test1.t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +SELECT a FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SHOW GRANTS; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT CURRENT_ROLE(); +CURRENT_ROLE() +role1 +# Connect with node_1 +DROP USER foo@localhost; +DROP DATABASE test1; +# End of test diff --git a/mysql-test/suite/galera/t/galera_roles.test b/mysql-test/suite/galera/t/galera_roles.test new file mode 100644 index 00000000000..f9a15126e5e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_roles.test @@ -0,0 +1,167 @@ +# +# Test for CREATE/DROP/GRANT/REVOKE role. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # Testing CREATE/GRANT role +--echo # + +--echo +--echo # On node_1 +--connection node_1 + +CREATE DATABASE test1; +CREATE TABLE test1.t1 (a int, b int); +CREATE TABLE test1.t2 (a int, b int); +INSERT INTO test1.t1 values (1,2),(3,4); +INSERT INTO test1.t2 values (5,6),(7,8); + +CREATE PROCEDURE test1.pr1() SELECT "pr1"; + +CREATE USER foo@localhost; +CREATE ROLE role1; + +GRANT role1 TO foo@localhost; +GRANT RELOAD ON *.* TO role1; +GRANT SELECT ON mysql.* TO role1; +GRANT EXECUTE ON PROCEDURE test1.pr1 TO role1; +GRANT SELECT ON test1.t1 TO role1; +GRANT SELECT (a) ON test1.t2 TO role1; + +--echo # Open connections to the 2 nodes using 'foo' user. +--let $port_1= \$NODE_MYPORT_1 +--connect(foo_node_1,127.0.0.1,foo,,test,$port_1,) + +--let $port_2= \$NODE_MYPORT_2 +--connect(foo_node_2,127.0.0.1,foo,,test,$port_2,) + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +SHOW GRANTS; + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_DBACCESS_DENIED_ERROR +SHOW TABLES FROM test1; + +SET ROLE role1; + +FLUSH TABLES; +--sorted_result +SELECT * FROM mysql.roles_mapping; +SHOW TABLES FROM test1; +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t2; +SELECT a FROM test1.t2; +CALL test1.pr1(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +SHOW GRANTS; + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_DBACCESS_DENIED_ERROR +SHOW TABLES FROM test1; + +SET ROLE role1; + +FLUSH TABLES; +--sorted_result +SELECT * FROM mysql.roles_mapping; +SHOW TABLES FROM test1; +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t2; +SELECT a FROM test1.t2; +CALL test1.pr1(); + +--echo # +--echo # Testing REVOKE role +--echo # + +--echo # +--echo # Connect with node_1 +--connection node_1 +REVOKE EXECUTE ON PROCEDURE test1.pr1 FROM role1; + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +--error ER_PROCACCESS_DENIED_ERROR +CALL test1.pr1(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +--error ER_PROCACCESS_DENIED_ERROR +CALL test1.pr1(); + +--echo # +--echo # Testing DROP role +--echo # + +--echo +--echo # Connect with node_1 +--connection node_1 + +DROP ROLE role1; + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT a FROM test1.t2; + +SHOW GRANTS; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; # yes, repeat it twice +SELECT CURRENT_ROLE(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT a FROM test1.t2; + +SHOW GRANTS; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; # yes, repeat it twice +SELECT CURRENT_ROLE(); + +# Cleanup +disconnect foo_node_2; +--echo # Connect with node_1 +--connection node_1 + +DROP USER foo@localhost; +DROP DATABASE test1; + +--source include/galera_end.inc +--echo # End of test diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c561cc73707..70602049604 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4626,6 +4626,7 @@ end_with_restore_list: case SQLCOM_REVOKE_ROLE: case SQLCOM_GRANT_ROLE: { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_grant_role(thd, lex->users_list, lex->sql_command != SQLCOM_GRANT_ROLE))) my_ok(thd);