From 5333dafa843477b5499a5e77a5bf942bc1ed7a18 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sun, 5 May 2013 21:39:31 +0300 Subject: [PATCH 01/10] Fixed errors and compiler warnings found by buildbot Solaris fixes: - Fixed that wait_timeout_func and wait_timeout tests works on solaris - We have to compile without NO_ALARM on Solaris as Solaris doesn't support timeouts on sockets with setsockopt(.. SO_RCVTIMEO). - Fixed that compile-solaris-amd64-debug works (before that we got a wrong ELF class: ELFCLASS64 on linkage) - Added missing sync_with_master Other bug fixes: - Free memory for rpl_global_gtid_binlog_state before exit() to avoid 'accessing uninitalized mutex' error. BUILD/FINISH.sh: Fixed issues on Solaris with ksh BUILD/compile-solaris-amd64-debug: Added missing -m64 flag configure.cmake: We have to compile without NO_ALARM on Solaris as Solaris doesn't support timeouts on sockets with setsockopt(.. SO_RCVTIMEO) mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test: - Added missing sync_with_master (fix by knielsen) sql-common/client.c: Added () to get rid of compiler warning sql/item_strfunc.cc: Fixed compiler warning sql/log.cc: Free memory for static variable rpl_global_gtid_binlog_state before exit() - If we are compiling with safemalloc, we would try to call sf_free() for some members after sf_terminate() was called, which would result of trying to access the uninitalized mutex 'sf_mutex' sql/multi_range_read.cc: Fixed compiler warnings of converting double to ulong. sql/opt_range.cc: Fixed compiler warnings of converting double to ulong or uint - Better to have all variables that can be number of rows as 'ha_rows' sql/rpl_gtid.cc: Added rpl_binlog_state::free() to be able to free memory for static objects before exit() sql/rpl_gtid.h: Added rpl_binlog_state::free() to be able to free memory for static objects before exit() sql/set_var.cc: Fixed compiler warning sql/sql_join_cache.cc: Fixed compiler warnings of converting double to uint sql/sql_show.cc: Added cast to get rid of compiler warning sql/sql_statistics.cc: Remove code that didn't do anything. (store_record() with record[0] is a no-op) storage/xtradb/os/os0file.c: Added __attribute__ ((unused)) support-files/compiler_warnings.supp: Ignore warnings from atomic_add_64_nv (was not able to fix this with a cast as the macro is a bit different between systems) vio/viosocket.c: Added more DBUG_PRINT --- BUILD/FINISH.sh | 3 +- BUILD/compile-solaris-amd64-debug | 2 +- configure.cmake | 3 ++ mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test | 1 + sql-common/client.c | 7 +++- sql/item_strfunc.cc | 5 ++- sql/log.cc | 8 +++- sql/multi_range_read.cc | 4 +- sql/opt_range.cc | 38 +++++++++---------- sql/rpl_gtid.cc | 16 ++++++-- sql/rpl_gtid.h | 2 + sql/set_var.cc | 2 +- sql/sql_join_cache.cc | 4 +- sql/sql_show.cc | 4 +- sql/sql_statistics.cc | 2 +- storage/xtradb/os/os0file.c | 3 +- support-files/compiler_warnings.supp | 3 +- vio/viosocket.c | 7 +++- 18 files changed, 73 insertions(+), 41 deletions(-) diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh index e29b6936849..86085fcc593 100644 --- a/BUILD/FINISH.sh +++ b/BUILD/FINISH.sh @@ -42,8 +42,7 @@ path=`dirname $0` if [ -z "$just_clean" ] then commands="$commands -CC=\"$CC\" CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" \ -$configure" +CC=\"$CC\" CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" $configure" fi if [ -z "$just_configure" -a -z "$just_clean" ] diff --git a/BUILD/compile-solaris-amd64-debug b/BUILD/compile-solaris-amd64-debug index 4d6d3f6fce4..770572bd1d7 100755 --- a/BUILD/compile-solaris-amd64-debug +++ b/BUILD/compile-solaris-amd64-debug @@ -20,7 +20,7 @@ path=`dirname $0` extra_flags="$amd64_cflags -D__sun -m64 -mtune=athlon64 $debug_cflags" extra_configs="$amd64_configs $debug_configs $max_configs --with-libevent" -LDFLAGS="-lmtmalloc -R/usr/sfw/lib/64" +LDFLAGS="-m64 -lmtmalloc -R/usr/sfw/lib/64" export LDFLAGS . "$path/FINISH.sh" diff --git a/configure.cmake b/configure.cmake index f98b42ec159..23fa3a7c5c2 100644 --- a/configure.cmake +++ b/configure.cmake @@ -951,12 +951,15 @@ CHECK_CXX_SOURCE_COMPILES(" # they are silently ignored. For those OS's we will not attempt # to use SO_SNDTIMEO and SO_RCVTIMEO even if it is said to work. # See Bug#29093 for the problem with SO_SND/RCVTIMEO on HP/UX. +# Solaris11 has a similar problem # To use alarm is simple, simply avoid setting anything. IF(WIN32) SET(HAVE_SOCKET_TIMEOUT 1) ELSEIF(CMAKE_SYSTEM MATCHES "HP-UX") SET(HAVE_SOCKET_TIMEOUT 0) +ELSEIF(CMAKE_SYSTEM_NAME MATCHES "SunOS") + SET(HAVE_SOCKET_TIMEOUT 0) ELSEIF(CMAKE_CROSSCOMPILING) SET(HAVE_SOCKET_TIMEOUT 0) ELSE() diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test index 549d11e9d1c..57f1975ed77 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test @@ -48,6 +48,7 @@ let $binlog_file=LAST; source include/show_binlog_events.inc; connection server_1; +--sync_with_master source include/stop_slave.inc; source include/wait_for_slave_to_stop.inc; reset slave all; diff --git a/sql-common/client.c b/sql-common/client.c index 507917b0722..a1904bae93a 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3420,8 +3420,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, strmov(mysql->server_version,(char*) net->read_pos+1); mysql->port=port; - /* remove the rpl hack from the version string, see RPL_VERSION_HACK comment */ - if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH && + /* + remove the rpl hack from the version string, see RPL_VERSION_HACK + comment + */ + if ((mysql->server_capabilities & CLIENT_PLUGIN_AUTH) && strncmp(mysql->server_version, RPL_VERSION_HACK, sizeof(RPL_VERSION_HACK) - 1) == 0) mysql->server_version+= sizeof(RPL_VERSION_HACK) - 1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1ee4a4436fe..15b1cedf346 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3866,7 +3866,10 @@ bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref) vals= (DYNAMIC_COLUMN_VALUE *) alloc_root(thd->mem_root, sizeof(DYNAMIC_COLUMN_VALUE) * (arg_count / 2)); - for (i= 0; i + 1 < arg_count && args[i]->result_type() == INT_RESULT; i+= 2); + for (i= 0; + i + 1 < arg_count && args[i]->result_type() == INT_RESULT; + i+= 2) + ; if (i + 1 < arg_count) { names= TRUE; diff --git a/sql/log.cc b/sql/log.cc index a4ec5583dc9..a96ec830b01 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -119,7 +119,6 @@ static MYSQL_BIN_LOG::xid_count_per_binlog * static bool start_binlog_background_thread(); - static rpl_binlog_state rpl_global_gtid_binlog_state; /** @@ -2994,6 +2993,13 @@ void MYSQL_BIN_LOG::cleanup() mysql_cond_destroy(&COND_binlog_background_thread); mysql_cond_destroy(&COND_binlog_background_thread_end); } + + /* + Free data for global binlog state. + We can't do that automaticly as we need to do this before + safemalloc is shut down + */ + rpl_global_gtid_binlog_state.free(); DBUG_VOID_RETURN; } diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index e3719600dff..ceb6b16ec7a 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -1199,9 +1199,9 @@ bool DsMrr_impl::setup_buffer_sharing(uint key_size_in_keybuf, statistics? */ uint parts= my_count_bits(key_tuple_map); - ulong rpc; + ha_rows rpc; ulonglong rowids_size= rowid_buf_elem_size; - if ((rpc= key_info->actual_rec_per_key(parts - 1))) + if ((rpc= (ha_rows) key_info->actual_rec_per_key(parts - 1))) rowids_size= rowid_buf_elem_size * rpc; double fraction_for_rowids= diff --git a/sql/opt_range.cc b/sql/opt_range.cc index b736f898768..85c9c9fd394 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5919,8 +5919,8 @@ ha_rows records_in_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, ha_rows ext_records= ext_index_scan->records; if (i < used_key_parts) { - ulong f1= key_info->actual_rec_per_key(i-1); - ulong f2= key_info->actual_rec_per_key(i); + double f1= key_info->actual_rec_per_key(i-1); + double f2= key_info->actual_rec_per_key(i); ext_records= (ha_rows) ((double) ext_records / f2 * f1); } if (ext_records < table_cardinality) @@ -13157,11 +13157,11 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, double *read_cost, ha_rows *records) { ha_rows table_records; - uint num_groups; - uint num_blocks; - uint keys_per_block; - uint keys_per_group; - uint keys_per_subgroup; /* Average number of keys in sub-groups */ + ha_rows num_groups; + ha_rows num_blocks; + uint keys_per_block; + ha_rows keys_per_group; + ha_rows keys_per_subgroup; /* Average number of keys in sub-groups */ /* formed by a key infix. */ double p_overlap; /* Probability that a sub-group overlaps two blocks. */ double quick_prefix_selectivity; @@ -13170,24 +13170,24 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, DBUG_ENTER("cost_group_min_max"); table_records= table->stat_records(); - keys_per_block= (table->file->stats.block_size / 2 / - (index_info->key_length + table->file->ref_length) - + 1); - num_blocks= (uint)(table_records / keys_per_block) + 1; + keys_per_block= (uint) (table->file->stats.block_size / 2 / + (index_info->key_length + table->file->ref_length) + + 1); + num_blocks= (ha_rows)(table_records / keys_per_block) + 1; /* Compute the number of keys in a group. */ - keys_per_group= index_info->actual_rec_per_key(group_key_parts - 1); + keys_per_group= (ha_rows) index_info->actual_rec_per_key(group_key_parts - 1); if (keys_per_group == 0) /* If there is no statistics try to guess */ /* each group contains 10% of all records */ - keys_per_group= (uint)(table_records / 10) + 1; - num_groups= (uint)(table_records / keys_per_group) + 1; + keys_per_group= (table_records / 10) + 1; + num_groups= (table_records / keys_per_group) + 1; /* Apply the selectivity of the quick select for group prefixes. */ if (range_tree && (quick_prefix_records != HA_POS_ERROR)) { quick_prefix_selectivity= (double) quick_prefix_records / (double) table_records; - num_groups= (uint) rint(num_groups * quick_prefix_selectivity); + num_groups= (ha_rows) rint(num_groups * quick_prefix_selectivity); set_if_bigger(num_groups, 1); } @@ -13196,7 +13196,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, Compute the probability that two ends of a subgroup are inside different blocks. */ - keys_per_subgroup= index_info->actual_rec_per_key(used_key_parts - 1); + keys_per_subgroup= (ha_rows) index_info->actual_rec_per_key(used_key_parts - 1); if (keys_per_subgroup >= keys_per_block) /* If a subgroup is bigger than */ p_overlap= 1.0; /* a block, it will overlap at least two blocks. */ else @@ -13224,9 +13224,9 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, *records= num_groups; DBUG_PRINT("info", - ("table rows: %lu keys/block: %u keys/group: %u result rows: %lu blocks: %u", - (ulong)table_records, keys_per_block, keys_per_group, - (ulong) *records, num_blocks)); + ("table rows: %lu keys/block: %u keys/group: %lu result rows: %lu blocks: %lu", + (ulong)table_records, keys_per_block, (ulong) keys_per_group, + (ulong) *records, (ulong) num_blocks)); DBUG_VOID_RETURN; } diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index d6a6ed90bd3..bda060115ed 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -686,6 +686,7 @@ rpl_binlog_state::rpl_binlog_state() sizeof(uint32), NULL, my_free, HASH_UNIQUE); mysql_mutex_init(key_LOCK_binlog_state, &LOCK_binlog_state, MY_MUTEX_INIT_SLOW); + initialized= 1; } @@ -699,11 +700,20 @@ rpl_binlog_state::reset() my_hash_reset(&hash); } +void rpl_binlog_state::free() +{ + if (initialized) + { + initialized= 0; + reset(); + my_hash_free(&hash); + mysql_mutex_destroy(&LOCK_binlog_state); + } +} + rpl_binlog_state::~rpl_binlog_state() { - reset(); - my_hash_free(&hash); - mysql_mutex_destroy(&LOCK_binlog_state); + free(); } diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index e63d8439803..046533fd760 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -135,11 +135,13 @@ struct rpl_binlog_state HASH hash; /* Mutex protecting access to the state. */ mysql_mutex_t LOCK_binlog_state; + my_bool initialized; rpl_binlog_state(); ~rpl_binlog_state(); void reset(); + void free(); int update(const struct rpl_gtid *gtid); uint64 seq_no_from_state(); int write_to_iocache(IO_CACHE *dest); diff --git a/sql/set_var.cc b/sql/set_var.cc index 48f7cc7a054..97545778f18 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -315,7 +315,7 @@ longlong sys_var::val_int(bool *is_null, { case_get_string_as_lex_string; case_for_integers(return val); - case_for_double(return val); + case_for_double(return (longlong) val); default: my_error(ER_VAR_CANT_BE_READ, MYF(0), name.str); return 0; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 6b0882bda80..9fca8730cb5 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -3812,8 +3812,8 @@ uint JOIN_TAB_SCAN_MRR::aux_buffer_incr(ulong recno) uint incr= 0; TABLE_REF *ref= &join_tab->ref; TABLE *tab= join_tab->table; - uint rec_per_key= - tab->key_info[ref->key].actual_rec_per_key(ref->key_parts-1); + ha_rows rec_per_key= + (ha_rows) tab->key_info[ref->key].actual_rec_per_key(ref->key_parts-1); set_if_bigger(rec_per_key, 1); if (recno == 1) incr= ref->key_length + tab->file->ref_length; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 46cc157061d..b448e5a64b9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5977,8 +5977,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, KEY *key=show_table->key_info+i; if (key->rec_per_key[j]) { - ha_rows records=((double) show_table->stat_records() / - key->actual_rec_per_key(j)); + ha_rows records= (ha_rows) ((double) show_table->stat_records() / + key->actual_rec_per_key(j)); table->field[9]->store((longlong) records, TRUE); table->field[9]->set_notnull(); } diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index f355f2c7760..2e2886a1d3f 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -337,7 +337,7 @@ protected: void store_record_for_lookup() { - store_record(stat_table, record[0]); + DBUG_ASSERT(record[0] == stat_table->record[0]); } bool update_record() diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index 8f7f8216782..1724e39d342 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -1475,7 +1475,8 @@ static int os_file_set_atomic_writes(os_file_t file, const char *name) return ret; } #else -static int os_file_set_atomic_writes(os_file_t file, const char *name) +static int os_file_set_atomic_writes(os_file_t file __attribute__ ((unused)), + const char *name) { fprintf(stderr, "InnoDB : can't use atomic writes on %s - not implemented on this platform." diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 34f368c4373..7454eacfb34 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -48,7 +48,8 @@ btr/btr0cur\.c: .*value computed is not used.*: 3175-3375 btr/btr0sea\.c: passing argument 2 .* discards qualifiers from pointer target type ibuf/ibuf0ibuf.c: null argument where non-null required: 700-1000 fsp0fsp\.c: result of 32-bit shift implicitly converted to 64 bits - +log/log0log\.c : passing arg 1 of `atomic_add_64_nv' from incompatible pointer type +log/log0online.c : passing arg 1 of `atomic_add_64_nv' from incompatible pointer type # # bdb is not critical to keep up to date # diff --git a/vio/viosocket.c b/vio/viosocket.c index baefa1c6d06..960b49276a8 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -322,7 +322,9 @@ int vio_fastsend(Vio * vio __attribute__((unused))) } if (r) { - DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); + DBUG_PRINT("warning", + ("Couldn't set socket option for fast send, error %d", + socket_errno)); r= -1; } DBUG_PRINT("exit", ("%d", r)); @@ -819,7 +821,7 @@ void vio_timeout(Vio *vio, uint which, uint timeout) #if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) int r; DBUG_ENTER("vio_timeout"); - + DBUG_PRINT("enter", ("which: %u timeout: %u", which, timeout)); { #ifdef __WIN__ /* Windows expects time in milliseconds as int */ @@ -846,6 +848,7 @@ void vio_timeout(Vio *vio, uint which, uint timeout) Platforms not suporting setting of socket timeout should either use thr_alarm or just run without read/write timeout(s) */ + DBUG_PRINT("warning", ("timeout ignored")); #endif /* Make timeout values available for async operations. */ if (which) From e5a0daae5a95b3fa116d71f65dfaf85cbbb1ca7d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 May 2013 14:35:34 +0200 Subject: [PATCH 02/10] Fix big problem in previous push. (Relay log cleanup would nuke binlog state) --- sql/log.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/log.cc b/sql/log.cc index a96ec830b01..c0cd4be8a45 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2999,7 +2999,8 @@ void MYSQL_BIN_LOG::cleanup() We can't do that automaticly as we need to do this before safemalloc is shut down */ - rpl_global_gtid_binlog_state.free(); + if (!is_relay_log) + rpl_global_gtid_binlog_state.free(); DBUG_VOID_RETURN; } From 53d44ad18b83dd59481ddaa71dcf8dc9e3446b83 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 10 May 2013 12:32:34 +0300 Subject: [PATCH 03/10] Added some fixes that should make MyISAM & Aria REPAIR work with more than 4G records - If one specifies --force twice to myisamchk and aria_chk, then we will try to finnish the repair even if sort_buffer would be too small. This was done by dynamically allocate buffer handler objects as long as memory lasts. - New option for myisamchk and aria_chk: create-missing-keys - Changed default size of myisam_sort_buffer_size from 8M to 128M. - Changed default size of sort_buffer_size in aria_chk from 128M to 256M. - Increased information in error message about 'sort_buffer_size' beeing to small. - Print also to 'show warnings' if repair was retried. - Increased size of internal sort-buffer-readers from 16K to 128K - Changed printing of 'number of records' to use %ll instead of casting to long - Changed buffer sizes for myisam and aria to use MY_ALIGN_DOWN() to get same number of bytes allocated on different machines. include/my_global.h: Added MY_ALIGN_DOWN() to get previous alignment (for big memory areas) include/myisam.h: Increased size of types to be able to handle more records include/myisamchk.h: Increased size of types to be able to handle more records Added T_FORCE_SORT_MEMORY to force repair to work even if sort_buffer would not be big enough mysql-test/r/myisam.result: Updated result mysql-test/r/mysqld--help.result: Updated result mysql-test/r/repair.result: Updated result mysql-test/suite/maria/maria.result: Added test cases for some fixed bugs in MyISAM to verify that Aria doesn't have them too. mysql-test/suite/maria/maria.test: Added test cases for some fixed bugs in MyISAM to verify that Aria doesn't have them too. mysql-test/suite/maria/maria3.result: Updated result after sort buffer size increase mysql-test/suite/sys_vars/r/aria_sort_buffer_size_basic.result: Updated result after sort buffer size increase mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic.result: Updated result after sort buffer size increase mysql-test/suite/sys_vars/t/myisam_sort_buffer_size_basic.test: Updated result after sort buffer size increase mysql-test/t/myisam.test: Fixed error messages to not print system specific data mysql-test/t/repair.test: Fixed error messages to not print system specific data storage/maria/ha_maria.cc: Print also to 'show warnings' if repair was retried Changed default size of sort_buffer_size from 128M to 256M (same as in mysqld) storage/maria/ma_check.c: Renamed USE_BUFFER_INIT -> PAGE_BUFFER_INIT storage/maria/ma_sort.c: Increased size of internal sort-buffer-readers from 16K to 128K Increased size of types to be able to handle more records Added support for T_FORCE_SORT_MEMORY Don't allocate too many extra BUFFPEK at a time (they are probably not needed) Improved error message for "sort_buffer_size is too small" Changed printing of 'number of records' to use %ll instead of casting to long Fixed bug where maria_update_key_parts() was called too early. Fixed bug in detecting result from read_to_buffer(). Added 'out of memory' checking when calling 'alloc_dynamic()'. storage/maria/maria_chk.c: Added --create-missing-keys If one specifies --force twice then we will try to finnish the repair even if sort_buffer would be too small. check_param.sort_buffer_length varialble was used with wrong type. storage/maria/maria_def.h: Increased size of types to be able to handle more records Use MY_ALIGN_DOWN() to get same number of bytes allocated on different machines Renamed USE_BUFFER_INIT -> PAGE_BUFFER_INIT storage/maria/maria_ftdump.c: Renamed USE_BUFFER_INIT -> PAGE_BUFFER_INIT storage/maria/maria_read_log.c: Use PAGE_BUFFER_INIT for page cache storage/myisam/ha_myisam.cc: Changed default size of myisam_sort_buffer_size from 8M to 128M storage/myisam/mi_check.c: Renamed USE_BUFFER_INIT -> KEY_BUFFER_INIT storage/myisam/myisam_ftdump.c: Renamed USE_BUFFER_INIT -> KEY_BUFFER_INIT storage/myisam/myisamchk.c: Added --create-missing-keys If one specifies --force twice then we will try to finnish the repair even if sort_buffer would be too small. check_param.sort_buffer_length varialble was used with wrong type. Renamed USE_BUFFER_INIT -> KEY_BUFFER_INIT storage/myisam/myisamdef.h: Increased SORT_BUFFER_INIT to 64M (speeds up repair a lot and most machines have nowadays a lot of memory) Use MY_ALIGN_DOWN() to get same number of bytes allocated on different machines Renamed USE_BUFFER_INIT -> KEY_BUFFER_INIT storage/myisam/sort.c: Increased size of internal sort-buffer-readers from 16K to 128K Increased size of types to be able to handle more records Added support for T_FORCE_SORT_MEMORY Don't allocate too many extra BUFFPEK at a time (they are probably not needed) Improved error message for "sort_buffer_size is too small" Changed printing of 'number of records' to use %ll instead of casting to long Fixed bug in detecting result from read_to_buffer(). Added 'out of memory' checking when calling 'alloc_dynamic()'. --- include/my_global.h | 3 +- include/myisam.h | 12 +- include/myisamchk.h | 11 +- mysql-test/r/myisam.result | 4 +- mysql-test/r/mysqld--help.result | 2 +- mysql-test/r/repair.result | 4 +- mysql-test/suite/maria/maria.result | 62 ++++ mysql-test/suite/maria/maria.test | 46 +++ mysql-test/suite/maria/maria3.result | 2 +- .../r/aria_sort_buffer_size_basic.result | 22 +- .../r/myisam_sort_buffer_size_basic.result | 20 +- .../t/myisam_sort_buffer_size_basic.test | 4 +- mysql-test/t/myisam.test | 2 + mysql-test/t/repair.test | 2 + storage/maria/ha_maria.cc | 8 +- storage/maria/ma_check.c | 2 +- storage/maria/ma_sort.c | 344 +++++++++++------- storage/maria/maria_chk.c | 51 ++- storage/maria/maria_def.h | 18 +- storage/maria/maria_ftdump.c | 2 +- storage/maria/maria_read_log.c | 8 +- storage/myisam/ha_myisam.cc | 2 +- storage/myisam/mi_check.c | 2 +- storage/myisam/myisam_ftdump.c | 2 +- storage/myisam/myisamchk.c | 44 ++- storage/myisam/myisamdef.h | 9 +- storage/myisam/sort.c | 289 +++++++++------ 27 files changed, 651 insertions(+), 326 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 30e8909ed13..1b59e1b1a36 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -847,7 +847,8 @@ typedef long my_ptrdiff_t; typedef long long my_ptrdiff_t; #endif -#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1)) +#define MY_ALIGN_DOWN(A,L) ((A) & ~((L) - 1)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) #define ALIGN_MAX_UNIT (sizeof(double)) /* Size to make adressable obj. */ diff --git a/include/myisam.h b/include/myisam.h index d5484b1eac6..b3b953b6e99 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -356,8 +356,10 @@ typedef struct st_mi_sort_param ulonglong notnull[HA_MAX_KEY_SEG+1]; my_off_t pos,max_pos,filepos,start_recpos; - uint key, key_length,real_key_length,sortbuff_size; - uint maxbuffers, keys, find_length, sort_keys_length; + uint key, key_length,real_key_length; + uint maxbuffers, find_length; + ulonglong sortbuff_size; + ha_rows keys; my_bool fix_datafile, master; my_bool calc_checksum; /* calculate table checksum */ @@ -366,10 +368,10 @@ typedef struct st_mi_sort_param int (*key_write)(struct st_mi_sort_param *, const void *); void (*lock_in_memory)(HA_CHECK *); int (*write_keys)(struct st_mi_sort_param *, register uchar **, - uint , struct st_buffpek *, IO_CACHE *); - uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + ulonglong , struct st_buffpek *, IO_CACHE *); + my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, - uint, uint); + uint, ulonglong); } MI_SORT_PARAM; /* functions in mi_check */ diff --git a/include/myisamchk.h b/include/myisamchk.h index c079b7d290b..152467db547 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -62,9 +62,10 @@ #define T_ZEROFILL ((ulonglong) 1L << 32) #define T_ZEROFILL_KEEP_LSN ((ulonglong) 1L << 33) /** If repair should not bump create_rename_lsn */ -#define T_NO_CREATE_RENAME_LSN ((ulonglong) 1L << 33) -#define T_CREATE_UNIQUE_BY_SORT ((ulonglong) 1L << 34) -#define T_SUPPRESS_ERR_HANDLING ((ulonglong) 1L << 35) +#define T_NO_CREATE_RENAME_LSN ((ulonglong) 1L << 34) +#define T_CREATE_UNIQUE_BY_SORT ((ulonglong) 1L << 35) +#define T_SUPPRESS_ERR_HANDLING ((ulonglong) 1L << 36) +#define T_FORCE_SORT_MEMORY ((ulonglong) 1L << 37) #define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL) @@ -180,8 +181,8 @@ typedef struct st_buffpek { my_off_t file_pos; /* Where we are in the sort file */ uchar *base, *key; /* Key pointers */ ha_rows count; /* Number of rows in table */ - ulong mem_count; /* numbers of keys in memory */ - ulong max_keys; /* Max keys in buffert */ + ha_rows mem_count; /* Numbers of keys in memory */ + ha_rows max_keys; /* Max keys in buffert */ } BUFFPEK; #endif /* _myisamchk_h */ diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 2530182ea67..267110be487 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2355,7 +2355,7 @@ Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' REPAIR TABLE t1; Table Op Msg_type Msg_text -test.t1 repair error myisam_sort_buffer_size is too small +test.t1 repair error myisam_sort_buffer_size is too small. X test.t1 repair warning Number of rows changed from 0 to 7168 test.t1 repair status OK SET myisam_repair_threads=2; @@ -2424,7 +2424,7 @@ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'); Warnings: -Error 1034 myisam_sort_buffer_size is too small +Error 1034 myisam_sort_buffer_size is too small. X Error 1034 Number of rows changed from 0 to 157 SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; INSERT INTO t1 VALUES('1'); diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index dfd6998b9f3..70b93e7025f 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1045,7 +1045,7 @@ myisam-max-sort-file-size 9223372036853727232 myisam-mmap-size 18446744073709551615 myisam-recover-options DEFAULT myisam-repair-threads 1 -myisam-sort-buffer-size 8388608 +myisam-sort-buffer-size 134216704 myisam-stats-method nulls_unequal myisam-use-mmap FALSE net-buffer-length 16384 diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 1a98f2f0f36..241c32b4b40 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -77,12 +77,12 @@ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'); Warnings: -Error 1034 myisam_sort_buffer_size is too small +Error 1034 myisam_sort_buffer_size is too small. X Error 1034 Number of rows changed from 0 to 157 SET myisam_repair_threads=2; REPAIR TABLE t1; Table Op Msg_type Msg_text -test.t1 repair error myisam_sort_buffer_size is too small +test.t1 repair error myisam_sort_buffer_size is too small. X test.t1 repair warning Number of rows changed from 0 to 157 test.t1 repair status OK SET myisam_repair_threads=@@global.myisam_repair_threads; diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index ddd0adade57..914c9568ea4 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -2679,3 +2679,65 @@ select count(*) from t1; count(*) 13 drop table t1; +# +# BUG#47444 - --myisam_repair_threads > 1 can result in all index +# cardinalities=1 +# +SET aria_repair_threads=2; +SET aria_sort_buffer_size=8192; +CREATE TABLE t1(a CHAR(255), KEY(a), KEY(a), KEY(a)); +INSERT INTO t1 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(0),(1),(2),(3); +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +CARDINALITY +14 +14 +14 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +SET aria_sort_buffer_size=@@global.aria_sort_buffer_size; +SET aria_repair_threads=@@global.aria_repair_threads; +# +# BUG#47073 - valgrind errs, corruption,failed repair of partition, +# low myisam_sort_buffer_size +# +CREATE TABLE t1(a INT, b CHAR(10), KEY(a), KEY(b)); +INSERT INTO t1 VALUES(1,'0'),(2,'0'),(3,'0'),(4,'0'),(5,'0'), +(6,'0'),(7,'0'); +INSERT INTO t1 SELECT a+10,b FROM t1; +INSERT INTO t1 SELECT a+20,b FROM t1; +INSERT INTO t1 SELECT a+40,b FROM t1; +INSERT INTO t1 SELECT a+80,b FROM t1; +INSERT INTO t1 SELECT a+160,b FROM t1; +INSERT INTO t1 SELECT a+320,b FROM t1; +INSERT INTO t1 SELECT a+640,b FROM t1; +INSERT INTO t1 SELECT a+1280,b FROM t1; +INSERT INTO t1 SELECT a+2560,b FROM t1; +INSERT INTO t1 SELECT a+5120,b FROM t1; +SET aria_sort_buffer_size=4096; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair error aria_sort_buffer_size is too small. X +test.t1 repair error Create index by sort failed +test.t1 repair info Retrying repair with keycache +test.t1 repair status OK +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SET aria_repair_threads=2; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair error aria_sort_buffer_size is too small. X +test.t1 repair error Create index by sort failed +test.t1 repair info Retrying repair with keycache +test.t1 repair status OK +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SET aria_repair_threads=@@global.aria_repair_threads; +SET aria_sort_buffer_size=@@global.aria_sort_buffer_size; +DROP TABLE t1; diff --git a/mysql-test/suite/maria/maria.test b/mysql-test/suite/maria/maria.test index 3fa7d755fe4..7ecf1e33061 100644 --- a/mysql-test/suite/maria/maria.test +++ b/mysql-test/suite/maria/maria.test @@ -1963,6 +1963,52 @@ unlock tables; select count(*) from t1; drop table t1; +--echo # +--echo # BUG#47444 - --myisam_repair_threads > 1 can result in all index +--echo # cardinalities=1 +--echo # +SET aria_repair_threads=2; +SET aria_sort_buffer_size=8192; +CREATE TABLE t1(a CHAR(255), KEY(a), KEY(a), KEY(a)); +INSERT INTO t1 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(0),(1),(2),(3); +--replace_regex /Current aria_sort_buffer_size.*/X/ +REPAIR TABLE t1; +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; +CHECK TABLE t1; +DROP TABLE t1; +SET aria_sort_buffer_size=@@global.aria_sort_buffer_size; +SET aria_repair_threads=@@global.aria_repair_threads; + +--echo # +--echo # BUG#47073 - valgrind errs, corruption,failed repair of partition, +--echo # low myisam_sort_buffer_size +--echo # +CREATE TABLE t1(a INT, b CHAR(10), KEY(a), KEY(b)); +INSERT INTO t1 VALUES(1,'0'),(2,'0'),(3,'0'),(4,'0'),(5,'0'), + (6,'0'),(7,'0'); +INSERT INTO t1 SELECT a+10,b FROM t1; +INSERT INTO t1 SELECT a+20,b FROM t1; +INSERT INTO t1 SELECT a+40,b FROM t1; +INSERT INTO t1 SELECT a+80,b FROM t1; +INSERT INTO t1 SELECT a+160,b FROM t1; +INSERT INTO t1 SELECT a+320,b FROM t1; +INSERT INTO t1 SELECT a+640,b FROM t1; +INSERT INTO t1 SELECT a+1280,b FROM t1; +INSERT INTO t1 SELECT a+2560,b FROM t1; +INSERT INTO t1 SELECT a+5120,b FROM t1; +SET aria_sort_buffer_size=4096; +--replace_regex /Current aria_sort_buffer_size.*/X/ +REPAIR TABLE t1; +CHECK TABLE t1; +SET aria_repair_threads=2; +# May report different values depending on threads activity. +--replace_regex /Current aria_sort_buffer_size.*/X/ +REPAIR TABLE t1; +CHECK TABLE t1; +SET aria_repair_threads=@@global.aria_repair_threads; +SET aria_sort_buffer_size=@@global.aria_sort_buffer_size; +DROP TABLE t1; + # # End of test # diff --git a/mysql-test/suite/maria/maria3.result b/mysql-test/suite/maria/maria3.result index b502d71e772..189329fe5c8 100644 --- a/mysql-test/suite/maria/maria3.result +++ b/mysql-test/suite/maria/maria3.result @@ -317,7 +317,7 @@ aria_pagecache_division_limit 100 aria_page_checksum OFF aria_recover NORMAL aria_repair_threads 1 -aria_sort_buffer_size 134217728 +aria_sort_buffer_size 268434432 aria_stats_method nulls_unequal aria_sync_log_dir NEWFILE show status like 'aria%'; diff --git a/mysql-test/suite/sys_vars/r/aria_sort_buffer_size_basic.result b/mysql-test/suite/sys_vars/r/aria_sort_buffer_size_basic.result index cf067c7e7b6..56522566ec9 100644 --- a/mysql-test/suite/sys_vars/r/aria_sort_buffer_size_basic.result +++ b/mysql-test/suite/sys_vars/r/aria_sort_buffer_size_basic.result @@ -1,30 +1,34 @@ SET @start_global_value = @@global.aria_sort_buffer_size; select @@global.aria_sort_buffer_size; @@global.aria_sort_buffer_size -134217728 +268434432 select @@session.aria_sort_buffer_size; @@session.aria_sort_buffer_size -134217728 +268434432 show global variables like 'aria_sort_buffer_size'; Variable_name Value -aria_sort_buffer_size 134217728 +aria_sort_buffer_size 268434432 show session variables like 'aria_sort_buffer_size'; Variable_name Value -aria_sort_buffer_size 134217728 +aria_sort_buffer_size 268434432 select * from information_schema.global_variables where variable_name='aria_sort_buffer_size'; VARIABLE_NAME VARIABLE_VALUE -ARIA_SORT_BUFFER_SIZE 134217728 +ARIA_SORT_BUFFER_SIZE 268434432 select * from information_schema.session_variables where variable_name='aria_sort_buffer_size'; VARIABLE_NAME VARIABLE_VALUE -ARIA_SORT_BUFFER_SIZE 134217728 +ARIA_SORT_BUFFER_SIZE 268434432 set global aria_sort_buffer_size=10; +Warnings: +Warning 1292 Truncated incorrect aria_sort_buffer_size value: '10' select @@global.aria_sort_buffer_size; @@global.aria_sort_buffer_size -10 +4096 set session aria_sort_buffer_size=10; +Warnings: +Warning 1292 Truncated incorrect aria_sort_buffer_size value: '10' select @@session.aria_sort_buffer_size; @@session.aria_sort_buffer_size -10 +4096 set global aria_sort_buffer_size=1.1; ERROR 42000: Incorrect argument type to variable 'aria_sort_buffer_size' set session aria_sort_buffer_size=1e1; @@ -36,7 +40,7 @@ Warnings: Warning 1292 Truncated incorrect aria_sort_buffer_size value: '0' select @@global.aria_sort_buffer_size; @@global.aria_sort_buffer_size -4 +4096 set session aria_sort_buffer_size=cast(-1 as unsigned int); select @@session.aria_sort_buffer_size; @@session.aria_sort_buffer_size diff --git a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic.result b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic.result index 85482be9ad4..932d06668fb 100644 --- a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic.result +++ b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic.result @@ -1,11 +1,11 @@ SET @start_global_value = @@global.myisam_sort_buffer_size ; SELECT @start_global_value; @start_global_value -8388608 +134216704 SET @start_session_value = @@session.myisam_sort_buffer_size ; SELECT @start_session_value; @start_session_value -8388608 +134216704 '#--------------------FN_DYNVARS_005_01-------------------------#' SET @@global.myisam_sort_buffer_size = 100; Warnings: @@ -13,22 +13,22 @@ Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100' SET @@global.myisam_sort_buffer_size = DEFAULT; SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -8388608 +134216704 SET @@session.myisam_sort_buffer_size = 200; Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '200' SET @@session.myisam_sort_buffer_size = DEFAULT; SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -8388608 +134216704 '#--------------------FN_DYNVARS_005_02-------------------------#' SET @@global.myisam_sort_buffer_size = DEFAULT; -SELECT @@global.myisam_sort_buffer_size = 8388608; -@@global.myisam_sort_buffer_size = 8388608 +SELECT @@global.myisam_sort_buffer_size = 134216704; +@@global.myisam_sort_buffer_size = 134216704 1 SET @@session.myisam_sort_buffer_size = DEFAULT; -SELECT @@session.myisam_sort_buffer_size = 8388608; -@@session.myisam_sort_buffer_size = 8388608 +SELECT @@session.myisam_sort_buffer_size = 134216704; +@@session.myisam_sort_buffer_size = 134216704 1 '#--------------------FN_DYNVARS_005_03-------------------------#' SET @@global.myisam_sort_buffer_size = 4; @@ -187,8 +187,8 @@ ERROR 42S22: Unknown column 'myisam_sort_buffer_size' in 'field list' SET @@global.myisam_sort_buffer_size = @start_global_value; SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -8388608 +134216704 SET @@session.myisam_sort_buffer_size = @start_session_value; SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -8388608 +134216704 diff --git a/mysql-test/suite/sys_vars/t/myisam_sort_buffer_size_basic.test b/mysql-test/suite/sys_vars/t/myisam_sort_buffer_size_basic.test index c35949ac5f3..1aa25fa2c8e 100644 --- a/mysql-test/suite/sys_vars/t/myisam_sort_buffer_size_basic.test +++ b/mysql-test/suite/sys_vars/t/myisam_sort_buffer_size_basic.test @@ -60,10 +60,10 @@ SELECT @@session.myisam_sort_buffer_size ; ######################################################################## SET @@global.myisam_sort_buffer_size = DEFAULT; -SELECT @@global.myisam_sort_buffer_size = 8388608; +SELECT @@global.myisam_sort_buffer_size = 134216704; SET @@session.myisam_sort_buffer_size = DEFAULT; -SELECT @@session.myisam_sort_buffer_size = 8388608; +SELECT @@session.myisam_sort_buffer_size = 134216704; --echo '#--------------------FN_DYNVARS_005_03-------------------------#' diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 8323890b028..6c9371eed25 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1600,6 +1600,7 @@ INSERT INTO t1 SELECT a+1280,b FROM t1; INSERT INTO t1 SELECT a+2560,b FROM t1; INSERT INTO t1 SELECT a+5120,b FROM t1; SET myisam_sort_buffer_size=4; +--replace_regex /Current myisam_sort_buffer_size.*/X/ REPAIR TABLE t1; SET myisam_repair_threads=2; @@ -1648,6 +1649,7 @@ DROP TABLE t1, t2, t3; CREATE TABLE t1(a CHAR(255), KEY(a)); SELECT * FROM t1, t1 AS a1; SET myisam_sort_buffer_size=4; +--replace_regex /Current myisam_sort_buffer_size.*/X/ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 3c55f06ff4c..6536c052019 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -61,6 +61,7 @@ DROP TABLE t1; # CREATE TABLE t1(a CHAR(255), KEY(a)); SET myisam_sort_buffer_size=4096; +--replace_regex /Current myisam_sort_buffer_size.*/X/ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), @@ -79,6 +80,7 @@ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'); SET myisam_repair_threads=2; +--replace_regex /Current myisam_sort_buffer_size.*/X/ REPAIR TABLE t1; SET myisam_repair_threads=@@global.myisam_repair_threads; SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 1a11bdd6050..6561bec5f22 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -260,10 +260,10 @@ static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG, "disables parallel repair.", 0, 0, 1, 1, 128, 1); -static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, +static MYSQL_THDVAR_ULONGLONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, "The buffer that is allocated when sorting the index when doing a " - "REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", - 0, 0, 128L*1024L*1024L, 4, UINT_MAX32, 1); + "REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", NULL, NULL, + SORT_BUFFER_INIT, MIN_SORT_BUFFER, SIZE_T_MAX, 1); static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG, "Specifies how Aria index statistics collection code should treat " @@ -1455,6 +1455,8 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt) if ((param.testflag & T_REP_BY_SORT)) { param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP; + if (thd->vio_ok()) + _ma_check_print_info(¶m, "Retrying repair with keycache"); sql_print_information("Retrying repair of: '%s' with keycache", table->s->path.str); continue; diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 8d2a2d3aec3..6bcb9c21a71 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -114,7 +114,7 @@ void maria_chk_init(HA_CHECK *param) param->keys_in_use= ~(ulonglong) 0; param->search_after_block=HA_OFFSET_ERROR; param->auto_increment_value= 0; - param->use_buffers=USE_BUFFER_INIT; + param->use_buffers= PAGE_BUFFER_INIT; param->read_buffer_length=READ_BUFFER_INIT; param->write_buffer_length=READ_BUFFER_INIT; param->sort_buffer_length=SORT_BUFFER_INIT; diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 4bc179c3008..65035e77c76 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -36,8 +36,10 @@ #define MERGEBUFF2 31 #define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) -#define DISK_BUFFER_SIZE (IO_SIZE*16) +#define DISK_BUFFER_SIZE (IO_SIZE*128) +/* How many keys we can keep in memory */ +typedef ulonglong ha_keys; /* Pointers of functions for store and read keys from temp file @@ -47,41 +49,42 @@ extern void print_error(const char *fmt,...); /* Functions defined in this file */ -static ha_rows find_all_keys(MARIA_SORT_PARAM *info,uint keys, +static ha_rows find_all_keys(MARIA_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, - DYNAMIC_ARRAY *buffpek,int *maxbuffer, + DYNAMIC_ARRAY *buffpek,uint *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions); -static int write_keys(MARIA_SORT_PARAM *info, uchar **sort_keys, - uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); +static int write_keys(MARIA_SORT_PARAM *info,uchar **sort_keys, + ha_keys count, BUFFPEK *buffpek,IO_CACHE *tempfile); static int write_key(MARIA_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile); static int write_index(MARIA_SORT_PARAM *info, uchar **sort_keys, - uint count); -static int merge_many_buff(MARIA_SORT_PARAM *info,uint keys, + ha_keys count); +static int merge_many_buff(MARIA_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, - BUFFPEK *buffpek,int *maxbuffer, + BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file); -static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, - uint sort_length); -static int merge_buffers(MARIA_SORT_PARAM *info,uint keys, +static my_off_t read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, + uint sort_length); +static int merge_buffers(MARIA_SORT_PARAM *info, ha_keys keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb); -static int merge_index(MARIA_SORT_PARAM *,uint, uchar **,BUFFPEK *, int, +static int merge_index(MARIA_SORT_PARAM *,ha_keys,uchar **,BUFFPEK *, uint, IO_CACHE *); static int flush_maria_ft_buf(MARIA_SORT_PARAM *info); -static int write_keys_varlen(MARIA_SORT_PARAM *info, uchar **sort_keys, - uint count, BUFFPEK *buffpek, +static int write_keys_varlen(MARIA_SORT_PARAM *info,uchar **sort_keys, + ha_keys count, BUFFPEK *buffpek, IO_CACHE *tempfile); -static uint read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, - uint sort_length); +static my_off_t read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, + uint sort_length); static int write_merge_key(MARIA_SORT_PARAM *info, IO_CACHE *to_file, - uchar *key, uint sort_length, uint count); + uchar *key, uint sort_length, ha_keys count); static int write_merge_key_varlen(MARIA_SORT_PARAM *info, - IO_CACHE *to_file, uchar *key, - uint sort_length, uint count); + IO_CACHE *to_file, + uchar* key, uint sort_length, + ha_keys count); static inline int my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); @@ -102,11 +105,11 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, size_t sortbuff_size) { - int error,maxbuffer,skr; - size_t memavl,old_memavl; - uint keys,sort_length; + int error; + uint sort_length, maxbuffer; + size_t memavl, old_memavl; DYNAMIC_ARRAY buffpek; - ha_rows records; + ha_rows records, keys; uchar **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; DBUG_ENTER("_ma_create_index_by_sort"); @@ -117,7 +120,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) { info->write_keys= write_keys_varlen; - info->read_to_buffer=read_to_buffer_varlen; + info->read_to_buffer= read_to_buffer_varlen; info->write_key=write_merge_key_varlen; } else @@ -140,31 +143,53 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, while (memavl >= MIN_SORT_MEMORY) { - if ((records < UINT_MAX32) && - ((my_off_t) (records + 1) * - (sort_length + sizeof(char*)) <= (my_off_t) memavl)) - keys= (uint)records+1; + /* Check if we can fit all keys into memory */ + if (((ulonglong) (records + 1) * + (sort_length + sizeof(char*)) <= memavl)) + keys= records+1; + else if ((info->sort_info->param->testflag & + (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) == + T_FORCE_SORT_MEMORY) + { + /* + Use all of the given sort buffer for key data. + Allocate 1000 buffers at a start for new data. More buffers + will be allocated when needed. + */ + keys= memavl / (sort_length+sizeof(char*)); + maxbuffer= (uint) min((ulonglong) 1000, (records / keys)+1); + } else + { + /* + All keys can't fit in memory. + Calculate how many keys + buffers we can keep in memory + */ + uint maxbuffer_org; do { - skr=maxbuffer; - if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer || - (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/ + maxbuffer_org= maxbuffer; + if (memavl < sizeof(BUFFPEK) * maxbuffer || + (keys= (memavl-sizeof(BUFFPEK)*maxbuffer)/ (sort_length+sizeof(char*))) <= 1 || - keys < (uint) maxbuffer) + keys < maxbuffer) { _ma_check_print_error(info->sort_info->param, - "aria_sort_buffer_size is too small"); + "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu rows: %llu sort_length: %u", + (ulonglong) sortbuff_size, (ulonglong) records, + sort_length); + my_errno= ENOMEM; goto err; } } - while ((maxbuffer= (int) (records/(keys-1)+1)) != skr); + while ((maxbuffer= (uint) (records/(keys-1)+1)) != maxbuffer_org); + } if ((sort_keys=(uchar**) my_malloc(keys*(sort_length+sizeof(char*))+ HA_FT_MAXBYTELEN, MYF(0)))) { if (my_init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer, - maxbuffer/2, MYF(0))) + min(maxbuffer/2, 1000), MYF(0))) { my_free(sort_keys); sort_keys= 0; @@ -178,14 +203,20 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, } if (memavl < MIN_SORT_MEMORY) { - _ma_check_print_error(info->sort_info->param, "Aria sort buffer" - " too small"); /* purecov: tested */ - goto err; /* purecov: tested */ + /* purecov: begin inspected */ + _ma_check_print_error(info->sort_info->param, + "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu rows: %llu sort_length: %u", + (ulonglong) sortbuff_size, (ulonglong) records, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ } (*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */ if (!no_messages) - printf(" - Searching for keys, allocating buffer for %d keys\n",keys); + my_fprintf(stdout, + " - Searching for keys, allocating buffer for %llu keys\n", + (ulonglong) keys); if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer, &tempfile,&tempfile_for_exceptions)) @@ -197,8 +228,8 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, if (maxbuffer == 0) { if (!no_messages) - printf(" - Dumping %lu keys\n", (ulong) records); - if (write_index(info,sort_keys, (uint) records)) + my_fprintf(stdout, " - Dumping %llu keys\n", (ulonglong) records); + if (write_index(info, sort_keys, (ha_keys) records)) goto err; /* purecov: inspected */ } else @@ -207,7 +238,8 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, if (maxbuffer >= MERGEBUFF2) { if (!no_messages) - printf(" - Merging %lu keys\n", (ulong) records); /* purecov: tested */ + my_fprintf(stdout, " - Merging %llu keys\n", + (ulonglong) records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) goto err; /* purecov: inspected */ @@ -266,13 +298,13 @@ err: /* Search after all keys and place them in a temp. file */ -static ha_rows find_all_keys(MARIA_SORT_PARAM *info, uint keys, +static ha_rows find_all_keys(MARIA_SORT_PARAM *info, ha_rows keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek, - int *maxbuffer, IO_CACHE *tempfile, + uint *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions) { int error; - uint idx; + ha_rows idx; DBUG_ENTER("find_all_keys"); idx=error=0; @@ -328,9 +360,11 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) { MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg; int error; - size_t memavl,old_memavl; + size_t memavl, old_memavl; + longlong sortbuff_size; + ha_keys keys, idx; uint sort_length; - ulong idx, maxbuffer, keys; + uint maxbuffer; uchar **sort_keys=0; LINT_INIT(keys); @@ -364,8 +398,9 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) bzero((char*) &sort_param->buffpek,sizeof(sort_param->buffpek)); bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); - memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY); - idx= (uint)sort_param->sort_info->max_records; + sortbuff_size= sort_param->sortbuff_size; + memavl= max(sortbuff_size, MIN_SORT_MEMORY); + idx= (ha_keys) sort_param->sort_info->max_records; sort_length= sort_param->key_length; maxbuffer= 1; @@ -373,23 +408,36 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) { if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) keys= idx+1; + else if ((sort_param->sort_info->param->testflag & + (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) == + T_FORCE_SORT_MEMORY) + { + /* + Use all of the given sort buffer for key data. + Allocate 1000 buffers at a start for new data. More buffers + will be allocated when needed. + */ + keys= memavl / (sort_length+sizeof(char*)); + maxbuffer= (uint) min((ulonglong) 1000, (idx / keys)+1); + } else { - ulong skr; + uint maxbuffer_org; do { - skr= maxbuffer; + maxbuffer_org= maxbuffer; if (memavl < sizeof(BUFFPEK)*maxbuffer || (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ (sort_length+sizeof(char*))) <= 1 || keys < maxbuffer) { _ma_check_print_error(sort_param->sort_info->param, - "aria_sort_buffer_size is too small"); + "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) idx, sort_length); goto err; } } - while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); + while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org); } if ((sort_keys= (uchar **) my_malloc(keys*(sort_length+sizeof(char*))+ @@ -397,7 +445,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) HA_FT_MAXBYTELEN : 0), MYF(0)))) { if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), - maxbuffer, maxbuffer/2, MYF(0))) + maxbuffer, min(maxbuffer/2, 1000), MYF(0))) { my_free(sort_keys); sort_keys= (uchar **) NULL; /* for err: label */ @@ -412,14 +460,19 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) } if (memavl < MIN_SORT_MEMORY) { + /* purecov: begin inspected */ _ma_check_print_error(sort_param->sort_info->param, - "Aria sort buffer too small"); - goto err; /* purecov: tested */ + "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) idx, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ } if (sort_param->sort_info->param->testflag & T_VERBOSE) - printf("Key %d - Allocating buffer for %lu keys\n", - sort_param->key+1, (ulong) keys); + my_fprintf(stdout, + "Key %d - Allocating buffer for %llu keys\n", + sort_param->key + 1, (ulonglong) keys); sort_param->sort_keys= sort_keys; idx= error= 0; @@ -431,7 +484,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) { if (sort_param->real_key_length > sort_param->key_length) { - if (write_key(sort_param,sort_keys[idx], + if (write_key(sort_param, sort_keys[idx], &sort_param->tempfile_for_exceptions)) goto err; continue; @@ -449,7 +502,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) (size_t) sort_param->key_length); idx= 1; } - sort_keys[idx]=sort_keys[idx - 1] + sort_param->key_length; + sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length; } if (error > 0) goto err; @@ -465,14 +518,13 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) else sort_param->keys= idx; - sort_param->sort_keys_length= keys; goto ok; err: DBUG_PRINT("error", ("got some error")); sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */ my_free(sort_keys); - sort_param->sort_keys=0; + sort_param->sort_keys= 0; delete_dynamic(& sort_param->buffpek); close_cached_file(&sort_param->tempfile); close_cached_file(&sort_param->tempfile_for_exceptions); @@ -483,8 +535,12 @@ ok: Detach from the share if the writer is involved. Avoid others to be blocked. This includes a flush of the write buffer. This will also indicate EOF to the readers. + That means that a writer always gets here first and readers - + only when they see EOF. But if a reader finishes prematurely + because of an error it may reach this earlier - don't allow it + to detach the writer thread. */ - if (sort_param->sort_info->info->rec_cache.share) + if (sort_param->master && sort_param->sort_info->info->rec_cache.share) remove_io_thread(&sort_param->sort_info->info->rec_cache); /* Readers detach from the share if any. Avoid others to be blocked. */ @@ -518,7 +574,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) for (i= 0, sinfo= sort_param ; i < sort_info->total_keys ; - i++, rec_per_key_part+=sinfo->keyinfo->keysegs, sinfo++) + i++, sinfo++) { if (!sinfo->sort_keys) { @@ -534,19 +590,15 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) { if (param->testflag & T_VERBOSE) { - printf("Key %d - Dumping %u keys\n",sinfo->key+1, sinfo->keys); + my_fprintf(stdout, + "Key %d - Dumping %llu keys\n", sinfo->key+1, + (ulonglong) sinfo->keys); fflush(stdout); } if (write_index(sinfo, sinfo->sort_keys, sinfo->keys) || flush_maria_ft_buf(sinfo) || _ma_flush_pending_blocks(sinfo)) got_error=1; } - if (!got_error && param->testflag & T_STATISTICS) - maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, - param->stats_method == - MI_STATS_METHOD_IGNORE_NULLS ? - sinfo->notnull : NULL, - (ulonglong) share->state.state.records); } my_free(sinfo->sort_keys); my_free(sinfo->rec_buff); @@ -559,6 +611,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) delete_dynamic(&sinfo->buffpek), close_cached_file(&sinfo->tempfile), close_cached_file(&sinfo->tempfile_for_exceptions), + rec_per_key_part+= sinfo->keyinfo->keysegs, sinfo++) { if (got_error) @@ -597,10 +650,12 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) if (maxbuffer >= MERGEBUFF2) { if (param->testflag & T_VERBOSE) - printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys); - if (merge_many_buff(sinfo, keys, (uchar **) mergebuf, + my_fprintf(stdout, + "Key %d - Merging %llu keys\n", + sinfo->key+1, (ulonglong) sinfo->keys); + if (merge_many_buff(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek, 0, BUFFPEK *), - (int*) &maxbuffer, &sinfo->tempfile)) + &maxbuffer, &sinfo->tempfile)) { got_error=1; continue; @@ -660,6 +715,13 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) } } } + if (!got_error && (param->testflag & T_STATISTICS)) + maria_update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, + param->stats_method == + MI_STATS_METHOD_IGNORE_NULLS ? + sinfo->notnull : NULL, + (ulonglong) share->state.state.records); + } my_free(mergebuf); DBUG_RETURN(got_error); @@ -669,12 +731,15 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) /* Write all keys in memory to file for later merge */ static int write_keys(MARIA_SORT_PARAM *info, register uchar **sort_keys, - uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) + ha_keys count, BUFFPEK *buffpek, IO_CACHE *tempfile) { uchar **end; uint sort_length=info->key_length; DBUG_ENTER("write_keys"); + if (!buffpek) + DBUG_RETURN(1); /* Out of memory */ + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, info); if (!my_b_inited(tempfile) && @@ -687,7 +752,7 @@ static int write_keys(MARIA_SORT_PARAM *info, register uchar **sort_keys, for (end=sort_keys+count ; sort_keys != end ; sort_keys++) { - if (my_b_write(tempfile, *sort_keys, (uint) sort_length)) + if (my_b_write(tempfile, *sort_keys, sort_length)) DBUG_RETURN(1); /* purecov: inspected */ } DBUG_RETURN(0); @@ -710,14 +775,17 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs) static int write_keys_varlen(MARIA_SORT_PARAM *info, - register uchar **sort_keys, - uint count, BUFFPEK *buffpek, - IO_CACHE *tempfile) + register uchar **sort_keys, + ha_keys count, BUFFPEK *buffpek, + IO_CACHE *tempfile) { uchar **end; int err; DBUG_ENTER("write_keys_varlen"); + if (!buffpek) + DBUG_RETURN(1); /* Out of memory */ + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, info); if (!my_b_inited(tempfile) && @@ -756,9 +824,8 @@ static int write_key(MARIA_SORT_PARAM *info, uchar *key, /* Write index */ -static int write_index(MARIA_SORT_PARAM *info, - register uchar **sort_keys, - register uint count) +static int write_index(MARIA_SORT_PARAM *info, register uchar **sort_keys, + register ha_keys count) { DBUG_ENTER("write_index"); @@ -777,11 +844,11 @@ static int write_index(MARIA_SORT_PARAM *info, /* Merge buffers to make < MERGEBUFF2 buffers */ -static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys, - uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, IO_CACHE *t_file) +static int merge_many_buff(MARIA_SORT_PARAM *info, ha_keys keys, + uchar **sort_keys, BUFFPEK *buffpek, + uint *maxbuffer, IO_CACHE *t_file) { - int tmp, merges, max_merges; + uint tmp, merges, max_merges; IO_CACHE t_file2, *from_file, *to_file, *temp; BUFFPEK *lastbuff; DBUG_ENTER("merge_many_buff"); @@ -807,11 +874,11 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys, from_file= t_file ; to_file= &t_file2; while (*maxbuffer >= MERGEBUFF2) { - int i; + uint i; reinit_io_cache(from_file,READ_CACHE,0L,0,0); reinit_io_cache(to_file,WRITE_CACHE,0L,0,0); lastbuff=buffpek; - for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) + for (i=0 ; i + MERGEBUFF*3/2 <= *maxbuffer ; i+=MERGEBUFF) { if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, buffpek+i,buffpek+i+MERGEBUFF-1)) @@ -825,14 +892,19 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys, if (flush_io_cache(to_file)) break; /* purecov: inspected */ temp=from_file; from_file=to_file; to_file=temp; - *maxbuffer= (int) (lastbuff-buffpek)-1; + *maxbuffer= (uint) (lastbuff-buffpek)-1; if (info->sort_info->param->max_stage != 1) /* If not parallel */ _ma_report_progress(info->sort_info->param, merges++, max_merges); } cleanup: close_cached_file(to_file); /* This holds old result */ if (to_file == t_file) + { + DBUG_ASSERT(t_file2.type == WRITE_CACHE); *t_file=t_file2; /* Copy result file */ + t_file->current_pos= &t_file->write_pos; + t_file->current_end= &t_file->write_end; + } DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */ } /* merge_many_buff */ @@ -851,33 +923,35 @@ cleanup: -1 Error */ -static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, - uint sort_length) +static my_off_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) { - register uint count; - uint length; + register ha_keys count; + my_off_t length; - if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) + if ((count= (ha_keys) min((ha_rows) buffpek->max_keys,buffpek->count))) { - if (mysql_file_pread(fromfile->file, buffpek->base, - (length= sort_length*count),buffpek->file_pos,MYF_RW)) - return((uint) -1); /* purecov: inspected */ + if (mysql_file_pread(fromfile->file, (uchar*) buffpek->base, + (length= sort_length * count), + buffpek->file_pos, MYF_RW)) + return(HA_OFFSET_ERROR); /* purecov: inspected */ buffpek->key=buffpek->base; buffpek->file_pos+= length; /* New filepos */ buffpek->count-= count; buffpek->mem_count= count; } - return (count*sort_length); + return (((my_off_t) count) * sort_length); } /* read_to_buffer */ -static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, - uint sort_length) + +static my_off_t read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) { - register uint count; + register ha_keys count; uint idx; uchar *buffp; - if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) + if ((count= (ha_keys) min((ha_rows) buffpek->max_keys,buffpek->count))) { buffp= buffpek->base; @@ -886,7 +960,7 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, uint16 length_of_key; if (mysql_file_pread(fromfile->file,(uchar*)&length_of_key,sizeof(length_of_key), buffpek->file_pos,MYF_RW)) - return((uint) -1); + return(HA_OFFSET_ERROR); buffpek->file_pos+=sizeof(length_of_key); if (mysql_file_pread(fromfile->file, buffp, length_of_key, buffpek->file_pos,MYF_RW)) @@ -898,15 +972,15 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, buffpek->count-= count; buffpek->mem_count= count; } - return (count*sort_length); + return (((my_off_t) count) * sort_length); } /* read_to_buffer_varlen */ static int write_merge_key_varlen(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar* key, - uint sort_length, uint count) + uint sort_length, ha_keys count) { - uint idx; + ha_keys idx; uchar *bufs = key; for (idx=1;idx<=count;idx++) @@ -921,34 +995,40 @@ static int write_merge_key_varlen(MARIA_SORT_PARAM *info, static int write_merge_key(MARIA_SORT_PARAM *info __attribute__((unused)), - IO_CACHE *to_file, uchar *key, - uint sort_length, uint count) + IO_CACHE *to_file, uchar *key, + uint sort_length, ha_keys count) { - return my_b_write(to_file, key, (size_t) sort_length*count); + return my_b_write(to_file, key, ((size_t) sort_length) * count); } /* Merge buffers to one buffer If to_file == 0 then use info->key_write + + Return: + 0 ok + 1 error */ static int -merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, +merge_buffers(MARIA_SORT_PARAM *info, ha_keys keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb) { - int error; - uint sort_length,maxcount; + int error= 1; + uint sort_length; + ha_keys maxcount; ha_rows count; - my_off_t UNINIT_VAR(to_start_filepos); + my_off_t UNINIT_VAR(to_start_filepos), read_length; uchar *strpos; BUFFPEK *buffpek,**refpek; QUEUE queue; DBUG_ENTER("merge_buffers"); - count=error=0; - maxcount=keys/((uint) (Tb-Fb) +1); + count= 0; + maxcount= keys/((uint) (Tb-Fb) +1); DBUG_ASSERT(maxcount > 0); + LINT_INIT(to_start_filepos); if (to_file) to_start_filepos=my_b_tell(to_file); strpos= (uchar*) sort_keys; @@ -963,10 +1043,10 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { count+= buffpek->count; buffpek->base= strpos; - buffpek->max_keys=maxcount; - strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek, - sort_length)); - if (error == -1) + buffpek->max_keys= maxcount; + strpos+= (read_length= info->read_to_buffer(from_file,buffpek, + sort_length)); + if (read_length == HA_OFFSET_ERROR) goto err; /* purecov: inspected */ queue_insert(&queue,(uchar*) buffpek); } @@ -980,27 +1060,20 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { if (info->write_key(info,to_file, buffpek->key, (uint) sort_length,1)) - { - error=1; goto err; /* purecov: inspected */ - } + goto err; /* purecov: inspected */ } else { if ((*info->key_write)(info,(void*) buffpek->key)) - { - error=1; goto err; /* purecov: inspected */ - } + goto err; /* purecov: inspected */ } buffpek->key+=sort_length; if (! --buffpek->mem_count) { /* It's enough to check for killedptr before a slow operation */ if (_ma_killed_ptr(info->sort_info->param)) - { - error=1; goto err; - } - if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length))) + if (!(read_length= info->read_to_buffer(from_file,buffpek,sort_length))) { uchar *base= buffpek->base; uint max_keys=buffpek->max_keys; @@ -1027,9 +1100,9 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } break; /* One buffer have been removed */ } + else if (read_length == HA_OFFSET_ERROR) + goto err; /* purecov: inspected */ } - else if (error == -1) - goto err; /* purecov: inspected */ queue_replace_top(&queue); /* Top element has been replaced */ } } @@ -1061,8 +1134,9 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } } } - while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != - -1 && error != 0); + while ((read_length= info->read_to_buffer(from_file,buffpek,sort_length)) != HA_OFFSET_ERROR && read_length != 0); + if (read_length == 0) + error= 0; lastbuff->count=count; if (to_file) @@ -1076,8 +1150,8 @@ err: /* Do a merge to output-file (save only positions) */ static int -merge_index(MARIA_SORT_PARAM *info, uint keys, uchar **sort_keys, - BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) +merge_index(MARIA_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, + BUFFPEK *buffpek, uint maxbuffer, IO_CACHE *tempfile) { DBUG_ENTER("merge_index"); if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek, diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 62225a7a4b0..8a7ba30eb08 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -191,7 +191,7 @@ end: enum options_mc { OPT_CHARSETS_DIR=256, OPT_SET_COLLATION,OPT_START_CHECK_POS, - OPT_CORRECT_CHECKSUM, OPT_PAGE_BUFFER_SIZE, + OPT_CORRECT_CHECKSUM, OPT_CREATE_MISSING_KEYS, OPT_PAGE_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE, OPT_MARIA_BLOCK_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, @@ -229,6 +229,11 @@ static struct my_option my_long_options[] = {"correct-checksum", OPT_CORRECT_CHECKSUM, "Correct checksum information for table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"create-missing-keys", OPT_CREATE_MISSING_KEYS, + "Create missing keys. This assumes that the data file is correct and that " + "the the number of rows stored in the index file is correct. Enables " + "--quick", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", @@ -362,8 +367,8 @@ static struct my_option my_long_options[] = { "page_buffer_size", OPT_PAGE_BUFFER_SIZE, "Size of page buffer. Used by --safe-repair", &check_param.use_buffers, &check_param.use_buffers, 0, - GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, 1024L*1024L, - (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, + GET_ULONG, REQUIRED_ARG, PAGE_BUFFER_INIT, 1024L*1024L, + SIZE_T_MAX, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, { "read_buffer_size", OPT_READ_BUFFER_SIZE, "Read buffer size for sequential reads during scanning", &check_param.read_buffer_length, @@ -379,9 +384,8 @@ static struct my_option my_long_options[] = { "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "Size of sort buffer. Used by --recover", &check_param.sort_buffer_length, - &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG, - (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), - (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0}, + &check_param.sort_buffer_length, 0, GET_ULL, REQUIRED_ARG, + SORT_BUFFER_INIT, MIN_SORT_BUFFER, SIZE_T_MAX, MALLOC_OVERHEAD, 1L, 0}, { "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "Internal buffer for sorting keys; Don't touch :)", &check_param.sort_key_blocks, @@ -497,10 +501,18 @@ Recover (repair)/ options (When using '--recover' or '--safe-recover'):\n\ --correct-checksum Correct checksum information for table.\n\ -D, --data-file-length=# Max length of data file (when recreating data\n\ file when it's full).\n\ + --create-missing-keys\n\ + Create missing keys. This assumes that the data\n\ + file is correct and that the the number of rows stored\n\ + in the index file is correct. Enables --quick.\n\ -e, --extend-check Try to recover every possible row from the data file\n\ Normally this will also find a lot of garbage rows;\n\ Don't use this option if you are not totally desperate.\n\ - -f, --force Overwrite old temporary files.\n\ + -f, --force Overwrite old temporary files. Add another --force to\n\ + avoid 'sort_buffer_size is too small' errors.\n\ + In this case we will attempt to do the repair with the\n\ + given sort_buffer_size and dynamically allocate\n\ + as many management buffers as needed.\n\ -k, --keys-used=# Tell Aria to update only some specific keys. # is a\n\ bit mask of which keys to use. This can be used to\n\ get faster inserts.\n\ @@ -664,10 +676,13 @@ get_one_option(int optid, if (argument == disabled_my_option) { check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL; - check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE); + check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE | + T_FORCE_SORT_MEMORY); } else { + if (check_param.testflag & T_FORCE_CREATE) + check_param.testflag= T_FORCE_SORT_MEMORY; check_param.tmpfile_createflag= O_RDWR | O_TRUNC; check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE; } @@ -720,8 +735,26 @@ get_one_option(int optid, if (argument == disabled_my_option) check_param.testflag&= ~(T_QUICK | T_FORCE_UNIQUENESS); else + { + /* + If T_QUICK was specified before, but not OPT_CREATE_MISSING_KEYS, + then add T_FORCE_UNIQUENESS. + */ check_param.testflag|= - (check_param.testflag & T_QUICK) ? T_FORCE_UNIQUENESS : T_QUICK; + ((check_param.testflag & (T_QUICK | T_CREATE_MISSING_KEYS)) == + T_QUICK ? T_FORCE_UNIQUENESS : T_QUICK); + } + break; + case OPT_CREATE_MISSING_KEYS: + if (argument == disabled_my_option) + check_param.testflag&= ~(T_QUICK | T_CREATE_MISSING_KEYS); + else + { + check_param.testflag|= T_QUICK | T_CREATE_MISSING_KEYS; + /* Use repair by sort by default */ + if (!(check_param.testflag & T_REP_ANY)) + check_param.testflag|= T_REP_BY_SORT; + } break; case 'u': if (argument == disabled_my_option) diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 0dce9114f2a..a1275e7ccd2 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -94,9 +94,10 @@ typedef struct st_maria_sort_param */ ulonglong unique[HA_MAX_KEY_SEG+1]; ulonglong notnull[HA_MAX_KEY_SEG+1]; + ulonglong sortbuff_size; MARIA_RECORD_POS pos,max_pos,filepos,start_recpos, current_filepos; - uint key, key_length,real_key_length,sortbuff_size; + uint key, key_length,real_key_length; uint maxbuffers, keys, find_length, sort_keys_length; my_bool fix_datafile, master; my_bool calc_checksum; /* calculate table checksum */ @@ -107,10 +108,10 @@ typedef struct st_maria_sort_param int (*key_write)(struct st_maria_sort_param *, const uchar *); void (*lock_in_memory)(HA_CHECK *); int (*write_keys)(struct st_maria_sort_param *, register uchar **, - uint , struct st_buffpek *, IO_CACHE *); - uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + ulonglong , struct st_buffpek *, IO_CACHE *); + my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); int (*write_key)(struct st_maria_sort_param *, IO_CACHE *,uchar *, - uint, uint); + uint, ulonglong); } MARIA_SORT_PARAM; int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile); @@ -1223,10 +1224,11 @@ typedef struct st_maria_block_info #define UPDATE_AUTO_INC 8 #define UPDATE_OPEN_COUNT 16 -#define USE_BUFFER_INIT (((1024L*1024L*128-MALLOC_OVERHEAD)/8192)*8192) -#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (1024L*1024L*256-MALLOC_OVERHEAD) -#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) +/* We use MY_ALIGN_DOWN here mainly to ensure that we get stable values for mysqld --help ) */ +#define PAGE_BUFFER_INIT MY_ALIGN_DOWN(1024L*1024L*256L-MALLOC_OVERHEAD, 8192) +#define READ_BUFFER_INIT MY_ALIGN_DOWN(1024L*256L-MALLOC_OVERHEAD, 1024) +#define SORT_BUFFER_INIT MY_ALIGN_DOWN(1024L*1024L*256L-MALLOC_OVERHEAD, 1024) +#define MIN_SORT_BUFFER 4096 #define fast_ma_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _ma_writeinfo((INFO),0) #define fast_ma_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _ma_readinfo((INFO),F_RDLCK,1) diff --git a/storage/maria/maria_ftdump.c b/storage/maria/maria_ftdump.c index 92e57fa9a1e..68e13a8ddc4 100644 --- a/storage/maria/maria_ftdump.c +++ b/storage/maria/maria_ftdump.c @@ -84,7 +84,7 @@ int main(int argc,char *argv[]) usage(); } - init_pagecache(maria_pagecache, USE_BUFFER_INIT, 0, 0, + init_pagecache(maria_pagecache, PAGE_BUFFER_INIT, 0, 0, MARIA_KEY_BLOCK_LENGTH, MY_WME); if (!(info=maria_open(argv[0], O_RDONLY, diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 74aa8bd9d11..d9393399da4 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -32,7 +32,8 @@ const char *default_dbug_option= "d:t:o,/tmp/aria_read_log.trace"; static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent; static my_bool opt_check; static const char *opt_tmpdir; -static ulong opt_page_buffer_size, opt_translog_buffer_size; +static ulong opt_translog_buffer_size; +static ulonglong opt_page_buffer_size; static ulonglong opt_start_from_lsn, opt_end_lsn, opt_start_from_checkpoint; static MY_TMPDIR maria_chk_tmpdir; @@ -204,9 +205,8 @@ static struct my_option my_long_options[] = { "page-buffer-size", 'P', "The size of the buffer used for index blocks for Aria tables", &opt_page_buffer_size, &opt_page_buffer_size, 0, - GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, - 1024L*1024L, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD, - (long) IO_SIZE, 0}, + GET_ULL, REQUIRED_ARG, PAGE_BUFFER_INIT, + PAGE_BUFFER_INIT, SIZE_T_MAX, MALLOC_OVERHEAD, (long) IO_SIZE, 0}, { "start-from-lsn", 'o', "Start reading log from this lsn", &opt_start_from_lsn, &opt_start_from_lsn, 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 5432f4fa605..c5d4f987c00 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -78,7 +78,7 @@ static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_ULONGLONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, "The buffer that is allocated when sorting the index when doing " "a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE", NULL, NULL, - 8192 * 1024, MIN_SORT_BUFFER + MALLOC_OVERHEAD, SIZE_T_MAX, 1); + SORT_BUFFER_INIT, MIN_SORT_BUFFER, SIZE_T_MAX, 1); static MYSQL_SYSVAR_BOOL(use_mmap, opt_myisam_use_mmap, PLUGIN_VAR_NOCMDARG, "Use memory mapping for reading and writing MyISAM tables", NULL, NULL, FALSE); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 056aff5a72b..97ea1d17c26 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -91,7 +91,7 @@ void myisamchk_init(HA_CHECK *param) param->opt_follow_links=1; param->keys_in_use= ~(ulonglong) 0; param->search_after_block=HA_OFFSET_ERROR; - param->use_buffers=USE_BUFFER_INIT; + param->use_buffers= KEY_BUFFER_INIT; param->read_buffer_length=READ_BUFFER_INIT; param->write_buffer_length=READ_BUFFER_INIT; param->sort_buffer_length=SORT_BUFFER_INIT; diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c index ce0d7be3f0b..e1ea9f2de37 100644 --- a/storage/myisam/myisam_ftdump.c +++ b/storage/myisam/myisam_ftdump.c @@ -84,7 +84,7 @@ int main(int argc,char *argv[]) usage(); } - init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0); + init_key_cache(dflt_key_cache, MI_KEY_BLOCK_LENGTH, KEY_BUFFER_INIT, 0, 0, 0); if (!(info=mi_open(argv[0], O_RDONLY, HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER))) diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 7be84599d86..d5c13e9cba3 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -134,7 +134,7 @@ int main(int argc, char **argv) enum options_mc { OPT_CHARSETS_DIR=256, OPT_SET_COLLATION,OPT_START_CHECK_POS, - OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, + OPT_CORRECT_CHECKSUM, OPT_CREATE_MISSING_KEYS, OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, @@ -165,6 +165,11 @@ static struct my_option my_long_options[] = {"correct-checksum", OPT_CORRECT_CHECKSUM, "Correct checksum information for table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"create-missing-keys", OPT_CREATE_MISSING_KEYS, + "Create missing keys. This assumes that the data file is correct and that " + "the the number of rows stored in the index file is correct. Enables " + "--quick", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", @@ -270,7 +275,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "key_buffer_size", OPT_KEY_BUFFER_SIZE, "", &check_param.use_buffers, &check_param.use_buffers, 0, - GET_ULL, REQUIRED_ARG, USE_BUFFER_INIT, MALLOC_OVERHEAD, + GET_ULL, REQUIRED_ARG, KEY_BUFFER_INIT, MALLOC_OVERHEAD, SIZE_T_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, { "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "", &opt_key_cache_block_size, @@ -395,10 +400,18 @@ static void usage(void) -e, --extend-check Try to recover every possible row from the data file\n\ Normally this will also find a lot of garbage rows;\n\ Don't use this option if you are not totally desperate.\n\ - -f, --force Overwrite old temporary files.\n\ + -f, --force Overwrite old temporary files. Add another --force to\n\ + avoid 'myisam_sort_buffer_size is too small' errors.\n\ + In this case we will attempt to do the repair with the\n\ + given myisam_sort_buffer_size and dynamically allocate\n\ + as many management buffers as needed.\n\ -k, --keys-used=# Tell MyISAM to update only some specific keys. # is a\n\ bit mask of which keys to use. This can be used to\n\ get faster inserts.\n\ + --create-missing-keys\n\ + Create missing keys. This assumes that the data\n\ + file is correct and that the the number of rows stored\n\ + in the index file is correct. Enables --quick\n\ --max-record-length=#\n\ Skip rows bigger than this if myisamchk can't allocate\n\ memory to hold it.\n\ @@ -541,10 +554,13 @@ get_one_option(int optid, if (argument == disabled_my_option) { check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL; - check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE); + check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE | + T_FORCE_SORT_MEMORY); } else { + if (check_param.testflag & T_FORCE_CREATE) + check_param.testflag= T_FORCE_SORT_MEMORY; check_param.tmpfile_createflag= O_RDWR | O_TRUNC; check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE; } @@ -597,8 +613,26 @@ get_one_option(int optid, if (argument == disabled_my_option) check_param.testflag&= ~(T_QUICK | T_FORCE_UNIQUENESS); else + { + /* + If T_QUICK was specified before, but not OPT_CREATE_MISSING_KEYS, + then add T_FORCE_UNIQUENESS. + */ check_param.testflag|= - (check_param.testflag & T_QUICK) ? T_FORCE_UNIQUENESS : T_QUICK; + ((check_param.testflag & (T_QUICK | T_CREATE_MISSING_KEYS)) == + T_QUICK ? T_FORCE_UNIQUENESS : T_QUICK); + } + break; + case OPT_CREATE_MISSING_KEYS: + if (argument == disabled_my_option) + check_param.testflag&= ~(T_QUICK | T_CREATE_MISSING_KEYS); + else + { + check_param.testflag|= T_QUICK | T_CREATE_MISSING_KEYS; + /* Use repair by sort by default */ + if (!(check_param.testflag & T_REP_ANY)) + check_param.testflag|= T_REP_BY_SORT; + } break; case 'u': if (argument == disabled_my_option) diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index a0377e34130..178660d6249 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -629,10 +629,11 @@ typedef struct st_mi_block_info /* Parameter to _mi_get_block_info */ #define UPDATE_AUTO_INC 8 #define UPDATE_OPEN_COUNT 16 -#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE) -#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) -#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) +/* We use MY_ALIGN_DOWN here mainly to ensure that we get stable values for mysqld --help ) */ +#define KEY_BUFFER_INIT MY_ALIGN_DOWN(1024L*1024L-MALLOC_OVERHEAD, IO_SIZE) +#define READ_BUFFER_INIT MY_ALIGN_DOWN(1024L*256L-MALLOC_OVERHEAD, 1024) +#define SORT_BUFFER_INIT MY_ALIGN_DOWN(1024L*1024L*128L-MALLOC_OVERHEAD, 1024) +#define MIN_SORT_BUFFER 4096 enum myisam_log_commands { diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 4af45ea02e9..4bff7b14e1a 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -34,8 +34,10 @@ #define MERGEBUFF 15 #define MERGEBUFF2 31 #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) -#define DISK_BUFFER_SIZE (IO_SIZE*16) +#define DISK_BUFFER_SIZE (IO_SIZE*128) +/* How many keys we can keep in memory */ +typedef ulonglong ha_keys; /* Pointers of functions for store and read keys from temp file @@ -45,42 +47,42 @@ extern void print_error(const char *fmt,...); /* Functions defined in this file */ -static ha_rows find_all_keys(MI_SORT_PARAM *info,uint keys, +static ha_rows find_all_keys(MI_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, - DYNAMIC_ARRAY *buffpek,int *maxbuffer, + DYNAMIC_ARRAY *buffpek,uint *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions); static int write_keys(MI_SORT_PARAM *info,uchar **sort_keys, - uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); + ha_keys count, BUFFPEK *buffpek,IO_CACHE *tempfile); static int write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile); static int write_index(MI_SORT_PARAM *info,uchar * *sort_keys, - uint count); -static int merge_many_buff(MI_SORT_PARAM *info,uint keys, + ha_keys count); +static int merge_many_buff(MI_SORT_PARAM *info, ha_keys keys, uchar * *sort_keys, - BUFFPEK *buffpek,int *maxbuffer, + BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file); -static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, - uint sort_length); -static int merge_buffers(MI_SORT_PARAM *info,uint keys, +static my_off_t read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, + uint sort_length); +static int merge_buffers(MI_SORT_PARAM *info, ha_keys keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar * *sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb); -static int merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, +static int merge_index(MI_SORT_PARAM *,ha_keys,uchar **,BUFFPEK *, uint, IO_CACHE *); static int flush_ft_buf(MI_SORT_PARAM *info); static int write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys, - uint count, BUFFPEK *buffpek, + ha_keys count, BUFFPEK *buffpek, IO_CACHE *tempfile); -static uint read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, +static my_off_t read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); static int write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file, - uchar *key, uint sort_length, uint count); + uchar *key, uint sort_length, ha_keys count); static int write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar* key, uint sort_length, - uint count); + ha_keys count); static inline int my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); @@ -101,15 +103,15 @@ my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulonglong sortbuff_size) { - int error,maxbuffer,skr; - uint sort_length, keys; + int error; + uint sort_length, maxbuffer; ulonglong memavl, old_memavl; DYNAMIC_ARRAY buffpek; - ha_rows records; + ha_rows records, keys; uchar **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; DBUG_ENTER("_create_index_by_sort"); - DBUG_PRINT("enter",("sort_length: %d", info->key_length)); + DBUG_PRINT("enter",("sort_length: %u", info->key_length)); if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) { @@ -135,37 +137,55 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, sort_length= info->key_length; LINT_INIT(keys); - if ((memavl - sizeof(BUFFPEK)) / (sort_length + sizeof(char *)) > UINT_MAX32) - memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); - while (memavl >= MIN_SORT_BUFFER) { - if ((records < UINT_MAX32) && - ((my_off_t) (records + 1) * - (sort_length + sizeof(char*)) <= (my_off_t) memavl)) - keys= (uint)records+1; + /* Check if we can fit all keys into memory */ + if (((ulonglong) (records + 1) * + (sort_length + sizeof(char*)) <= memavl)) + keys= records+1; + else if ((info->sort_info->param->testflag & + (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) == + T_FORCE_SORT_MEMORY) + { + /* + Use all of the given sort buffer for key data. + Allocate 1000 buffers at a start for new data. More buffers + will be allocated when needed. + */ + keys= memavl / (sort_length+sizeof(char*)); + maxbuffer= (uint) min((ulonglong) 1000, (records / keys)+1); + } else + { + /* + All keys can't fit in memory. + Calculate how many keys + buffers we can keep in memory + */ + uint maxbuffer_org; do { - skr=maxbuffer; - if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer || - (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/ + maxbuffer_org= maxbuffer; + if (memavl < sizeof(BUFFPEK) * maxbuffer || + (keys= (memavl-sizeof(BUFFPEK)*maxbuffer)/ (sort_length+sizeof(char*))) <= 1 || - keys < (uint) maxbuffer) + keys < maxbuffer) { mi_check_print_error(info->sort_info->param, - "myisam_sort_buffer_size is too small"); + "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) records, + sort_length); my_errno= ENOMEM; goto err; } } - while ((maxbuffer= (int) (records/(keys-1)+1)) != skr); + while ((maxbuffer= (uint) (records/(keys-1)+1)) != maxbuffer_org); + } if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+ HA_FT_MAXBYTELEN, MYF(0)))) { if (my_init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer, - maxbuffer/2, MYF(0))) + min(maxbuffer/2, 1000), MYF(0))) { my_free(sort_keys); sort_keys= 0; @@ -179,24 +199,30 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, } if (memavl < MIN_SORT_BUFFER) { - mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */ - my_errno= ENOMEM; /* purecov: tested */ - goto err; /* purecov: tested */ + /* purecov: begin inspected */ + mi_check_print_error(info->sort_info->param, + "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) records, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ } (*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */ if (!no_messages) - printf(" - Searching for keys, allocating buffer for %d keys\n",keys); + my_fprintf(stdout, + " - Searching for keys, allocating buffer for %llu keys\n", + (ulonglong) keys); - if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer, - &tempfile,&tempfile_for_exceptions)) + if ((records= find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer, + &tempfile,&tempfile_for_exceptions)) == HA_POS_ERROR) goto err; /* purecov: tested */ if (maxbuffer == 0) { if (!no_messages) - printf(" - Dumping %lu keys\n", (ulong) records); - if (write_index(info,sort_keys, (uint) records)) + my_fprintf(stdout, " - Dumping %llu keys\n", (ulonglong) records); + if (write_index(info, sort_keys, (ha_keys) records)) goto err; /* purecov: inspected */ } else @@ -205,7 +231,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (maxbuffer >= MERGEBUFF2) { if (!no_messages) - printf(" - Merging %lu keys\n", (ulong) records); /* purecov: tested */ + my_fprintf(stdout, " - Merging %llu keys\n", + (ulonglong) records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) goto err; /* purecov: inspected */ @@ -259,13 +286,13 @@ err: /* Search after all keys and place them in a temp. file */ -static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys, +static ha_rows find_all_keys(MI_SORT_PARAM *info, ha_rows keys, uchar **sort_keys, DYNAMIC_ARRAY *buffpek, - int *maxbuffer, IO_CACHE *tempfile, + uint *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions) { int error; - uint idx; + ha_rows idx; DBUG_ENTER("find_all_keys"); idx=error=0; @@ -314,9 +341,10 @@ pthread_handler_t thr_find_all_keys(void *arg) { MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg; int error; - ulonglong memavl, old_memavl; - uint keys, sort_length; - uint idx, maxbuffer; + ulonglong memavl, old_memavl, sortbuff_size; + ha_keys keys, idx; + uint sort_length; + uint maxbuffer; uchar **sort_keys=0; LINT_INIT(keys); @@ -351,37 +379,47 @@ pthread_handler_t thr_find_all_keys(void *arg) bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); sort_keys= (uchar **) NULL; - memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER); - idx= (uint)sort_param->sort_info->max_records; + sortbuff_size= sort_param->sortbuff_size; + memavl= max(sortbuff_size, MIN_SORT_BUFFER); + idx= (ha_keys) sort_param->sort_info->max_records; sort_length= sort_param->key_length; maxbuffer= 1; - if ((memavl - sizeof(BUFFPEK)) / (sort_length + - sizeof(char *)) > UINT_MAX32) - memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); - while (memavl >= MIN_SORT_BUFFER) { if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) keys= idx+1; + else if ((sort_param->sort_info->param->testflag & + (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) == + T_FORCE_SORT_MEMORY) + { + /* + Use all of the given sort buffer for key data. + Allocate 1000 buffers at a start for new data. More buffers + will be allocated when needed. + */ + keys= memavl / (sort_length+sizeof(char*)); + maxbuffer= (uint) min((ulonglong) 1000, (idx / keys)+1); + } else { - uint skr; + uint maxbuffer_org; do { - skr= maxbuffer; + maxbuffer_org= maxbuffer; if (memavl < sizeof(BUFFPEK)*maxbuffer || (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ (sort_length+sizeof(char*))) <= 1 || keys < (uint) maxbuffer) { mi_check_print_error(sort_param->sort_info->param, - "myisam_sort_buffer_size is too small"); + "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) idx, sort_length); goto err; } } - while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); + while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org); } if ((sort_keys= (uchar**) my_malloc(keys*(sort_length+sizeof(char*))+ @@ -389,7 +427,7 @@ pthread_handler_t thr_find_all_keys(void *arg) HA_FT_MAXBYTELEN : 0), MYF(0)))) { if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK), - maxbuffer, maxbuffer/2, MYF(0))) + maxbuffer, min(maxbuffer/2, 1000), MYF(0))) { my_free(sort_keys); sort_keys= (uchar **) NULL; /* for err: label */ @@ -404,14 +442,19 @@ pthread_handler_t thr_find_all_keys(void *arg) } if (memavl < MIN_SORT_BUFFER) { + /* purecov: begin inspected */ mi_check_print_error(sort_param->sort_info->param, - "MyISAM sort buffer too small"); - goto err; /* purecov: tested */ + "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu rows: %llu sort_length: %u", + sortbuff_size, (ulonglong) idx, sort_length); + my_errno= ENOMEM; + goto err; + /* purecov: end inspected */ } if (sort_param->sort_info->param->testflag & T_VERBOSE) - printf("Key %d - Allocating buffer for %d keys\n", - sort_param->key + 1, keys); + my_fprintf(stdout, + "Key %d - Allocating buffer for %llu keys\n", + sort_param->key + 1, (ulonglong) keys); sort_param->sort_keys= sort_keys; idx= error= 0; @@ -436,7 +479,8 @@ pthread_handler_t thr_find_all_keys(void *arg) &sort_param->tempfile)) goto err; sort_keys[0]= (uchar*) (sort_keys+keys); - memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length); + memcpy(sort_keys[0], sort_keys[idx - 1], + (size_t) sort_param->key_length); idx= 1; } sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length; @@ -454,7 +498,6 @@ pthread_handler_t thr_find_all_keys(void *arg) else sort_param->keys= idx; - sort_param->sort_keys_length= keys; goto ok; err: @@ -527,7 +570,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { if (param->testflag & T_VERBOSE) { - printf("Key %d - Dumping %u keys\n",sinfo->key+1, sinfo->keys); + my_fprintf(stdout, + "Key %d - Dumping %llu keys\n", sinfo->key+1, + (ulonglong) sinfo->keys); fflush(stdout); } if (write_index(sinfo, sinfo->sort_keys, sinfo->keys) || @@ -584,10 +629,12 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) if (maxbuffer >= MERGEBUFF2) { if (param->testflag & T_VERBOSE) - printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys); + my_fprintf(stdout, + "Key %d - Merging %llu keys\n", + sinfo->key+1, (ulonglong) sinfo->keys); if (merge_many_buff(sinfo, keys, (uchar **)mergebuf, dynamic_element(&sinfo->buffpek, 0, BUFFPEK *), - (int*) &maxbuffer, &sinfo->tempfile)) + &maxbuffer, &sinfo->tempfile)) { got_error=1; continue; @@ -651,12 +698,15 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) /* Write all keys in memory to file for later merge */ static int write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, - uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) + ha_keys count, BUFFPEK *buffpek, IO_CACHE *tempfile) { uchar **end; uint sort_length=info->key_length; DBUG_ENTER("write_keys"); + if (!buffpek) + DBUG_RETURN(1); /* Out of memory */ + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, info); if (!my_b_inited(tempfile) && @@ -669,7 +719,7 @@ static int write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, for (end=sort_keys+count ; sort_keys != end ; sort_keys++) { - if (my_b_write(tempfile,(uchar*) *sort_keys,(uint) sort_length)) + if (my_b_write(tempfile,(uchar*) *sort_keys, sort_length)) DBUG_RETURN(1); /* purecov: inspected */ } DBUG_RETURN(0); @@ -693,13 +743,16 @@ my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs) static int write_keys_varlen(MI_SORT_PARAM *info, register uchar **sort_keys, - uint count, BUFFPEK *buffpek, + ha_keys count, BUFFPEK *buffpek, IO_CACHE *tempfile) { uchar **end; int err; DBUG_ENTER("write_keys_varlen"); + if (!buffpek) + DBUG_RETURN(1); /* Out of memory */ + my_qsort2((uchar*) sort_keys,count,sizeof(uchar*),(qsort2_cmp) info->key_cmp, info); if (!my_b_inited(tempfile) && @@ -738,7 +791,7 @@ static int write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile) /* Write index */ static int write_index(MI_SORT_PARAM *info, register uchar **sort_keys, - register uint count) + register ha_keys count) { DBUG_ENTER("write_index"); @@ -755,11 +808,11 @@ static int write_index(MI_SORT_PARAM *info, register uchar **sort_keys, /* Merge buffers to make < MERGEBUFF2 buffers */ -static int merge_many_buff(MI_SORT_PARAM *info, uint keys, +static int merge_many_buff(MI_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, IO_CACHE *t_file) + uint *maxbuffer, IO_CACHE *t_file) { - register int i; + register uint i; IO_CACHE t_file2, *from_file, *to_file, *temp; BUFFPEK *lastbuff; DBUG_ENTER("merge_many_buff"); @@ -777,7 +830,7 @@ static int merge_many_buff(MI_SORT_PARAM *info, uint keys, reinit_io_cache(from_file,READ_CACHE,0L,0,0); reinit_io_cache(to_file,WRITE_CACHE,0L,0,0); lastbuff=buffpek; - for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) + for (i=0 ; i + MERGEBUFF*3/2 <= *maxbuffer ; i+=MERGEBUFF) { if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, buffpek+i,buffpek+i+MERGEBUFF-1)) @@ -789,7 +842,7 @@ static int merge_many_buff(MI_SORT_PARAM *info, uint keys, if (flush_io_cache(to_file)) break; /* purecov: inspected */ temp=from_file; from_file=to_file; to_file=temp; - *maxbuffer= (int) (lastbuff-buffpek)-1; + *maxbuffer= (uint) (lastbuff-buffpek)-1; } cleanup: close_cached_file(to_file); /* This holds old result */ @@ -818,35 +871,36 @@ cleanup: -1 Error */ -static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, - uint sort_length) +static my_off_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) { - register uint count; - uint length; + register ha_keys count; + my_off_t length; - if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) + if ((count= (ha_keys) min((ha_rows) buffpek->max_keys,buffpek->count))) { if (mysql_file_pread(fromfile->file, (uchar*) buffpek->base, - (length= sort_length*count), + (length= sort_length * count), buffpek->file_pos, MYF_RW)) - return((uint) -1); /* purecov: inspected */ + return(HA_OFFSET_ERROR); /* purecov: inspected */ buffpek->key=buffpek->base; - buffpek->file_pos+= length; /* New filepos */ + buffpek->file_pos+= length; /* New filepos */ buffpek->count-= count; buffpek->mem_count= count; } - return (count*sort_length); + return (((my_off_t) count) * sort_length); } /* read_to_buffer */ -static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, - uint sort_length) + +static my_off_t read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) { - register uint count; + register ha_keys count; uint16 length_of_key = 0; uint idx; uchar *buffp; - if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) + if ((count= (ha_keys) min((ha_rows) buffpek->max_keys,buffpek->count))) { buffp = buffpek->base; @@ -854,11 +908,11 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, { if (mysql_file_pread(fromfile->file, (uchar*)&length_of_key, sizeof(length_of_key), buffpek->file_pos, MYF_RW)) - return((uint) -1); + return(HA_OFFSET_ERROR); buffpek->file_pos+=sizeof(length_of_key); if (mysql_file_pread(fromfile->file, (uchar*) buffp, length_of_key, buffpek->file_pos, MYF_RW)) - return((uint) -1); + return(HA_OFFSET_ERROR); buffpek->file_pos+=length_of_key; buffp = buffp + sort_length; } @@ -866,15 +920,15 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, buffpek->count-= count; buffpek->mem_count= count; } - return (count*sort_length); + return (((my_off_t) count) * sort_length); } /* read_to_buffer_varlen */ static int write_merge_key_varlen(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar* key, - uint sort_length, uint count) + uint sort_length, ha_keys count) { - uint idx; + ha_keys idx; uchar *bufs = key; for (idx=1;idx<=count;idx++) @@ -890,32 +944,37 @@ static int write_merge_key_varlen(MI_SORT_PARAM *info, static int write_merge_key(MI_SORT_PARAM *info __attribute__((unused)), IO_CACHE *to_file, uchar *key, - uint sort_length, uint count) + uint sort_length, ha_keys count) { - return my_b_write(to_file, key, (size_t) sort_length*count); + return my_b_write(to_file, key, ((size_t) sort_length) * count); } /* Merge buffers to one buffer If to_file == 0 then use info->key_write + + Return: + 0 ok + 1 error */ static int -merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, +merge_buffers(MI_SORT_PARAM *info, ha_keys keys, IO_CACHE *from_file, IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb) { - int error; - uint sort_length,maxcount; + int error= 1; + uint sort_length; + ha_keys maxcount; ha_rows count; - my_off_t UNINIT_VAR(to_start_filepos); + my_off_t UNINIT_VAR(to_start_filepos), read_length; uchar *strpos; BUFFPEK *buffpek,**refpek; QUEUE queue; DBUG_ENTER("merge_buffers"); count=error=0; - maxcount=keys/((uint) (Tb-Fb) +1); + maxcount= keys/((uint) (Tb-Fb) +1); DBUG_ASSERT(maxcount > 0); LINT_INIT(to_start_filepos); if (to_file) @@ -932,10 +991,10 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { count+= buffpek->count; buffpek->base= (uchar*) strpos; - buffpek->max_keys=maxcount; - strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek, - sort_length)); - if (error == -1) + buffpek->max_keys= maxcount; + strpos+= (read_length= info->read_to_buffer(from_file,buffpek, + sort_length)); + if (read_length == HA_OFFSET_ERROR) goto err; /* purecov: inspected */ queue_insert(&queue,(uchar*) buffpek); } @@ -966,10 +1025,9 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, /* It's enough to check for killedptr before a slow operation */ if (killed_ptr(info->sort_info->param)) { - error=1; goto err; } - if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length))) + if (!(read_length= info->read_to_buffer(from_file,buffpek,sort_length))) { uchar *base= buffpek->base; uint max_keys=buffpek->max_keys; @@ -996,9 +1054,9 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } break; /* One buffer have been removed */ } + else if (read_length == HA_OFFSET_ERROR) + goto err; /* purecov: inspected */ } - else if (error == -1) - goto err; /* purecov: inspected */ queue_replace_top(&queue); /* Top element has been replaced */ } } @@ -1030,8 +1088,9 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } } } - while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 && - error != 0); + while ((read_length= info->read_to_buffer(from_file,buffpek,sort_length)) != HA_OFFSET_ERROR && read_length != 0); + if (read_length == 0) + error= 0; lastbuff->count=count; if (to_file) @@ -1045,8 +1104,8 @@ err: /* Do a merge to output-file (save only positions) */ static int -merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, - BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) +merge_index(MI_SORT_PARAM *info, ha_keys keys, uchar **sort_keys, + BUFFPEK *buffpek, uint maxbuffer, IO_CACHE *tempfile) { DBUG_ENTER("merge_index"); if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek, @@ -1055,6 +1114,7 @@ merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, DBUG_RETURN(0); } /* merge_index */ + static int flush_ft_buf(MI_SORT_PARAM *info) { @@ -1067,4 +1127,3 @@ flush_ft_buf(MI_SORT_PARAM *info) } return err; } - From 7202c21b343c14d0f1fc868fc7789486338a656f Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 10 May 2013 16:01:38 +0300 Subject: [PATCH 04/10] Merge of patch lp:~ahiguti100/maria/handlersocket-fix-78 by Akira Higuchi A bugfix of HandlerSocket is not applied to mariadb yet --- .../docs-en/about-handlersocket.en.txt | 2 +- .../docs-en/installation.en.txt | 9 +- .../handler_socket/docs-en/perl-client.en.txt | 10 +- plugin/handler_socket/docs-en/protocol.en.txt | 33 ++- .../docs-ja/installation.ja.txt | 3 +- .../handler_socket/docs-ja/perl-client.ja.txt | 10 +- plugin/handler_socket/docs-ja/protocol.ja.txt | 248 ++++++++++++------ .../handler_socket/handlersocket/database.cpp | 2 +- .../perl-Net-HandlerSocket/HandlerSocket.xs | 2 +- .../handler_socket/regtest/test_01_lib/run.sh | 2 +- .../regtest/test_01_lib/test14.pl | 2 +- .../regtest/test_01_lib/test17.pl | 2 +- .../regtest/test_01_lib/test19.pl | 2 +- .../regtest/test_01_lib/test24.expected | 2 + .../regtest/test_01_lib/test24.pl | 35 +++ 15 files changed, 256 insertions(+), 108 deletions(-) create mode 100644 plugin/handler_socket/regtest/test_01_lib/test24.expected create mode 100644 plugin/handler_socket/regtest/test_01_lib/test24.pl diff --git a/plugin/handler_socket/docs-en/about-handlersocket.en.txt b/plugin/handler_socket/docs-en/about-handlersocket.en.txt index 0a13a2713d6..73b9cab556b 100644 --- a/plugin/handler_socket/docs-en/about-handlersocket.en.txt +++ b/plugin/handler_socket/docs-en/about-handlersocket.en.txt @@ -66,7 +66,7 @@ Here is a list of other language bindings: https://github.com/koichik/node-handlersocket The home of HandlerSocket is here: - https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL + https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL More documents are available in docs-en/ and docs-ja/ directories. diff --git a/plugin/handler_socket/docs-en/installation.en.txt b/plugin/handler_socket/docs-en/installation.en.txt index 8e680ed35f1..0a0616fa5c8 100644 --- a/plugin/handler_socket/docs-en/installation.en.txt +++ b/plugin/handler_socket/docs-en/installation.en.txt @@ -17,10 +17,11 @@ crash, etc). $ ./autogen.sh $ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin - --with-mysql-source refers to the top of MySQL source directory, ---with-mysql-bindir refers to where MySQL binary executables (i.e. -mysql_config) are located, and --with-mysql-plugindir refers to a plugin -directory where plugin libraries (*.so) are installed. + --with-mysql-source refers to the top of MySQL source directory (which +contains the VERSION file or the configure.in file), --with-mysql-bindir +refers to where MySQL binary executables (i.e. mysql_config) are located, +and --with-mysql-plugindir refers to a plugin directory where plugin +libraries (*.so) are installed. $ make $ sudo make install diff --git a/plugin/handler_socket/docs-en/perl-client.en.txt b/plugin/handler_socket/docs-en/perl-client.en.txt index 2b863c638f0..448d33b5f12 100644 --- a/plugin/handler_socket/docs-en/perl-client.en.txt +++ b/plugin/handler_socket/docs-en/perl-client.en.txt @@ -93,7 +93,6 @@ The execute_single method can be used for inserting records also. my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]); die $hs->get_error() if $res->[0] != 0; - my $num_inserted_rows = $res->[1]; The 3rd argument must be an arrayref whose elements correspond to the 5th argument for the corresponding open_index call. If there @@ -116,6 +115,15 @@ executing them separatedly. # ... } +----------------------------------------------------------------- +If handlersocket is configured to authenticate client connections +(ie., handlersocket_plain_secret or handlersocket_plain_secret_wr +is set), a client must call 'auth' method before any other +methods. + + my $res = $hs->auth('password'); + die $hs->get_error() if $res->[0] != 0; + ----------------------------------------------------------------- When an error is occured, the first element of the returned arrayref becomes a non-zero value. A negative value indicates diff --git a/plugin/handler_socket/docs-en/protocol.en.txt b/plugin/handler_socket/docs-en/protocol.en.txt index afde231df7d..e36f17444ae 100644 --- a/plugin/handler_socket/docs-en/protocol.en.txt +++ b/plugin/handler_socket/docs-en/protocol.en.txt @@ -29,7 +29,7 @@ Request and Response lines) at one time, and receive responses for them at one time. ---------------------------------------------------------------------------- -'open_index' request +Opening index The 'open_index' request has the following syntax. @@ -74,23 +74,21 @@ FILETER is a sequence of the following parameters. HandlerSocket supports '=', '>', '>=', '<', and '<='. - indicates the length of the trailing parameters ... . This must be smaller than or equal to the number of index columns specified by - the parameter of the corresponding 'open_index' request. + the parameter of the corresponding 'open_index' request. - ... specify the index column values to fetch. - LIM is optional. and are numbers. When omitted, it works as if 1 and 0 are specified. These parameter works like LIMIT of SQL. These values don't include the number of records skipped by a filter. - IN is optional. It works like WHERE ... IN syntax of SQL. must be - smaller than or equal to the number of index columns specified by the - parameter of the corresponding 'open_index' request. If IN is - specified in a find request, the -th parameter value of ... - is ignored. - smaller than or equal to the number of index columns specified by the + smaller than the number of index columns specified by the + parameter of the corresponding 'open_index' request. If IN is specified in + a find request, the -th parameter value of ... is ignored. - FILTERs are optional. A FILTER specifies a filter. is either 'F' (filter) or 'W' (while). specifies the comparison operation to use. - must be smaller than or equal to the number of columns specified by - the parameter of the corresponding 'open_index' request. - Multiple filters can be specified, and work as the logical AND of them. - The difference of 'F' and 'W' is that, when a record does not meet the + must be smaller than the number of columns specified by the + parameter of the corresponding 'open_index' request. Multiple + filters can be specified, and work as the logical AND of them. The + difference of 'F' and 'W' is that, when a record does not meet the specified condition, 'F' simply skips the record, and 'W' stops the loop. ---------------------------------------------------------------------------- @@ -112,8 +110,8 @@ MOD is a sequence of the following parameters. must be smaller than or equal to the length of specified by the corresponding 'open_index' request. If is 'D', these parameters are ignored. If is '+' or '-', values must be numeric. If is - '-' and it attempts to change column values from negative to positive or - positive to negative, it is not modified. + '-' and it attempts to change a column value from negative to positive or + positive to negative, the column value is not modified. ---------------------------------------------------------------------------- Inserting data @@ -187,6 +185,8 @@ syntax. 0 1 - is the number of modified rows. +- As an exception, if the '?' suffix is specified in , a response has + the syntax of a response for 'find' instead. ---------------------------------------------------------------------------- Response for 'insert' @@ -196,3 +196,10 @@ syntax. 0 1 +---------------------------------------------------------------------------- +Response for 'auth' + +If 'auth' is succeeded, HanderSocket returns a line of the following syntax. + + 0 1 + diff --git a/plugin/handler_socket/docs-ja/installation.ja.txt b/plugin/handler_socket/docs-ja/installation.ja.txt index c14f47f6c02..0e8f3513712 100644 --- a/plugin/handler_socket/docs-ja/installation.ja.txt +++ b/plugin/handler_socket/docs-ja/installation.ja.txt @@ -8,7 +8,8 @@ HandlerSocketプラグインのビルド方法(RPMを使わない方法) $ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin ここで--with-mysql-sourceにはMySQLのソースコードのトップディレク -トリを指定します。--with-mysql-bindirにはインストール済みのMySQL +トリを指定します(そこにVERSIONファイルかconfigure.inファイルがなく +てはなりません)。--with-mysql-bindirにはインストール済みのMySQL のmysql_configコマンドが有るディレクトリを指定します。 その後以下のようにビルド・インストールします。 diff --git a/plugin/handler_socket/docs-ja/perl-client.ja.txt b/plugin/handler_socket/docs-ja/perl-client.ja.txt index 5d3adfa3301..90b7e4d6fd8 100644 --- a/plugin/handler_socket/docs-ja/perl-client.ja.txt +++ b/plugin/handler_socket/docs-ja/perl-client.ja.txt @@ -86,7 +86,6 @@ execute_singleメソッドは列の挿入にも使用できます。 my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]); die $hs->get_error() if $res->[0] != 0; - my $num_inserted_rows = $res->[1]; 第3引数は、対応するopen_index呼び出しの第5引数の列リストと同じだ けの長さの配列への参照でなければなりません。open_index呼び出しの @@ -109,6 +108,15 @@ execute_multiメソッドを使えば、複数のリクエストを一つの呼 # ... } +----------------------------------------------------------------- +もしhandlersocketが接続を認証するように設定されている +(handlersocket_plain_secret又はhandlersocket_plain_secret_wrがセッ +トされている)ならば、クライアントは他のメソッド呼び出しの前にauth +メソッドを呼び出す必要があります。 + + my $res = $hs->auth('password'); + die $hs->get_error() if $res->[0] != 0; + ----------------------------------------------------------------- エラーが起こると返値の配列参照の最初の要素が0以外になります。負の 数の場合はI/Oエラーが起こったことを示し、その場合はその diff --git a/plugin/handler_socket/docs-ja/protocol.ja.txt b/plugin/handler_socket/docs-ja/protocol.ja.txt index 01c9d39f71f..46cc9932e60 100644 --- a/plugin/handler_socket/docs-ja/protocol.ja.txt +++ b/plugin/handler_socket/docs-ja/protocol.ja.txt @@ -1,94 +1,180 @@ ------------------------------------------------------------------ +---------------------------------------------------------------------------- handlersocketの通信プロトコル ------------------------------------------------------------------ -構文 +---------------------------------------------------------------------------- +基本的な構文 -・コマンド行は改行(LF)で終わる。 -・コマンド行は複数のトークンからなり、トークン間はTABで区切られる。 +・HandlerSocketのプロトコルは行ベース。各行は改行文字(0x0a)で終わる。 +・各行は複数のトークンからなり、トークン間はTAB文字(0x09)で区切られる。 ・トークンはNULLトークンか、文字列トークンのいずれか。 -・NULLトークンは単一のNUL文字であらわされる。 -・文字列トークンは、0バイト以上の文字列であらわされる。ただし0x10 - 未満の文字については0x01を前置し、0x40を加えたコードであらわさ - れる。それ以外の文字はその文字自身のコードであらわされる。 +・NULLトークンは単一のNUL文字(0x00)であらわされる。 +・文字列トークンは、0バイト以上の文字列であらわされる。ただし0x10未満の文字 + については0x01を前置し、0x40を加えたコードであらわされる。それ以外の文字は + その文字自身のコードであらわされる。 ------------------------------------------------------------------ +---------------------------------------------------------------------------- リクエストとレスポンス -・接続が確立した直後の状態では、まずクライアントがコマンド行を送 - る。(リクエスト) -・サーバはクライアントが送ったリクエストと丁度同じ数のコマンド行 - を返す。(レスポンス) -・リクエストはパイプライン化してよい。つまりクライアントは前に - 送ったリクエストに対する返事を待たずに次のリクエストを送っても - よい。 +・HandlerSocketのプロトコルは単純なリクエスト・レスポンスプロトコルになって + いる。接続が確立した後は、まずクライアントがリクエストを送る。 +・サーバは、クライアントが送ったリクエストと丁度同じ数の行(レスポンス)を返 + す。 +・リクエストはパイプライン化してよい。つまりクライアントは前に送ったリクエス + トに対する返事(レスポンス)を待たずに次のリクエストを送ってもよい。 ------------------------------------------------------------------ -リクエスト +---------------------------------------------------------------------------- +インデックスを開く -・open_index命令は次のような構文を持つ。 - 'P' indexid dbname tablename indexname fieldlist - indexidは開いている索引に付けられる番号で、同一接続上で後に実行 - する命令の、対象索引を指定するために使われる。dbname、tablename、 - indexnameはそれぞれ開きたいDB、テーブル、索引の名前。索引の名前 - として"PRIMARY"を指定するとプライマリキーが開かれる。fieldlist - はカンマ区切りの列名のリスト。 -・find命令は次のような構文を持つ。 - indexid op nflds v1 ... vn limit offset - indexidは実行対象の索引を指定する。opは索引検索の演算子(後述)。 - v1からvnは可変長で、その個数はnflds。nfldsはindexidで指定された - open_index命令のindexnameの索引のfieldlistのフィールド数に等し - いか小さくなくてはならない。m2からmkは可変長で、その個数は - indexidで指定されたopen_index命令が発行された際のfieldlistに一 - 致しなければならない。コマンド行のlimit以降は省略できる。limit - とoffsetは、検索条件に合致する列のうちレスポンスに返す列数の上 - 限と、スキップする列数。limitとoffsetを省略した場合はそれぞれ1 - と0が指定されたときと同じ動作をする。find命令はレスポンスとして、 - 条件に合致した列のリストを返す。opとして指定できる演算子は次の - とおり。 - '=' - v1 ... vnと一致するものを取得 - '>' - v1 ... vnより大きいものを昇順に取得 - '>=' - v1 ... vnに一致するか大きいものを昇順に取得 - '<' - v1 ... vnより小さいものを降順に取得 - '<=' - v1 ... vnに一致するか等しいものを降順に取得 - nfldsが1より大きい(v1 ... vnが2個以上)ときは辞書式順序で比較さ - れる。 -・find_modify命令は次のような構文を持つ。 - indexid op nflds v1 ... vn limit offset modop m1 ... mk - modopより前の部分はfind命令と同等で、これによって操作対象の行を - 指定する。その操作対象の行に対しmodopで指定された変更処理を実行 - する。m1 ... mkは可変長で、省略できる。modopは次いずれか。 - 'U' - indexidで指定されたopen_index命令のfieldlist列 - の内容を、m1 ... mkの値で更新する。 - 'D' - 対象の行を削除する。m1 ... mkの値は無視される。 -・insert命令はのような構文を持つ。 - indexid '+' nflds v1 ... vn - indexidで指定されたテーブルに、列を挿入する。v1 ... vnは可変長 - で、その個数はnflds。nfldsはindexidで指定されたopen_index命令の - indexnameの索引のfieldlistのフィールド数に等しいか小さくなくて - はならない。 +open_index命令は次のような構文を持つ。 ------------------------------------------------------------------ -レスポンス + P [] -・open_index命令が成功したとき、レスポンスは次の構文を持つ。 - '0' '1' -・find命令が成功したとき、レスポンスは次の構文を持つ。 - '0' nflds v1 ... vn - nfldsは結果セットの列の数をあらわす。v1 ... vnは可変長で、その - 長さはnfldsの整数倍。v1 ... vnは空のこともあり、それは条件に合 - 致するレコードが存在しなかったことをあらわす。結果セットが複数 - 行になったときはv1 ... vnの長さがnfldsの2倍以上となり、最初の - 行から順にv1 ... vnにセットされる。 -・modify命令が成功したとき、レスポンスは次の構文を持つ。 - '0' '1' nummod - nummodは変更が施された行数。nummodが0のときは変更された行が無 - かったことをあらわす。 -・insert命令が成功したとき、レスポンスは次の構文を持つ。 - '0' '1' -・命令が失敗したとき、レスポンスは命令に関わらず次の構文を持つ。 - err '1' message - errは0以外の数値で、エラーコードをあらわす。messageは人間可読な - エラーメッセージ。ただしmessageが無いこともある。 +- は数字で、同一接続上で後に実行する命令の、対象索引を指定するため + に使われる。 +- , , は文字列で、それぞれDB名、テーブル名、 + 索引の名前を指定する。として「PRIMARY」を指定するとプライマリ + キーが開かれる。 +- はカンマ区切りの列名のリスト。 +- はカンマ区切りの列名のリスト。これは省略することができる。 + +このopen_index命令が実行されると、HandlerSocketプラグインは指定されたDB、 +テーブル、索引を開く。開かれた索引は接続が閉じられるまで開かれたままになる。 +開かれた索引はの数字で識別される。もし既にに指定された番号 +の索引が既に開かれている場合は古いほうが閉じられる。このはなるべく +小さな数字を使ったほうが効率が良い。 + +---------------------------------------------------------------------------- +データ取得 + +find命令は次のような構文を持つ。 + + ... [LIM] [IN] [FILTER ...] + +LIMは次のようなパラメータの並び + + + +INは次のようなパラメータの並び + + @ ... + +FILTERは次のようなパラメータの並び + + + +- は数字で、これは同じ接続上で過去に実行したopen_index命令に指定さ + れた数字でなければならない。 +- は比較演算子で、現在のバージョンでは '=', '>', '>=', '<', '<=' をサ + ポートしている。 +- は後に続くパラメータ ... の長さ。この値は対応するopen_index + 命令のパラメータで指定された索引のキー列の数と同じか小さいもの + でなければならない。 +- ... は取得するべきキーの値を指定するパラメータ。 +- LIMは省略できる。は数字で、これはSQLのLIMITと同じように + はたらく。省略した場合は1と0を指定した場合と同じ動作をする。FILTERによっ + て読み飛ばされたレコードはにカウントされない。 +- INは省略できる。指定されると、これはSQLの WHERE ... IN のように動作する。 + は対応するopen_index命令のパラメータで指定された索引の + キー列の数より小さいものでなければならない。INが指定されたときは、find命 + 令の ... のうち番目の値は無視される。 +- FILTERは省略できる。これは行取得の際のフィルタを指定する。は + 'F'(filter)か'W'(while)のいずれかでなければならない。は比較演算子。 + は数字で、これは対応するopen_index命令ので指定された列の + 数より小さいものでなければならない。複数のフィルタを指定することもでき、 + その場合は各フィルタのANDと解釈される。'F'と'W'の違いは、条件にあてはま + らない行があったときに'F'は単にそれをスキップするが、'W'はその時点でルー + プを抜けるという点。 + +---------------------------------------------------------------------------- +更新と削除 + +find_modify命令は次のような構文を持つ。 + + ... [LIM] [IN] [FILTER ...] MOD + +MODは次のようなパラメータの並び + + ... + +- は'U', '+', '-', 'D', 'U?', '+?', '-?', 'D?'のいずれか。'?'が付いた + ものは付いていないものとほぼ同じ動作をするが、付いていないものがレスポン + スとして更新された行の数を返すのに対し、付いているものは更新される前の行 + の内容を返す点のみが異なる。'U'は更新、'D'は削除、'+'はインクリメント、 + '-'はデクリメントを実行する。 +- ... はセットされる各列の値。 ... の長さは対応する + open_index命令のの長さと等しいか小さくなければならない。が + 'D'のときはこれらのパラメータは無視される。が'+'か'-'のときは、これら + の値は数値でなければならない。が'-'で、それが負数から正数、または正数 + から負数へ列の値を変更するようなものであった場合は、値は変更されない。 + +---------------------------------------------------------------------------- +行の挿入 + +insert命令は次のような構文を持つ。 + + + ... + +- は後に続くパラメータ ... の長さ。これは対応するopen_indexの + の長さに等しいか小さくなければならない。 +- ... はセットされる各列の値。指定されないかった列についてはその列 + のデフォルト値がセットされる。 + +---------------------------------------------------------------------------- +認証 + +auth命令は次のような構文を持つ。 + + A + +- は現在のバージョンでは'1'のみが有効。 +- 指定されたが、サーバの設定の'handlersocket_plain_secret'や + 'handlersocket_plain_secret_wr'に指定された文字列と一致した場合にのみ認証 + は成功する。 +- HandlerSocketの認証が有効になっているときは、この'auth'が成功しない限りそ + れ以外の命令は全て失敗する。 + +---------------------------------------------------------------------------- +open_indexに対するレスポンス + +open_index命令が成功したとき、レスポンスは次の構文を持つ。 + + 0 1 + +---------------------------------------------------------------------------- +findに対するレスポンス + +find命令が成功したとき、レスポンスは次の構文を持つ。 + + 0 ... + +- はfind命令の対応するopen_index命令に指定したの長さに + 一致する。 +- ... は結果セット。もしN行がfind命令で見つかったなら、 ... + の長さは ( * N )になる。 + +---------------------------------------------------------------------------- +find_modifyに対するレスポンス + +find_modify命令が成功したとき、レスポンスは次の構文を持つ。 + + 0 1 + +- は変更された行の数。 +- 例外として、が'?'の付いたものであった場合には、find命令に対するレスポ + ンスと同じ構文のレスポンスを返す。 + +---------------------------------------------------------------------------- +insertに対するレスポンス + +insert命令が成功したとき、レスポンスは次の構文を持つ。 + + 0 1 + +---------------------------------------------------------------------------- +authに対するレスポンス + +auth命令が成功したとき、レスポンスは次の構文を持つ。 + + 0 1 diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp index 311eec55fa8..beb28ef708c 100644 --- a/plugin/handler_socket/handlersocket/database.cpp +++ b/plugin/handler_socket/handlersocket/database.cpp @@ -658,7 +658,7 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst, empty_record(table); memset(buf, 0, table->s->null_bytes); /* clear null flags */ const prep_stmt::fields_type& rf = pst.get_ret_fields(); - const size_t n = rf.size(); + const size_t n = std::min(rf.size(), fvalslen); for (size_t i = 0; i < n; ++i) { uint32_t fn = rf[i]; Field *const fld = table->field[fn]; diff --git a/plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs b/plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs index 8e8d2520337..04dab6d0a68 100644 --- a/plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs +++ b/plugin/handler_socket/perl-Net-HandlerSocket/HandlerSocket.xs @@ -151,7 +151,7 @@ sv_get_string_ref(SV *sv) static IV sv_get_iv(SV *sv) { - if (sv == 0 || !SvIOK(sv)) { + if (sv == 0 || ( !SvIOK(sv) && !SvPOK(sv) ) ) { return 0; } return SvIV(sv); diff --git a/plugin/handler_socket/regtest/test_01_lib/run.sh b/plugin/handler_socket/regtest/test_01_lib/run.sh index 8514612832f..84603d65a57 100755 --- a/plugin/handler_socket/regtest/test_01_lib/run.sh +++ b/plugin/handler_socket/regtest/test_01_lib/run.sh @@ -1,6 +1,6 @@ #!/bin/bash -TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23"; +TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24"; source ../common/compat.sh diff --git a/plugin/handler_socket/regtest/test_01_lib/test14.pl b/plugin/handler_socket/regtest/test_01_lib/test14.pl index 68ce87bdd63..ff4e433ae8f 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test14.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test14.pl @@ -27,7 +27,7 @@ srand(999); my %valmap = (); -my $sth = $dbh->prepare("insert into $table values (?,?,?)"); +my $sth = $dbh->prepare("insert ignore into $table values (?,?,?)"); for (my $i = 0; $i < $tablesize; ++$i) { my $k = $i; my ($s1, $s2) = ("", ""); diff --git a/plugin/handler_socket/regtest/test_01_lib/test17.pl b/plugin/handler_socket/regtest/test_01_lib/test17.pl index b7861b880f5..1ffd7fa1242 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test17.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test17.pl @@ -60,7 +60,7 @@ sub test_one { $dbh->do( "create table $table (" . "k $typ, " . - "v1 varchar(2047), " . + "v1 varchar(1000), " . "v2 $typ, " . "primary key(k$keylen_str), " . "index i1(v1), index i2(v2$keylen_str, v1(300))) " . diff --git a/plugin/handler_socket/regtest/test_01_lib/test19.pl b/plugin/handler_socket/regtest/test_01_lib/test19.pl index 6c43267c927..9870199c1a7 100644 --- a/plugin/handler_socket/regtest/test_01_lib/test19.pl +++ b/plugin/handler_socket/regtest/test_01_lib/test19.pl @@ -113,7 +113,7 @@ sub test_one { "(k1 int not null, k2 int not null, " . "v1 int not null, v2 $typ default null, " . "primary key (k1, k2) ) engine = innodb"); - my $sth = $dbh->prepare("insert into $table values (?,?,?,?)"); + my $sth = $dbh->prepare("insert ignore into $table values (?,?,?,?)"); for (my $i = 0; $i < $tablesize; ++$i) { my $j = 0; for my $v (@$values) { diff --git a/plugin/handler_socket/regtest/test_01_lib/test24.expected b/plugin/handler_socket/regtest/test_01_lib/test24.expected new file mode 100644 index 00000000000..5d07e01bb92 --- /dev/null +++ b/plugin/handler_socket/regtest/test_01_lib/test24.expected @@ -0,0 +1,2 @@ +HS +0 0 diff --git a/plugin/handler_socket/regtest/test_01_lib/test24.pl b/plugin/handler_socket/regtest/test_01_lib/test24.pl new file mode 100644 index 00000000000..6cd95a995e5 --- /dev/null +++ b/plugin/handler_socket/regtest/test_01_lib/test24.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +# vim:sw=2:ai + +# test for issue #78 + +BEGIN { + push @INC, "../common/"; +}; + +use strict; +use warnings; +use hstest; + +my $dbh = hstest::init_testdb(); +my $table = 'hstesttbl'; +my $tablesize = 100; +$dbh->do( + "create table $table (" . + "id bigint(20) not null auto_increment, " . + "t1 timestamp not null default current_timestamp, " . + "primary key (id)" . + ") engine = innodb"); +srand(999); + +my %valmap = (); + +my $hs = hstest::get_hs_connection(undef, 9999); +my $dbname = $hstest::conf{dbname}; +$hs->open_index(0, $dbname, $table, 'PRIMARY', 'id,t1'); +my $res = $hs->execute_single(0, '+', [ 321 ], 0, 0); +die $hs->get_error() if $res->[0] != 0; +print "HS\n"; +print join(' ', @$res) . "\n"; + From 9fae9930244d505585d83590051a17df9bab7d8a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 May 2013 19:52:21 +0200 Subject: [PATCH 05/10] MDEV-26: Global transaction ID. Implement START SLAVE UNTIL master_gtid_pos = "". Add test cases, including a test showing how to use this to promote a new master among a set of slaves. --- mysql-test/include/rpl_init.inc | 1 + .../rpl/r/rpl_gtid_master_promote.result | 367 +++++++++++ mysql-test/suite/rpl/r/rpl_gtid_until.result | 225 +++++++ .../suite/rpl/t/rpl_gtid_master_promote.cnf | 35 ++ .../suite/rpl/t/rpl_gtid_master_promote.test | 267 ++++++++ mysql-test/suite/rpl/t/rpl_gtid_until.test | 234 +++++++ sql/lex.h | 3 +- sql/log.cc | 11 +- sql/log_event.cc | 88 ++- sql/log_event.h | 19 +- sql/rpl_gtid.cc | 25 +- sql/rpl_gtid.h | 2 + sql/rpl_rli.cc | 3 +- sql/rpl_rli.h | 8 +- sql/share/errmsg-utf8.txt | 2 + sql/slave.cc | 82 ++- sql/sql_lex.h | 4 + sql/sql_repl.cc | 589 ++++++++++++++---- sql/sql_yacc.yy | 10 +- 19 files changed, 1826 insertions(+), 149 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_master_promote.result create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_until.result create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_master_promote.test create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_until.test diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index e608a1223a5..939a05d8011 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -178,6 +178,7 @@ while ($_rpl_server) { RESET MASTER; RESET SLAVE; + SET GLOBAL gtid_pos= ""; } eval SET auto_increment_increment= $rpl_server_count; eval SET auto_increment_offset= $_rpl_server; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result new file mode 100644 index 00000000000..1f600b2a536 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result @@ -0,0 +1,367 @@ +include/rpl_init.inc [topology=1->2, 1->3, 1->4, 1->5] +ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) +RETURNS VARCHAR(100) DETERMINISTIC +BEGIN +SET s= CONCAT(",", s, ","); +SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); +SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); +RETURN s; +END| +include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; +include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; +include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; +include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; +SET gtid_domain_id= 1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t4 VALUES (1, 1); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t4 VALUES (1, 3); +SET gtid_domain_id= 2; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t4 VALUES (2, 1); +INSERT INTO t2 VALUES (3); +INSERT INTO t2 VALUES (4); +INSERT INTO t4 VALUES (2, 3); +SET gtid_domain_id= 3; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +INSERT INTO t4 VALUES (3, 1); +INSERT INTO t3 VALUES (3); +INSERT INTO t3 VALUES (4); +INSERT INTO t4 VALUES (3, 3); +START SLAVE UNTIL master_gtid_pos= "1-1-7,2-1-14,3-1-21"; +START SLAVE UNTIL master_gtid_pos= "1-1-4,2-1-14,3-1-24"; +START SLAVE UNTIL master_gtid_pos= "2-1-11,3-1-21,1-1-10"; +START SLAVE UNTIL master_gtid_pos= "3-1-18,1-1-7,2-1-17"; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +2 1 +3 1 +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +SELECT * FROM t2 ORDER BY a; +a +1 +2 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t4 ORDER BY a,b; +a b +2 1 +3 1 +3 3 +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t2 ORDER BY a; +a +SELECT * FROM t3 ORDER BY a; +a +1 +2 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +3 1 +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t3 ORDER BY a; +a +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +2 1 +2 3 +*** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. *** +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3; +START SLAVE UNTIL master_gtid_pos = "1-1-4,0-1-3,3-1-24,2-1-14"; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +2 1 +3 1 +3 3 +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4; +START SLAVE UNTIL master_gtid_pos = "1-1-10,0-1-3,3-1-21,2-1-11"; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +2 1 +3 1 +3 3 +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_5; +START SLAVE UNTIL master_gtid_pos = "1-1-7,0-1-3,3-1-18,2-1-17"; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +2 1 +2 3 +3 1 +3 3 +*** Now make 2 master and point 3,4,5 to the new master 2 +SET gtid_domain_id= 1; +INSERT INTO t1 values (5); +INSERT INTO t4 values (1,5); +SET gtid_domain_id= 2; +INSERT INTO t2 values (5); +INSERT INTO t4 values (2,5); +SET gtid_domain_id= 3; +INSERT INTO t3 values (5); +INSERT INTO t4 values (3,5); +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2; +include/start_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2; +include/start_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2; +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +1 5 +2 1 +2 3 +2 5 +3 1 +3 3 +3 5 +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +1 5 +2 1 +2 3 +2 5 +3 1 +3 3 +3 5 +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +1 5 +2 1 +2 3 +2 5 +3 1 +3 3 +3 5 +*** Now let the old master join up as slave. *** +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2, +master_user = "root", master_use_gtid = 1; +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t3 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t4 ORDER BY a,b; +a b +1 1 +1 3 +1 5 +2 1 +2 3 +2 5 +3 1 +3 3 +3 5 +*** Finally move things back and clean up. *** +include/stop_slave.inc +RESET SLAVE ALL; +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1; +include/start_slave.inc +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1; +include/start_slave.inc +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1; +include/start_slave.inc +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1; +include/start_slave.inc +SET gtid_domain_id = 0; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +DROP FUNCTION extract_gtid; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_until.result b/mysql-test/suite/rpl/r/rpl_gtid_until.result new file mode 100644 index 00000000000..382da1b3844 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_until.result @@ -0,0 +1,225 @@ +include/rpl_init.inc [topology=1->2] +ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) +RETURNS VARCHAR(100) DETERMINISTIC +BEGIN +SET s= CONCAT(",", s, ","); +SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); +SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); +RETURN s; +END| +START SLAVE UNTIL master_gtid_pos = ""; +ERROR HY000: Slave is already running +include/stop_slave_io.inc +START SLAVE UNTIL master_gtid_pos = ""; +ERROR HY000: Slave is already running +START SLAVE IO_THREAD; +include/wait_for_slave_io_to_start.inc +include/stop_slave_sql.inc +START SLAVE UNTIL master_gtid_pos = ""; +ERROR HY000: Slave is already running +include/stop_slave_io.inc +START SLAVE UNTIL master_gtid_pos = ""; +ERROR HY000: START SLAVE UNTIL master_gtid_pos requires that slave is using GTID +CHANGE MASTER TO master_use_gtid=1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +START SLAVE UNTIL master_gtid_pos = "0-1-100,1-1-100,2-2-200,1-3-100,4-4-400"; +ERROR HY000: GTID 1-3-100 and 1-1-100 conflict (duplicate domain id 1) +START SLAVE UNTIL master_log_file = "master-bin.000001", master_log_pos = 4, master_gtid_pos = ""; +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 'master_gtid_pos = ""' at line 1 +START SLAVE IO_THREAD UNTIL master_gtid_pos = ""; +ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL +START SLAVE SQL_THREAD UNTIL master_gtid_pos = ""; +ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL +START SLAVE UNTIL master_gtid_pos = '0-1-4'; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1; +a +1 +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +include/stop_slave.inc +START SLAVE UNTIL master_gtid_pos = "1-10-100,2-20-200"; +include/wait_for_slave_to_start.inc +Using_Gtid = '1' +Until_Condition = 'Gtid' +include/stop_slave.inc +include/start_slave.inc +*** Test UNTIL condition in an earlier binlog than the start GTID. *** +include/stop_slave.inc +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (3); +SET gtid_domain_id = 2; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (3); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (4); +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (4); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (5); +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (5); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (6); +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (6); +SET gtid_domain_id = 0; +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +master-bin.000003 # +master-bin.000004 # +START SLAVE UNTIL master_gtid_pos='1-1-11,2-1-12'; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +SELECT * FROM t2 ORDER BY a; +a +3 +4 +5 +START SLAVE UNTIL master_gtid_pos='1-1-13,2-1-8'; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +SELECT * FROM t2 ORDER BY a; +a +3 +4 +5 +START SLAVE UNTIL master_gtid_pos='1-1-11'; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +SELECT * FROM t2 ORDER BY a; +a +3 +4 +5 +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +SELECT * FROM t2 ORDER BY a; +a +3 +4 +5 +6 +*** Test when the UNTIL position is right at the end of the binlog file prior to the starting position *** +include/stop_slave.inc +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (7); +SET gtid_domain_id = 0; +START SLAVE UNTIL master_gtid_pos='1-1-13'; +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +*** Test when UNTIL condition is after a stand-alone event (not a transaction). *** +include/stop_slave.inc +CREATE TABLE t3 (a INT); +DROP TABLE t3; +START SLAVE UNTIL master_gtid_pos='1-1-15,0-1-16,2-1-14'; +include/wait_for_slave_to_stop.inc +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +include/start_slave.inc +*** Test UNTIL condition that has not yet been logged. *** +include/stop_slave.inc +RESET SLAVE ALL; +RESET MASTER; +SET GLOBAL gtid_pos=''; +RESET MASTER; +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +DELETE FROM t1 WHERE a >= 10; +RESET MASTER; +INSERT INTO t1 VALUES (10); +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, +master_user = "root", master_use_gtid = 1; +START SLAVE UNTIL master_gtid_pos = '0-1-2'; +include/wait_for_slave_to_start.inc +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +10 +11 +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +10 +11 +12 +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION extract_gtid; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf new file mode 100644 index 00000000000..4eafa897501 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf @@ -0,0 +1,35 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.3] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.4] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.5] +log-slave-updates +skip-slave-start +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket + +SERVER_MYPORT_5= @mysqld.5.port +SERVER_MYSOCK_5= @mysqld.5.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test new file mode 100644 index 00000000000..68935011c20 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test @@ -0,0 +1,267 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2, 1->3, 1->4, 1->5 +--source include/rpl_init.inc + +# Set up a topology with one master and 4 slaves. +# +# Replicate some events leaving the four slaves at different points +# in different domains. +# +# Then promote one slave as new master, bringing it ahead of all others +# using START SLAVE UNTIL master_gtid_pos. + +--connection server_1 +ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB; + +# Function to extract one GTID from a list. +delimiter |; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) + RETURNS VARCHAR(100) DETERMINISTIC +BEGIN + SET s= CONCAT(",", s, ","); + SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); + SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); + RETURN s; +END| +delimiter ;| + +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; + +--connection server_3 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; + +--connection server_4 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; + +--connection server_5 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=1; + + +# Create three separate replication streams on master server_1. +# +# Then use START SLAVE UNTIL to get the different streams interleaved +# differently spread over multiple binlogs on the different slaves, to +# test that new master promotion is able to deal with this. + +--connection server_1 + +SET gtid_domain_id= 1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d1_begin= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t4 VALUES (1, 1); +--let $d1_mid= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t4 VALUES (1, 3); +--let $d1_end= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` + +SET gtid_domain_id= 2; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d2_begin= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t4 VALUES (2, 1); +--let $d2_mid= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +INSERT INTO t2 VALUES (3); +INSERT INTO t2 VALUES (4); +INSERT INTO t4 VALUES (2, 3); +--let $d2_end= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` + +SET gtid_domain_id= 3; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d3_begin= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +INSERT INTO t4 VALUES (3, 1); +--let $d3_mid= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` +INSERT INTO t3 VALUES (3); +INSERT INTO t3 VALUES (4); +INSERT INTO t4 VALUES (3, 3); +--let $d3_end= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` + + +# Slave server_2 (that will be promoted to master) is in the middle +# of each stream. +--connection server_2 +eval START SLAVE UNTIL master_gtid_pos= "$d1_mid,$d2_mid,$d3_mid"; + +# The remaining slaves sit at different points each in different domains. +--connection server_3 +eval START SLAVE UNTIL master_gtid_pos= "$d1_begin,$d2_mid,$d3_end"; +--connection server_4 +eval START SLAVE UNTIL master_gtid_pos= "$d2_begin,$d3_mid,$d1_end"; +--connection server_5 +eval START SLAVE UNTIL master_gtid_pos= "$d3_begin,$d1_mid,$d2_end"; +--connection server_2 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_3 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_4 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. *** + +--connection server_3 +--let $server3_pos= `SELECT @@GLOBAL.gtid_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3; +eval START SLAVE UNTIL master_gtid_pos = "$server3_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--connection server_4 +--let $server4_pos= `SELECT @@GLOBAL.gtid_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4; +eval START SLAVE UNTIL master_gtid_pos = "$server4_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--connection server_5 +--let $server5_pos= `SELECT @@GLOBAL.gtid_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_5 SERVER_MYPORT_5 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_5; +eval START SLAVE UNTIL master_gtid_pos = "$server5_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--echo *** Now make 2 master and point 3,4,5 to the new master 2 +--connection server_2 +SET gtid_domain_id= 1; +INSERT INTO t1 values (5); +INSERT INTO t4 values (1,5); +SET gtid_domain_id= 2; +INSERT INTO t2 values (5); +INSERT INTO t4 values (2,5); +SET gtid_domain_id= 3; +INSERT INTO t3 values (5); +INSERT INTO t4 values (3,5); + +--connection server_3 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc +--connection server_4 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc +--connection server_5 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc + +--connection server_2 +--save_master_pos + +--connection server_3 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Now let the old master join up as slave. *** +--connection server_1 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + master_user = "root", master_use_gtid = 1; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Finally move things back and clean up. *** +--connection server_1 +--source include/stop_slave.inc +RESET SLAVE ALL; + +--connection server_2 +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_3 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_4 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_5 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc + +--connection server_1 +SET gtid_domain_id = 0; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +DROP FUNCTION extract_gtid; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_until.test b/mysql-test/suite/rpl/t/rpl_gtid_until.test new file mode 100644 index 00000000000..3b6e238f225 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_until.test @@ -0,0 +1,234 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +# Function to extract one GTID from a list. +delimiter |; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) + RETURNS VARCHAR(100) DETERMINISTIC +BEGIN + SET s= CONCAT(",", s, ","); + SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); + SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); + RETURN s; +END| +delimiter ;| +--save_master_pos + +--connection server_2 +--sync_with_master + +# Both replication threads must be stopped for UNTIL master_gtid_pos. +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +--source include/stop_slave_io.inc +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +--source include/stop_slave_sql.inc +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +--source include/stop_slave_io.inc +# UNTIL master_gtid_pos only valid if GTID is used. + +--error ER_UNTIL_REQUIRES_USING_GTID +START SLAVE UNTIL master_gtid_pos = ""; + +CHANGE MASTER TO master_use_gtid=1; + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +--let $gtid_pos=`SELECT @@GLOBAL.gtid_pos` +INSERT INTO t1 VALUES(2); + +--connection server_2 + +# Test various incorrect syntax for UNTIL master_gtid_pos. +--error ER_DUPLICATE_GTID_DOMAIN +START SLAVE UNTIL master_gtid_pos = "0-1-100,1-1-100,2-2-200,1-3-100,4-4-400"; +--error ER_PARSE_ERROR +START SLAVE UNTIL master_log_file = "master-bin.000001", master_log_pos = 4, master_gtid_pos = ""; +--error ER_BAD_SLAVE_UNTIL_COND +START SLAVE IO_THREAD UNTIL master_gtid_pos = ""; +--error ER_BAD_SLAVE_UNTIL_COND +START SLAVE SQL_THREAD UNTIL master_gtid_pos = ""; + +eval START SLAVE UNTIL master_gtid_pos = '$gtid_pos'; + +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1; + +--source include/start_slave.inc + +--connection server_1 +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Test showing the UNTIL condition in SHOW SLAVE STATUS. +--source include/stop_slave.inc +START SLAVE UNTIL master_gtid_pos = "1-10-100,2-20-200"; +--source include/wait_for_slave_to_start.inc +--let $status_items= Using_Gtid,Until_Condition +--source include/show_slave_status.inc + +# Clear the UNTIL condition. +--source include/stop_slave.inc +--source include/start_slave.inc + + +--echo *** Test UNTIL condition in an earlier binlog than the start GTID. *** +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (3); +SET gtid_domain_id = 2; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (3); +--let $d1_point1= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d2_point1= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (4); +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (4); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (5); +--let $d1_point2= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d2_point2= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (5); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (6); +--let $d1_point3= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d2_point3= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (6); +SET gtid_domain_id = 0; +--source include/show_binary_logs.inc +--save_master_pos + +--connection server_2 +# Let the slave reach an middle point in domain 1 and a late point in domain 2. +eval START SLAVE UNTIL master_gtid_pos='$d1_point2,$d2_point3'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +# Now test starting at a middle point in the binlogs when the stop position in +# one domain (domain 2) is early. +eval START SLAVE UNTIL master_gtid_pos='$d1_point3,$d2_point1'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +# Test that one UNTIL domain empty means stop that domain immediately. +eval START SLAVE UNTIL master_gtid_pos='$d1_point2'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Test when the UNTIL position is right at the end of the binlog file prior to the starting position *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (7); +SET gtid_domain_id = 0; +--save_master_pos + +--connection server_2 +eval START SLAVE UNTIL master_gtid_pos='$d1_point3'; +--source include/wait_for_slave_to_stop.inc +# This should not show row 7, as we requested stop just before it. +SELECT * FROM t1 ORDER BY a; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test when UNTIL condition is after a stand-alone event (not a transaction). *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +CREATE TABLE t3 (a INT); +--let $until_condition=`SELECT @@GLOBAL.gtid_pos` +DROP TABLE t3; +--save_master_pos + +--connection server_2 +eval START SLAVE UNTIL master_gtid_pos='$until_condition'; +--source include/wait_for_slave_to_stop.inc +SHOW CREATE TABLE t3; +--source include/start_slave.inc +--sync_with_master + +--echo *** Test UNTIL condition that has not yet been logged. *** + +--connection server_2 +--source include/stop_slave.inc +RESET SLAVE ALL; +RESET MASTER; +SET GLOBAL gtid_pos=''; + +--connection server_1 +# Do it once to compute the right GTID, then throw it away and do it again +# for the actual test. +RESET MASTER; +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +--let $until_condition=`SELECT @@GLOBAL.gtid_pos` +INSERT INTO t1 VALUES (12); +DELETE FROM t1 WHERE a >= 10; + +RESET MASTER; +INSERT INTO t1 VALUES (10); + +--connection server_2 +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + master_user = "root", master_use_gtid = 1; +eval START SLAVE UNTIL master_gtid_pos = '$until_condition'; +--source include/wait_for_slave_to_start.inc + +--connection server_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +--save_master_pos + +--connection server_2 +# This then should wait until it gets the row (11) and then stop, not +# yet having the row (12). +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +--source include/start_slave.inc +--sync_with_master +# And now the row (12) should be there. +SELECT * FROM t1 ORDER BY a; + + +# Clean up. +--connection server_1 +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION extract_gtid; + +--source include/rpl_end.inc diff --git a/sql/lex.h b/sql/lex.h index edf833021b0..756e7e80f7e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -330,7 +330,7 @@ static SYMBOL symbols[] = { { "LOW_PRIORITY", SYM(LOW_PRIORITY)}, { "MASTER", SYM(MASTER_SYM)}, { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)}, - { "MASTER_USE_GTID", SYM(MASTER_USE_GTID_SYM)}, + { "MASTER_GTID_POS", SYM(MASTER_GTID_POS_SYM)}, { "MASTER_HOST", SYM(MASTER_HOST_SYM)}, { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM)}, { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM)}, @@ -345,6 +345,7 @@ static SYMBOL symbols[] = { { "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM)}, { "MASTER_SSL_VERIFY_SERVER_CERT", SYM(MASTER_SSL_VERIFY_SERVER_CERT_SYM)}, { "MASTER_USER", SYM(MASTER_USER_SYM)}, + { "MASTER_USE_GTID", SYM(MASTER_USE_GTID_SYM)}, { "MASTER_HEARTBEAT_PERIOD", SYM(MASTER_HEARTBEAT_PERIOD_SYM)}, { "MATCH", SYM(MATCH)}, { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)}, diff --git a/sql/log.cc b/sql/log.cc index c0cd4be8a45..3266934beda 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3280,7 +3280,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, there had been an entry (domain_id, server_id, 0). */ - Gtid_list_log_event gl_ev(&rpl_global_gtid_binlog_state); + Gtid_list_log_event gl_ev(&rpl_global_gtid_binlog_state, 0); if (gl_ev.write(&log_file)) goto err; @@ -8718,16 +8718,11 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name, case GTID_LIST_EVENT: if (first_round) { - uint32 i; Gtid_list_log_event *glev= (Gtid_list_log_event *)ev; /* Initialise the binlog state from the Gtid_list event. */ - rpl_global_gtid_binlog_state.reset(); - for (i= 0; i < glev->count; ++i) - { - if (rpl_global_gtid_binlog_state.update(&(glev->list[i]))) - goto err2; - } + if (rpl_global_gtid_binlog_state.load(glev->list, glev->count)) + goto err2; } break; diff --git a/sql/log_event.cc b/sql/log_event.cc index aa86fa6ff62..9fbcbb68145 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6320,6 +6320,7 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len, : Log_event(buf, description_event), count(0), list(0) { uint32 i; + uint32 val; uint8 header_size= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[GTID_LIST_EVENT-1]; if (event_len < header_size + post_header_len || @@ -6327,7 +6328,9 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len, return; buf+= header_size; - count= uint4korr(buf) & ((1<<28)-1); + val= uint4korr(buf); + count= val & ((1<<28)-1); + gl_flags= val & ((uint32)0xf << 28); buf+= 4; if (event_len - (header_size + post_header_len) < count*element_size || (!(list= (rpl_gtid *)my_malloc(count*sizeof(*list) + (count == 0), @@ -6348,8 +6351,9 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len, #ifdef MYSQL_SERVER -Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set) - : count(gtid_set->count()), list(0) +Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set, + uint32 gl_flags_) + : count(gtid_set->count()), gl_flags(gl_flags_), list(0) { cache_type= EVENT_NO_CACHE; /* Failure to allocate memory will be caught by is_valid() returning false. */ @@ -6359,32 +6363,70 @@ Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set) gtid_set->get_gtid_list(list, count); } + +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) bool -Gtid_list_log_event::write(IO_CACHE *file) +Gtid_list_log_event::to_packet(String *packet) { uint32 i; - uchar buf[element_size]; + uchar *p; + uint32 needed_length; DBUG_ASSERT(count < 1<<28); - if (write_header(file, get_data_size())) - return 1; - int4store(buf, count & ((1<<28)-1)); - if (wrapper_my_b_safe_write(file, buf, GTID_LIST_HEADER_LEN)) - return 1; + needed_length= packet->length() + 4 + count*element_size; + if (packet->reserve(needed_length)) + return true; + p= (uchar *)packet->ptr() + packet->length();; + packet->length(needed_length); + int4store(p, (count & ((1<<28)-1)) | gl_flags); + p += 4; for (i= 0; i < count; ++i) { - int4store(buf, list[i].domain_id); - int4store(buf+4, list[i].server_id); - int8store(buf+8, list[i].seq_no); - if (wrapper_my_b_safe_write(file, buf, element_size)) - return 1; + int4store(p, list[i].domain_id); + int4store(p+4, list[i].server_id); + int8store(p+8, list[i].seq_no); + p += 16; } - return write_footer(file); + + return false; +} + + +bool +Gtid_list_log_event::write(IO_CACHE *file) +{ + char buf[128]; + String packet(buf, sizeof(buf), system_charset_info); + + packet.length(0); + if (to_packet(&packet)) + return true; + return + write_header(file, get_data_size()) || + wrapper_my_b_safe_write(file, (uchar *)packet.ptr(), packet.length()) || + write_footer(file); +} + + +int +Gtid_list_log_event::do_apply_event(Relay_log_info const *rli) +{ + int ret= Log_event::do_apply_event(rli); + if (rli->until_condition == Relay_log_info::UNTIL_GTID && + (gl_flags & FLAG_UNTIL_REACHED)) + { + char str_buf[128]; + String str(str_buf, sizeof(str_buf), system_charset_info); + const_cast(rli)->until_gtid_pos.to_string(&str); + sql_print_information("Slave SQL thread stops because it reached its" + " UNTIL master_gtid_pos %s", str.c_ptr_safe()); + const_cast(rli)->abort_slave= true; + } + return ret; } -#ifdef HAVE_REPLICATION void Gtid_list_log_event::pack_info(THD *thd, Protocol *protocol) { @@ -6439,12 +6481,24 @@ Gtid_list_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) */ bool Gtid_list_log_event::peek(const char *event_start, uint32 event_len, + uint8 checksum_alg, rpl_gtid **out_gtid_list, uint32 *out_list_len) { const char *p; uint32 count_field, count; rpl_gtid *gtid_list; + if (checksum_alg == BINLOG_CHECKSUM_ALG_CRC32) + { + if (event_len > BINLOG_CHECKSUM_LEN) + event_len-= BINLOG_CHECKSUM_LEN; + else + event_len= 0; + } + else + DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF || + checksum_alg == BINLOG_CHECKSUM_ALG_OFF); + if (event_len < LOG_EVENT_HEADER_LEN + GTID_LIST_HEADER_LEN) return true; p= event_start + LOG_EVENT_HEADER_LEN; diff --git a/sql/log_event.h b/sql/log_event.h index 5026b280b27..21d60cac928 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3116,7 +3116,7 @@ public: count 4 byte unsigned integer The lower 28 bits are the number of GTIDs. The upper 4 bits are - reserved for flags bits for future expansion + flags bits. @@ -3149,18 +3149,28 @@ public: The three elements in the body repeat COUNT times to form the GTID list. + + At the time of writing, only one flag bit is in use. + + Bit 28 of `count' is used for flag FLAG_UNTIL_REACHED, which is sent in a + Gtid_list event from the master to the slave to indicate that the START + SLAVE UNTIL master_gtid_pos=xxx condition has been reached. (This flag is + only sent in "fake" events generated on the fly, it is not written into + the binlog). */ class Gtid_list_log_event: public Log_event { public: uint32 count; + uint32 gl_flags; struct rpl_gtid *list; static const uint element_size= 4+4+8; + static const uint32 FLAG_UNTIL_REACHED= (1<<28); #ifdef MYSQL_SERVER - Gtid_list_log_event(rpl_binlog_state *gtid_set); + Gtid_list_log_event(rpl_binlog_state *gtid_set, uint32 gl_flags); #ifdef HAVE_REPLICATION void pack_info(THD *thd, Protocol *protocol); #endif @@ -3173,10 +3183,13 @@ public: Log_event_type get_type_code() { return GTID_LIST_EVENT; } int get_data_size() { return GTID_LIST_HEADER_LEN + count*element_size; } bool is_valid() const { return list != NULL; } -#ifdef MYSQL_SERVER +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + bool to_packet(String *packet); bool write(IO_CACHE *file); + virtual int do_apply_event(Relay_log_info const *rli); #endif static bool peek(const char *event_start, uint32 event_len, + uint8 checksum_alg, rpl_gtid **out_gtid_list, uint32 *out_list_len); }; diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index bda060115ed..a4bdeb9932b 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -711,6 +711,22 @@ void rpl_binlog_state::free() } } + +bool +rpl_binlog_state::load(struct rpl_gtid *list, uint32 count) +{ + uint32 i; + + reset(); + for (i= 0; i < count; ++i) + { + if (update(&(list[i]))) + return true; + } + return false; +} + + rpl_binlog_state::~rpl_binlog_state() { free(); @@ -1116,11 +1132,18 @@ slave_connection_state::remove(const rpl_gtid *in_gtid) int slave_connection_state::to_string(String *out_str) +{ + out_str->length(0); + return append_to_string(out_str); +} + + +int +slave_connection_state::append_to_string(String *out_str) { uint32 i; bool first; - out_str->length(0); first= true; for (i= 0; i < hash.records; ++i) { diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index 046533fd760..bd6663c0659 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -142,6 +142,7 @@ struct rpl_binlog_state void reset(); void free(); + bool load(struct rpl_gtid *list, uint32 count); int update(const struct rpl_gtid *gtid); uint64 seq_no_from_state(); int write_to_iocache(IO_CACHE *dest); @@ -172,6 +173,7 @@ struct slave_connection_state void remove(const rpl_gtid *gtid); ulong count() const { return hash.records; } int to_string(String *out_str); + int append_to_string(String *out_str); }; extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid, diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index ec2ca048976..d27a80313ac 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1096,7 +1096,8 @@ bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) ulonglong log_pos; DBUG_ENTER("Relay_log_info::is_until_satisfied"); - DBUG_ASSERT(until_condition != UNTIL_NONE); + DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || + until_condition == UNTIL_RELAY_POS); if (until_condition == UNTIL_MASTER_POS) { diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 7aff6720aac..6dd757343fd 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -263,7 +263,9 @@ public: thread is running). */ - enum {UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS} until_condition; + enum { + UNTIL_NONE= 0, UNTIL_MASTER_POS, UNTIL_RELAY_POS, UNTIL_GTID + } until_condition; char until_log_name[FN_REFLEN]; ulonglong until_log_pos; /* extension extracted from log_name and converted to int */ @@ -277,6 +279,8 @@ public: UNTIL_LOG_NAMES_CMP_UNKNOWN= -2, UNTIL_LOG_NAMES_CMP_LESS= -1, UNTIL_LOG_NAMES_CMP_EQUAL= 0, UNTIL_LOG_NAMES_CMP_GREATER= 1 } until_log_names_cmp_result; + /* Condition for UNTIL master_gtid_pos. */ + slave_connection_state until_gtid_pos; char cached_charset[6]; /* @@ -354,6 +358,8 @@ public: bool is_until_satisfied(THD *thd, Log_event *ev); inline ulonglong until_pos() { + DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || + until_condition == UNTIL_RELAY_POS); return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : group_relay_log_pos); } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 5dbc7637552..d7d5710b048 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6543,3 +6543,5 @@ ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG eng "Requested GTID_POS %u-%u-%llu conflicts with the binary log which contains a more recent GTID %u-%u-%llu. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog" ER_MASTER_GTID_POS_MISSING_DOMAIN eng "Requested GTID_POS contains no value for replication domain %u. This conflicts with the binary log which contains GTID %u-%u-%llu. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog" +ER_UNTIL_REQUIRES_USING_GTID + eng "START SLAVE UNTIL master_gtid_pos requires that slave is using GTID" diff --git a/sql/slave.cc b/sql/slave.cc index f0a9b27707c..1b3154e20ab 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1879,6 +1879,43 @@ after_set_capability: goto err; } } + + if (mi->rli.until_condition == Relay_log_info::UNTIL_GTID) + { + connect_state.length(0); + connect_state.append(STRING_WITH_LEN("SET @slave_until_gtid='"), + system_charset_info); + if (mi->rli.until_gtid_pos.append_to_string(&connect_state)) + { + err_code= ER_OUTOFMEMORY; + errmsg= "The slave I/O thread stops because a fatal out-of-memory " + "error is encountered when it tries to compute @slave_until_gtid."; + sprintf(err_buff, "%s Error: Out of memory", errmsg); + goto err; + } + connect_state.append(STRING_WITH_LEN("'"), system_charset_info); + + rc= mysql_real_query(mysql, connect_state.ptr(), connect_state.length()); + if (rc) + { + err_code= mysql_errno(mysql); + if (is_network_error(err_code)) + { + mi->report(ERROR_LEVEL, err_code, + "Setting @slave_until_gtid failed with error: %s", + mysql_error(mysql)); + goto network_err; + } + else + { + /* Fatal error */ + errmsg= "The slave I/O thread stops because a fatal error is " + "encountered when it tries to set @slave_until_gtid."; + sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); + goto err; + } + } + } } if (!mi->using_gtid) { @@ -2363,7 +2400,8 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, protocol->store( mi->rli.until_condition==Relay_log_info::UNTIL_NONE ? "None": ( mi->rli.until_condition==Relay_log_info::UNTIL_MASTER_POS? "Master": - "Relay"), &my_charset_bin); + ( mi->rli.until_condition==Relay_log_info::UNTIL_RELAY_POS? "Relay": + "Gtid")), &my_charset_bin); protocol->store(mi->rli.until_log_name, &my_charset_bin); protocol->store((ulonglong) mi->rli.until_log_pos); @@ -3057,7 +3095,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) This tests if the position of the beginning of the current event hits the UNTIL barrier. */ - if (rli->until_condition != Relay_log_info::UNTIL_NONE && + if ((rli->until_condition == Relay_log_info::UNTIL_MASTER_POS || + rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && rli->is_until_satisfied(thd, ev)) { char buf[22]; @@ -3954,7 +3993,8 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, saved_master_log_pos= rli->group_master_log_pos; saved_skip= rli->slave_skip_counter; } - if (rli->until_condition != Relay_log_info::UNTIL_NONE && + if ((rli->until_condition == Relay_log_info::UNTIL_MASTER_POS || + rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && rli->is_until_satisfied(thd, NULL)) { char buf[22]; @@ -4793,7 +4833,43 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) } break; + case GTID_LIST_EVENT: + { + const char *errmsg; + Gtid_list_log_event *glev; + Log_event *tmp; + + if (mi->rli.until_condition != Relay_log_info::UNTIL_GTID) + goto default_action; + if (!(tmp= Log_event::read_log_event(buf, event_len, &errmsg, + mi->rli.relay_log.description_event_for_queue, + opt_slave_sql_verify_checksum))) + { + error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; + goto err; + } + glev= static_cast(tmp); + if (glev->gl_flags & Gtid_list_log_event::FLAG_UNTIL_REACHED) + { + char str_buf[128]; + String str(str_buf, sizeof(str_buf), system_charset_info); + mi->rli.until_gtid_pos.to_string(&str); + sql_print_information("Slave IO thread stops because it reached its" + " UNTIL master_gtid_pos %s", str.c_ptr_safe()); + mi->abort_slave= true; + } + delete glev; + + /* + Do not update position for fake Gtid_list event (which has a zero + end_log_pos). + */ + inc_pos= uint4korr(buf+LOG_POS_OFFSET) ? event_len : 0; + } + break; + default: + default_action: inc_pos= event_len; break; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8bfcddefdfd..4c1d917aeae 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -289,6 +289,8 @@ struct LEX_MASTER_INFO char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher; char *relay_log_name; LEX_STRING connection_name; + /* Value in START SLAVE UNTIL master_gtid_pos=xxx */ + LEX_STRING gtid_pos_str; ulonglong pos; ulong relay_log_pos; ulong server_id; @@ -317,6 +319,8 @@ struct LEX_MASTER_INFO heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= repl_ignore_server_ids_opt= use_gtid_opt= LEX_MI_UNCHANGED; + gtid_pos_str.length= 0; + gtid_pos_str.str= NULL; } }; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 32e653cebff..aa21d191166 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -30,6 +30,14 @@ #include "rpl_handler.h" #include "debug_sync.h" + +enum enum_gtid_until_state { + GTID_UNTIL_NOT_DONE, + GTID_UNTIL_STOP_AFTER_STANDALONE, + GTID_UNTIL_STOP_AFTER_TRANSACTION +}; + + int max_binlog_dump_events = 0; // unlimited my_bool opt_sporadic_binlog_dump_fail = 0; #ifndef DBUG_OFF @@ -38,6 +46,74 @@ static int binlog_dump_count = 0; extern TYPELIB binlog_checksum_typelib; + +static int +fake_event_header(String* packet, Log_event_type event_type, ulong extra_len, + my_bool *do_checksum, ha_checksum *crc, const char** errmsg, + uint8 checksum_alg_arg) +{ + char header[LOG_EVENT_HEADER_LEN]; + ulong event_len; + + *do_checksum= checksum_alg_arg != BINLOG_CHECKSUM_ALG_OFF && + checksum_alg_arg != BINLOG_CHECKSUM_ALG_UNDEF; + + /* + 'when' (the timestamp) is set to 0 so that slave could distinguish between + real and fake Rotate events (if necessary) + */ + memset(header, 0, 4); + header[EVENT_TYPE_OFFSET] = (uchar)event_type; + event_len= LOG_EVENT_HEADER_LEN + extra_len + + (*do_checksum ? BINLOG_CHECKSUM_LEN : 0); + int4store(header + SERVER_ID_OFFSET, global_system_variables.server_id); + int4store(header + EVENT_LEN_OFFSET, event_len); + int2store(header + FLAGS_OFFSET, LOG_EVENT_ARTIFICIAL_F); + // TODO: check what problems this may cause and fix them + int4store(header + LOG_POS_OFFSET, 0); + if (packet->append(header, sizeof(header))) + { + *errmsg= "Failed due to out-of-memory writing event"; + return -1; + } + if (*do_checksum) + { + *crc= my_checksum(0L, NULL, 0); + *crc= my_checksum(*crc, (uchar*)header, sizeof(header)); + } + return 0; +} + + +static int +fake_event_footer(String *packet, my_bool do_checksum, ha_checksum crc, const char **errmsg) +{ + if (do_checksum) + { + char b[BINLOG_CHECKSUM_LEN]; + int4store(b, crc); + if (packet->append(b, sizeof(b))) + { + *errmsg= "Failed due to out-of-memory writing event checksum"; + return -1; + } + } + return 0; +} + + +static int +fake_event_write(NET *net, String *packet, const char **errmsg) +{ + if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) + { + *errmsg = "failed on my_net_write()"; + return -1; + } + return 0; +} + + /* fake_rotate_event() builds a fake (=which does not exist physically in any binlog) Rotate event, which contains the name of the binlog we are going to @@ -61,59 +137,71 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, uint8 checksum_alg_arg) { DBUG_ENTER("fake_rotate_event"); - char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN+100]; - - /* - this Rotate is to be sent with checksum if and only if - slave's get_master_version_and_clock time handshake value - of master's @@global.binlog_checksum was TRUE - */ - - my_bool do_checksum= checksum_alg_arg != BINLOG_CHECKSUM_ALG_OFF && - checksum_alg_arg != BINLOG_CHECKSUM_ALG_UNDEF; - - /* - 'when' (the timestamp) is set to 0 so that slave could distinguish between - real and fake Rotate events (if necessary) - */ - memset(header, 0, 4); - header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; - + char buf[ROTATE_HEADER_LEN+100]; + my_bool do_checksum; + int err; char* p = log_file_name+dirname_length(log_file_name); uint ident_len = (uint) strlen(p); - ulong event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN + - (do_checksum ? BINLOG_CHECKSUM_LEN : 0); - int4store(header + SERVER_ID_OFFSET, global_system_variables.server_id); - int4store(header + EVENT_LEN_OFFSET, event_len); - int2store(header + FLAGS_OFFSET, LOG_EVENT_ARTIFICIAL_F); + ha_checksum crc; - // TODO: check what problems this may cause and fix them - int4store(header + LOG_POS_OFFSET, 0); + if ((err= fake_event_header(packet, ROTATE_EVENT, + ident_len + ROTATE_HEADER_LEN, &do_checksum, &crc, + errmsg, checksum_alg_arg))) + DBUG_RETURN(err); - packet->append(header, sizeof(header)); int8store(buf+R_POS_OFFSET,position); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p, ident_len); if (do_checksum) { - char b[BINLOG_CHECKSUM_LEN]; - ha_checksum crc= my_checksum(0L, NULL, 0); - crc= my_checksum(crc, (uchar*)header, sizeof(header)); crc= my_checksum(crc, (uchar*)buf, ROTATE_HEADER_LEN); crc= my_checksum(crc, (uchar*)p, ident_len); - int4store(b, crc); - packet->append(b, sizeof(b)); } - if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) - { - *errmsg = "failed on my_net_write()"; - DBUG_RETURN(-1); - } + if ((err= fake_event_footer(packet, do_checksum, crc, errmsg)) || + (err= fake_event_write(net, packet, errmsg))) + DBUG_RETURN(err); + DBUG_RETURN(0); } + +static int fake_gtid_list_event(NET* net, String* packet, + Gtid_list_log_event *glev, const char** errmsg, + uint8 checksum_alg_arg) +{ + my_bool do_checksum; + int err; + ha_checksum crc; + char buf[128]; + String str(buf, sizeof(buf), system_charset_info); + + str.length(0); + if (glev->to_packet(&str)) + { + *errmsg= "Failed due to out-of-memory writing Gtid_list event"; + return -1; + } + if ((err= fake_event_header(packet, GTID_LIST_EVENT, + str.length(), &do_checksum, &crc, + errmsg, checksum_alg_arg))) + return err; + + packet->append(str); + if (do_checksum) + { + crc= my_checksum(crc, (uchar*)str.ptr(), str.length()); + } + + if ((err= fake_event_footer(packet, do_checksum, crc, errmsg)) || + (err= fake_event_write(net, packet, errmsg))) + return err; + + return 0; +} + + /* Reset thread transmit packet buffer for event sending @@ -526,6 +614,27 @@ get_slave_connect_state(THD *thd, String *out_str) } +/* + Get the value of the @slave_until_gtid user variable into the supplied + String (this is the GTID position specified for START SLAVE UNTIL + master_gtid_pos='xxx'). + + Returns false if error (ie. slave did not set the variable and is not doing + START SLAVE UNTIL mater_gtid_pos='xxx'), true if success. +*/ +static bool +get_slave_until_gtid(THD *thd, String *out_str) +{ + bool null_value; + + const LEX_STRING name= { C_STRING_WITH_LEN("slave_until_gtid") }; + user_var_entry *entry= + (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name.str, + name.length); + return entry && entry->val_str(&null_value, out_str, 0) && !null_value; +} + + /* Function prepares and sends repliation heartbeat event. @@ -773,10 +882,10 @@ contains_all_slave_gtid(slave_connection_state *st, Gtid_list_log_event *glev) static int check_slave_start_position(THD *thd, slave_connection_state *st, - const char **errormsg, rpl_gtid *error_gtid) + const char **errormsg, rpl_gtid *error_gtid, + slave_connection_state *until_gtid_state) { uint32 i; - bool found; int err; rpl_gtid **delete_list= NULL; uint32 delete_idx= 0; @@ -791,9 +900,9 @@ check_slave_start_position(THD *thd, slave_connection_state *st, rpl_gtid master_replication_gtid; rpl_gtid start_gtid; - if ((found= mysql_bin_log.find_in_binlog_state(slave_gtid->domain_id, - slave_gtid->server_id, - &master_gtid)) && + if (mysql_bin_log.find_in_binlog_state(slave_gtid->domain_id, + slave_gtid->server_id, + &master_gtid) && master_gtid.seq_no >= slave_gtid->seq_no) continue; @@ -814,6 +923,7 @@ check_slave_start_position(THD *thd, slave_connection_state *st, slave_gtid->seq_no != master_replication_gtid.seq_no) { rpl_gtid domain_gtid; + rpl_gtid *until_gtid; if (!mysql_bin_log.lookup_domain_in_binlog_state(slave_gtid->domain_id, &domain_gtid)) @@ -832,6 +942,27 @@ check_slave_start_position(THD *thd, slave_connection_state *st, ++missing_domains; continue; } + + if (until_gtid_state && + ( !(until_gtid= until_gtid_state->find(slave_gtid->domain_id)) || + (mysql_bin_log.find_in_binlog_state(until_gtid->domain_id, + until_gtid->server_id, + &master_gtid) && + master_gtid.seq_no >= until_gtid->seq_no))) + { + /* + The slave requested to start from a position that is not (yet) in + our binlog, but it also specified an UNTIL condition that _is_ in + our binlog (or a missing UNTIL, which means stop at the very + beginning). So the stop position is before the start position, and + we just delete the entry from the UNTIL hash to mark that this + domain has already reached the UNTIL condition. + */ + if(until_gtid) + until_gtid_state->remove(until_gtid); + continue; + } + *errormsg= "Requested slave GTID state not found in binlog"; *error_gtid= *slave_gtid; err= ER_GTID_POSITION_NOT_FOUND_IN_BINLOG; @@ -951,7 +1082,8 @@ end: the requested GTID that was already purged. */ static const char * -gtid_find_binlog_file(slave_connection_state *state, char *out_name) +gtid_find_binlog_file(slave_connection_state *state, char *out_name, + slave_connection_state *until_gtid_state) { MEM_ROOT memroot; binlog_file_entry *list; @@ -1003,42 +1135,60 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name) if (!glev || contains_all_slave_gtid(state, glev)) { - uint32 i; - strmake(out_name, buf, FN_REFLEN); - /* - As a special case, we allow to start from binlog file N if the - requested GTID is the last event (in the corresponding domain) in - binlog file (N-1), but then we need to remove that GTID from the slave - state, rather than skipping events waiting for it to turn up. - */ - for (i= 0; i < glev->count; ++i) + if (glev) { - const rpl_gtid *gtid= state->find(glev->list[i].domain_id); - if (!gtid) - { - /* - contains_all_slave_gtid() returns false if there is any domain in - Gtid_list_event which is not in the requested slave position. + uint32 i; - We may delete a domain from the slave state inside this loop, but - we only do this when it is the very last GTID logged for that - domain in earlier binlogs, and then we can not encounter it in any - further GTIDs in the Gtid_list. - */ - DBUG_ASSERT(0); - continue; - } - if (gtid->server_id == glev->list[i].server_id && - gtid->seq_no == glev->list[i].seq_no) + /* + As a special case, we allow to start from binlog file N if the + requested GTID is the last event (in the corresponding domain) in + binlog file (N-1), but then we need to remove that GTID from the slave + state, rather than skipping events waiting for it to turn up. + + If slave is doing START SLAVE UNTIL, check for any UNTIL conditions + that are already included in a previous binlog file. Delete any such + from the UNTIL hash, to mark that such domains have already reached + their UNTIL condition. + */ + for (i= 0; i < glev->count; ++i) { - /* - The slave requested to start from the very beginning of this - domain in this binlog file. So delete the entry from the state, - we do not need to skip anything. - */ - state->remove(gtid); + const rpl_gtid *gtid= state->find(glev->list[i].domain_id); + if (!gtid) + { + /* + Contains_all_slave_gtid() returns false if there is any domain in + Gtid_list_event which is not in the requested slave position. + + We may delete a domain from the slave state inside this loop, but + we only do this when it is the very last GTID logged for that + domain in earlier binlogs, and then we can not encounter it in any + further GTIDs in the Gtid_list. + */ + DBUG_ASSERT(0); + } else if (gtid->server_id == glev->list[i].server_id && + gtid->seq_no == glev->list[i].seq_no) + { + /* + The slave requested to start from the very beginning of this + domain in this binlog file. So delete the entry from the state, + we do not need to skip anything. + */ + state->remove(gtid); + } + + if (until_gtid_state && + (gtid= until_gtid_state->find(glev->list[i].domain_id)) && + gtid->server_id == glev->list[i].server_id && + gtid->seq_no <= glev->list[i].seq_no) + { + /* + We've already reached the stop position in UNTIL for this domain, + since it is before the start position. + */ + until_gtid_state->remove(gtid); + } } } @@ -1163,6 +1313,7 @@ gtid_state_from_pos(const char *name, uint32 offset, goto end; } status= Gtid_list_log_event::peek(packet.ptr(), packet.length(), + current_checksum_alg, >id_list, &list_len); if (status) { @@ -1256,6 +1407,49 @@ gtid_state_from_binlog_pos(const char *in_name, uint32 pos, String *out_str) } +static bool +is_until_reached(THD *thd, NET *net, String *packet, ulong *ev_offset, + enum_gtid_until_state gtid_until_group, + Log_event_type event_type, uint8 current_checksum_alg, + ushort flags, const char **errmsg, + rpl_binlog_state *until_binlog_state) +{ + switch (gtid_until_group) + { + case GTID_UNTIL_NOT_DONE: + return false; + case GTID_UNTIL_STOP_AFTER_STANDALONE: + if (Log_event::is_part_of_group(event_type)) + return false; + break; + case GTID_UNTIL_STOP_AFTER_TRANSACTION: + if (event_type != XID_EVENT && + (event_type != QUERY_EVENT || + !Query_log_event::peek_is_commit_rollback(packet->ptr()+*ev_offset, + packet->length()-*ev_offset, + current_checksum_alg))) + return false; + break; + } + + /* + The last event group has been sent, now the START SLAVE UNTIL condition + has been reached. + + Send a last fake Gtid_list_log_event with a flag set to mark that we + stop due to UNTIL condition. + */ + if (reset_transmit_packet(thd, flags, ev_offset, errmsg)) + return true; + Gtid_list_log_event glev(until_binlog_state, + Gtid_list_log_event::FLAG_UNTIL_REACHED); + if (fake_gtid_list_event(net, packet, &glev, errmsg, current_checksum_alg)) + return true; + *errmsg= NULL; + return true; +} + + /* Helper function for mysql_binlog_send() to write an event down the slave connection. @@ -1268,37 +1462,113 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, IO_CACHE *log, int mariadb_slave_capability, ulong ev_offset, uint8 current_checksum_alg, bool using_gtid_state, slave_connection_state *gtid_state, - enum_gtid_skip_type *gtid_skip_group) + enum_gtid_skip_type *gtid_skip_group, + slave_connection_state *until_gtid_state, + enum_gtid_until_state *gtid_until_group, + rpl_binlog_state *until_binlog_state) { my_off_t pos; size_t len= packet->length(); - /* Skip GTID event groups until we reach slave position within a domain_id. */ - if (event_type == GTID_EVENT && using_gtid_state && gtid_state->count() > 0) + if (event_type == GTID_LIST_EVENT && using_gtid_state && + (gtid_state->count() > 0 || until_gtid_state)) + { + rpl_gtid *gtid_list; + uint32 list_len; + bool err; + + if (ev_offset > len || + Gtid_list_log_event::peek(packet->ptr()+ev_offset, len - ev_offset, + current_checksum_alg, + >id_list, &list_len)) + return "Failed to read Gtid_list_log_event: corrupt binlog"; + err= until_binlog_state->load(gtid_list, list_len); + my_free(gtid_list); + if (err) + return "Failed in internal GTID book-keeping: Out of memory"; + } + + /* Skip GTID event groups until we reach slave position within a domain_id. */ + if (event_type == GTID_EVENT && using_gtid_state) { - uint32 server_id, domain_id; - uint64 seq_no; uchar flags2; rpl_gtid *gtid; - if (ev_offset > len || - Gtid_log_event::peek(packet->ptr()+ev_offset, len - ev_offset, - current_checksum_alg, - &domain_id, &server_id, &seq_no, &flags2)) - return "Failed to read Gtid_log_event: corrupt binlog"; - gtid= gtid_state->find(domain_id); - if (gtid != NULL) + if (gtid_state->count() > 0 || until_gtid_state) { - /* Skip this event group if we have not yet reached slave start pos. */ - if (server_id != gtid->server_id || seq_no <= gtid->seq_no) - *gtid_skip_group = (flags2 & Gtid_log_event::FL_STANDALONE ? - GTID_SKIP_STANDALONE : GTID_SKIP_TRANSACTION); - /* - Delete this entry if we have reached slave start position (so we will - not skip subsequent events and won't have to look them up and check). - */ - if (server_id == gtid->server_id && seq_no >= gtid->seq_no) - gtid_state->remove(gtid); + rpl_gtid event_gtid; + + if (ev_offset > len || + Gtid_log_event::peek(packet->ptr()+ev_offset, len - ev_offset, + current_checksum_alg, + &event_gtid.domain_id, &event_gtid.server_id, + &event_gtid.seq_no, &flags2)) + return "Failed to read Gtid_log_event: corrupt binlog"; + + if (until_binlog_state->update(&event_gtid)) + return "Failed in internal GTID book-keeping: Out of memory"; + + if (gtid_state->count() > 0) + { + gtid= gtid_state->find(event_gtid.domain_id); + if (gtid != NULL) + { + /* Skip this event group if we have not yet reached slave start pos. */ + if (event_gtid.server_id != gtid->server_id || + event_gtid.seq_no <= gtid->seq_no) + *gtid_skip_group = (flags2 & Gtid_log_event::FL_STANDALONE ? + GTID_SKIP_STANDALONE : GTID_SKIP_TRANSACTION); + /* + Delete this entry if we have reached slave start position (so we will + not skip subsequent events and won't have to look them up and check). + */ + if (event_gtid.server_id == gtid->server_id && + event_gtid.seq_no >= gtid->seq_no) + gtid_state->remove(gtid); + } + } + + if (until_gtid_state) + { + gtid= until_gtid_state->find(event_gtid.domain_id); + if (gtid == NULL) + { + /* + This domain already reached the START SLAVE UNTIL stop condition, + so skip this event group. + */ + *gtid_skip_group = (flags2 & Gtid_log_event::FL_STANDALONE ? + GTID_SKIP_STANDALONE : GTID_SKIP_TRANSACTION); + } + else if (event_gtid.server_id == gtid->server_id && + event_gtid.seq_no >= gtid->seq_no) + { + /* + We have reached the stop condition. + Delete this domain_id from the hash, so we will skip all further + events in this domain and eventually stop when all domains are + done. + */ + uint64 until_seq_no= gtid->seq_no; + until_gtid_state->remove(gtid); + if (until_gtid_state->count() == 0) + *gtid_until_group= (flags2 & Gtid_log_event::FL_STANDALONE ? + GTID_UNTIL_STOP_AFTER_STANDALONE : + GTID_UNTIL_STOP_AFTER_TRANSACTION); + if (event_gtid.seq_no > until_seq_no) + { + /* + The GTID in START SLAVE UNTIL condition is missing in our binlog. + This should normally not happen (user error), but since we can be + sure that we are now beyond the position that the UNTIL condition + should be in, we can just stop now. And we also need to skip this + event group (as it is beyond the UNTIL condition). + */ + *gtid_skip_group = (flags2 & Gtid_log_event::FL_STANDALONE ? + GTID_SKIP_STANDALONE : GTID_SKIP_TRANSACTION); + } + } + } } } @@ -1446,6 +1716,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, return NULL; /* Success */ } + void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags) { @@ -1465,12 +1736,17 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, mysql_mutex_t *log_lock; mysql_cond_t *log_cond; int mariadb_slave_capability; - char str_buf[256]; + char str_buf[128]; String connect_gtid_state(str_buf, sizeof(str_buf), system_charset_info); bool using_gtid_state; - slave_connection_state gtid_state, return_gtid_state; + char str_buf2[128]; + String slave_until_gtid_str(str_buf2, sizeof(str_buf2), system_charset_info); + slave_connection_state gtid_state, until_gtid_state_obj; + slave_connection_state *until_gtid_state= NULL; rpl_gtid error_gtid; enum_gtid_skip_type gtid_skip_group= GTID_SKIP_NOT; + enum_gtid_until_state gtid_until_group= GTID_UNTIL_NOT_DONE; + rpl_binlog_state until_binlog_state; uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; int old_max_allowed_packet= thd->variables.max_allowed_packet; @@ -1502,6 +1778,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, connect_gtid_state.length(0); using_gtid_state= get_slave_connect_state(thd, &connect_gtid_state); DBUG_EXECUTE_IF("simulate_non_gtid_aware_master", using_gtid_state= false;); + if (using_gtid_state && + get_slave_until_gtid(thd, &slave_until_gtid_str)) + until_gtid_state= &until_gtid_state_obj; + /* We want to corrupt the first event, in Log_event::read_log_event(). But we do not want the corruption to happen early, eg. when client does @@ -1557,13 +1837,23 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, my_errno= ER_UNKNOWN_ERROR; goto err; } + if (until_gtid_state && + until_gtid_state->load(slave_until_gtid_str.c_ptr_quick(), + slave_until_gtid_str.length())) + { + errmsg= "Out of memory or malformed slave request when obtaining UNTIL " + "position sent from slave"; + my_errno= ER_UNKNOWN_ERROR; + goto err; + } if ((error= check_slave_start_position(thd, >id_state, &errmsg, - &error_gtid))) + &error_gtid, until_gtid_state))) { my_errno= error; goto err; } - if ((errmsg= gtid_find_binlog_file(>id_state, search_file_name))) + if ((errmsg= gtid_find_binlog_file(>id_state, search_file_name, + until_gtid_state))) { my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; @@ -1753,6 +2043,15 @@ impossible position"; /* The Format_description_log_event event will be found naturally. */ } + /* + Handle the case of START SLAVE UNTIL with an UNTIL condition already + fulfilled at the start position. + + We will send one event, the format_description, and then stop. + */ + if (until_gtid_state && until_gtid_state->count() == 0) + gtid_until_group= GTID_UNTIL_STOP_AFTER_STANDALONE; + /* seek to the requested position, to start the requested dump */ my_b_seek(&log, pos); // Seek will done on next read @@ -1833,12 +2132,26 @@ impossible position"; log_file_name, &log, mariadb_slave_capability, ev_offset, current_checksum_alg, using_gtid_state, - >id_state, >id_skip_group))) + >id_state, >id_skip_group, + until_gtid_state, >id_until_group, + &until_binlog_state))) { errmsg= tmp_msg; my_errno= ER_UNKNOWN_ERROR; goto err; } + if (until_gtid_state && + is_until_reached(thd, net, packet, &ev_offset, gtid_until_group, + event_type, current_checksum_alg, flags, &errmsg, + &until_binlog_state)) + { + if (errmsg) + { + my_errno= ER_UNKNOWN_ERROR; + goto err; + } + goto end; + } DBUG_EXECUTE_IF("dump_thread_wait_before_send_xid", { @@ -1992,18 +2305,34 @@ impossible position"; goto err; } - if (read_packet && - (tmp_msg= send_event_to_slave(thd, net, packet, flags, event_type, - log_file_name, &log, - mariadb_slave_capability, ev_offset, - current_checksum_alg, - using_gtid_state, >id_state, - >id_skip_group))) + if (read_packet) { - errmsg= tmp_msg; - my_errno= ER_UNKNOWN_ERROR; - goto err; - } + if ((tmp_msg= send_event_to_slave(thd, net, packet, flags, event_type, + log_file_name, &log, + mariadb_slave_capability, ev_offset, + current_checksum_alg, + using_gtid_state, >id_state, + >id_skip_group, until_gtid_state, + >id_until_group, &until_binlog_state))) + { + errmsg= tmp_msg; + my_errno= ER_UNKNOWN_ERROR; + goto err; + } + if ( + until_gtid_state && + is_until_reached(thd, net, packet, &ev_offset, gtid_until_group, + event_type, current_checksum_alg, flags, &errmsg, + &until_binlog_state)) + { + if (errmsg) + { + my_errno= ER_UNKNOWN_ERROR; + goto err; + } + goto end; + } + } log.error=0; } @@ -2167,6 +2496,26 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) lock_slave_threads(mi); // this allows us to cleanly read slave_running // Get a mask of _stopped_ threads init_thread_mask(&thread_mask,mi,1 /* inverse */); + + if (thd->lex->mi.gtid_pos_str.str) + { + if (thread_mask != (SLAVE_IO|SLAVE_SQL)) + { + slave_errno= ER_SLAVE_WAS_RUNNING; + goto err; + } + if (thd->lex->slave_thd_opt) + { + slave_errno= ER_BAD_SLAVE_UNTIL_COND; + goto err; + } + if (!mi->using_gtid) + { + slave_errno= ER_UNTIL_REQUIRES_USING_GTID; + goto err; + } + } + /* Below we will start all stopped threads. But if the user wants to start only one thread, do as if the other thread was running (as we @@ -2213,10 +2562,22 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) strmake(mi->rli.until_log_name, thd->lex->mi.relay_log_name, sizeof(mi->rli.until_log_name)-1); } + else if (thd->lex->mi.gtid_pos_str.str) + { + if (mi->rli.until_gtid_pos.load(thd->lex->mi.gtid_pos_str.str, + thd->lex->mi.gtid_pos_str.length)) + { + slave_errno= ER_INCORRECT_GTID_STATE; + mysql_mutex_unlock(&mi->rli.data_lock); + goto err; + } + mi->rli.until_condition= Relay_log_info::UNTIL_GTID; + } else mi->rli.clear_until_condition(); - if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE) + if (mi->rli.until_condition == Relay_log_info::UNTIL_MASTER_POS || + mi->rli.until_condition == Relay_log_info::UNTIL_RELAY_POS) { /* Preparing members for effective until condition checking */ const char *p= fn_ext(mi->rli.until_log_name); @@ -2239,7 +2600,10 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) /* mark the cached result of the UNTIL comparison as "undefined" */ mi->rli.until_log_names_cmp_result= Relay_log_info::UNTIL_LOG_NAMES_CMP_UNKNOWN; + } + if (mi->rli.until_condition != Relay_log_info::UNTIL_NONE) + { /* Issuing warning then started without --skip-slave-start */ if (!opt_skip_slave_start) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, @@ -2271,6 +2635,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) ER(ER_SLAVE_WAS_RUNNING)); } +err: unlock_slave_threads(mi); if (slave_errno) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 94fdc46647f..e995b410a85 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1095,7 +1095,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token LOW_PRIORITY %token LT /* OPERATOR */ %token MASTER_CONNECT_RETRY_SYM -%token MASTER_USE_GTID_SYM +%token MASTER_GTID_POS_SYM %token MASTER_HOST_SYM %token MASTER_LOG_FILE_SYM %token MASTER_LOG_POS_SYM @@ -1111,6 +1111,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MASTER_SSL_VERIFY_SERVER_CERT_SYM %token MASTER_SYM %token MASTER_USER_SYM +%token MASTER_USE_GTID_SYM %token MASTER_HEARTBEAT_PERIOD_SYM %token MATCH /* SQL-2003-R */ %token MAX_CONNECTIONS_PER_HOUR @@ -7215,6 +7216,10 @@ slave_until: MYSQL_YYABORT; } } + | UNTIL_SYM MASTER_GTID_POS_SYM EQ TEXT_STRING_sys + { + Lex->mi.gtid_pos_str = $4; + } ; slave_until_opts: @@ -13326,12 +13331,13 @@ keyword_sp: | MAX_ROWS {} | MASTER_SYM {} | MASTER_HEARTBEAT_PERIOD_SYM {} - | MASTER_USE_GTID_SYM {} + | MASTER_GTID_POS_SYM {} | MASTER_HOST_SYM {} | MASTER_PORT_SYM {} | MASTER_LOG_FILE_SYM {} | MASTER_LOG_POS_SYM {} | MASTER_USER_SYM {} + | MASTER_USE_GTID_SYM {} | MASTER_PASSWORD_SYM {} | MASTER_SERVER_ID_SYM {} | MASTER_CONNECT_RETRY_SYM {} From d795bc9ff8d4a4e17f249a0eb9ac01f25d53a259 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 May 2013 12:41:11 +0200 Subject: [PATCH 06/10] Fix race condition in binlog dump thread during server shutdown. There was missing a check for THD::killed after THD::enter_cond(). This could cause the binlog dump thread to miss the kill signal during server shutdown and hang until it was force-closed. Also fix a race in a test case that occasionally fails in Buildbot. --- mysql-test/include/rpl_init.inc | 2 +- mysql-test/suite/rpl/r/rpl_gtid_basic.result | 1 + mysql-test/suite/rpl/t/rpl_gtid_basic.test | 8 ++++++-- sql/sql_repl.cc | 4 +++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index 939a05d8011..98e3c468253 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -177,8 +177,8 @@ while ($_rpl_server) if (!$rpl_skip_reset_master_and_slave) { RESET MASTER; - RESET SLAVE; SET GLOBAL gtid_pos= ""; + RESET SLAVE; } eval SET auto_increment_increment= $rpl_server_count; eval SET auto_increment_offset= $_rpl_server; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result index bbe59ee69ae..b1e53a4a0b5 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result @@ -107,6 +107,7 @@ a b include/stop_slave.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_MYPORT; include/start_slave.inc +include/wait_for_slave_to_start.inc include/stop_slave.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = SLAVE_MYPORT; include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test index becb284c0c2..9513acb17b6 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -95,12 +95,16 @@ SELECT * FROM t2 ORDER BY a; --echo *** Now change everything back to what it was, to make rpl_end.inc happy # Also check that MASTER_USE_GTID=1 is still enabled. connection server_2; +# We need to sync up server_2 before switching. If it happened to have reached +# the point 'UPDATE t2 SET b="j1a" WHERE a=5' it will fail to connect to +# server_1, which is (deliberately) missing that transaction. +--let $wait_condition= SELECT COUNT(*) = 7 FROM t2 +--source include/wait_condition.inc --source include/stop_slave.inc --replace_result $MASTER_MYPORT MASTER_MYPORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT; --source include/start_slave.inc ---let $wait_condition= SELECT COUNT(*) = 7 FROM t2 ---source include/wait_condition.inc +--source include/wait_for_slave_to_start.inc connection server_3; --source include/stop_slave.inc diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index aa21d191166..2e10af0aa8c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2263,6 +2263,8 @@ impossible position"; thd->enter_cond(log_cond, log_lock, "Master has sent all binlog to slave; " "waiting for binlog to be updated"); + if (thd->killed) + break; ret= mysql_bin_log.wait_for_update_bin_log(thd, heartbeat_ts); DBUG_ASSERT(ret == 0 || (heartbeat_period != 0)); if (ret == ETIMEDOUT || ret == ETIME) @@ -2294,7 +2296,7 @@ impossible position"; { DBUG_PRINT("wait",("binary log received update or a broadcast signal caught")); } - } while (signal_cnt == mysql_bin_log.signal_cnt && !thd->killed); + } while (signal_cnt == mysql_bin_log.signal_cnt); thd->exit_cond(old_msg); } break; From 1cd6eb5f942ca3e94e86a48512d992fbb3aeecd9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 May 2013 17:36:48 +0200 Subject: [PATCH 07/10] MDEV-26: Global transaction ID. Change of user interface to be more logical and more in line with expectations to work similar to old-style replication. User can now explicitly choose in CHANGE MASTER whether binlog position is taken into account (master_gtid_pos=current_pos) or not (master_gtid_pos= slave_pos) when slave connects to master. @@gtid_pos is replaced by three separate variables @@gtid_slave_pos (can be set by user, replicated GTIDs only), @@gtid_binlog_pos (read only), and @@gtid_current_pos (a combination of the two, most recent GTID within each domain). mysql.rpl_slave_state is renamed to mysql.gtid_slave_pos to match. This fixes MDEV-4474. --- mysql-test/include/check-testcase.test | 2 +- mysql-test/include/mtr_check.sql | 2 +- mysql-test/include/rpl_init.inc | 2 +- mysql-test/r/1st.result | 2 +- mysql-test/r/connect.result | 6 +- mysql-test/r/information_schema.result | 2 +- mysql-test/r/log_tables_upgrade.result | 2 +- mysql-test/r/mysql_upgrade.result | 14 +-- mysql-test/r/mysql_upgrade_ssl.result | 2 +- mysql-test/r/mysqlcheck.result | 8 +- mysql-test/r/system_mysql_db.result | 2 +- mysql-test/r/system_mysql_db_fix40123.result | 2 +- mysql-test/r/system_mysql_db_fix50030.result | 2 +- mysql-test/r/system_mysql_db_fix50117.result | 2 +- .../suite/funcs_1/r/is_columns_mysql.result | 16 +-- .../r/is_columns_mysql_embedded.result | 16 +-- .../funcs_1/r/is_key_column_usage.result | 4 +- .../suite/funcs_1/r/is_statistics.result | 4 +- .../funcs_1/r/is_statistics_mysql.result | 4 +- .../r/is_statistics_mysql_embedded.result | 8 +- .../funcs_1/r/is_table_constraints.result | 2 +- .../r/is_table_constraints_mysql.result | 2 +- ...is_table_constraints_mysql_embedded.result | 4 +- .../suite/funcs_1/r/is_tables_mysql.result | 46 ++++---- .../funcs_1/r/is_tables_mysql_embedded.result | 92 +++++++-------- mysql-test/suite/multi_source/gtid.result | 10 +- mysql-test/suite/multi_source/gtid.test | 6 +- .../suite/multi_source/info_logs.result | 12 +- .../suite/multi_source/multisource.result | 20 ++-- .../suite/multi_source/reset_master_slave.inc | 2 +- .../suite/multi_source/reset_slave.result | 4 +- mysql-test/suite/multi_source/simple.result | 22 ++-- mysql-test/suite/multi_source/syntax.result | 2 +- mysql-test/suite/rpl/r/rpl_gtid_basic.result | 6 +- mysql-test/suite/rpl/r/rpl_gtid_crash.result | 6 +- .../suite/rpl/r/rpl_gtid_errorhandling.result | 47 +++++--- .../rpl/r/rpl_gtid_master_promote.result | 12 +- .../suite/rpl/r/rpl_gtid_mdev4473.result | 8 +- .../suite/rpl/r/rpl_gtid_mdev4474.result | 63 ++++++++++ .../suite/rpl/r/rpl_gtid_nobinlog.result | 4 +- .../suite/rpl/r/rpl_gtid_startpos.result | 69 +++++------ .../suite/rpl/r/rpl_gtid_stop_start.result | 4 +- mysql-test/suite/rpl/r/rpl_gtid_until.result | 12 +- mysql-test/suite/rpl/r/rpl_sync.result | 2 +- mysql-test/suite/rpl/t/rpl_gtid_basic.test | 8 +- mysql-test/suite/rpl/t/rpl_gtid_crash.test | 8 +- .../suite/rpl/t/rpl_gtid_errorhandling.test | 45 +++++--- .../suite/rpl/t/rpl_gtid_master_promote.test | 36 +++--- mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test | 8 +- mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf | 11 ++ mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test | 76 ++++++++++++ mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test | 4 +- mysql-test/suite/rpl/t/rpl_gtid_startpos.test | 61 +++++----- .../suite/rpl/t/rpl_gtid_stop_start.test | 2 +- mysql-test/suite/rpl/t/rpl_gtid_until.test | 26 ++--- mysql-test/suite/rpl/t/rpl_sync.test | 2 +- .../sys_vars/r/gtid_binlog_pos_basic.result | 9 ++ .../sys_vars/r/gtid_current_pos_basic.result | 9 ++ .../suite/sys_vars/r/gtid_pos_basic.result | 47 -------- .../sys_vars/r/gtid_slave_pos_basic.result | 47 ++++++++ .../sys_vars/t/gtid_binlog_pos_basic.test | 15 +++ .../sys_vars/t/gtid_current_pos_basic.test | 15 +++ .../suite/sys_vars/t/gtid_pos_basic.test | 46 -------- .../sys_vars/t/gtid_slave_pos_basic.test | 46 ++++++++ mysql-test/t/system_mysql_db_fix40123.test | 2 +- mysql-test/t/system_mysql_db_fix50030.test | 2 +- mysql-test/t/system_mysql_db_fix50117.test | 2 +- scripts/mysql_system_tables.sql | 2 +- sql/lex.h | 2 + sql/log.cc | 14 ++- sql/log.h | 1 + sql/log_event.cc | 4 +- sql/rpl_gtid.cc | 38 ++++-- sql/rpl_gtid.h | 6 +- sql/rpl_mi.cc | 15 ++- sql/rpl_mi.h | 10 +- sql/share/errmsg-utf8.txt | 4 +- sql/slave.cc | 25 ++-- sql/sql_lex.h | 9 +- sql/sql_repl.cc | 72 ++++++++---- sql/sql_repl.h | 2 +- sql/sql_yacc.yy | 31 ++++- sql/sys_vars.cc | 80 +++++++++++-- sql/sys_vars.h | 108 +++++++++++++++++- 84 files changed, 996 insertions(+), 513 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_mdev4474.result create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test create mode 100644 mysql-test/suite/sys_vars/r/gtid_binlog_pos_basic.result create mode 100644 mysql-test/suite/sys_vars/r/gtid_current_pos_basic.result delete mode 100644 mysql-test/suite/sys_vars/r/gtid_pos_basic.result create mode 100644 mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result create mode 100644 mysql-test/suite/sys_vars/t/gtid_binlog_pos_basic.test create mode 100644 mysql-test/suite/sys_vars/t/gtid_current_pos_basic.test delete mode 100644 mysql-test/suite/sys_vars/t/gtid_pos_basic.test create mode 100644 mysql-test/suite/sys_vars/t/gtid_slave_pos_basic.test diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index b25c6945023..d4db37e6621 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -60,7 +60,7 @@ if ($tmp) --echo Last_SQL_Error --echo Replicate_Ignore_Server_Ids --echo Master_Server_Id # - --echo Using_Gtid 0 + --echo Using_Gtid No } if (!$tmp) { # Note: after WL#5177, fields 13-18 shall not be filtered-out. diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index c66a7fea938..467a3f973c7 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -31,7 +31,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 != 'GTID_POS' + AND variable_name not like 'GTID%POS' ORDER BY variable_name; -- Dump all databases, there should be none diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc index 98e3c468253..dbe93adbec3 100644 --- a/mysql-test/include/rpl_init.inc +++ b/mysql-test/include/rpl_init.inc @@ -177,7 +177,7 @@ while ($_rpl_server) if (!$rpl_skip_reset_master_and_slave) { RESET MASTER; - SET GLOBAL gtid_pos= ""; + SET GLOBAL gtid_slave_pos= ""; RESET SLAVE; } eval SET auto_increment_increment= $rpl_server_count; diff --git a/mysql-test/r/1st.result b/mysql-test/r/1st.result index e37bca20f0c..e847be49a91 100644 --- a/mysql-test/r/1st.result +++ b/mysql-test/r/1st.result @@ -13,6 +13,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -24,7 +25,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index a533b495267..b90e558cfaa 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -7,6 +7,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -18,7 +19,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats @@ -45,6 +45,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -56,7 +57,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats @@ -91,6 +91,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -102,7 +103,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 8e1d4856645..ce962a96f29 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -88,6 +88,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -98,7 +99,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log t1 diff --git a/mysql-test/r/log_tables_upgrade.result b/mysql-test/r/log_tables_upgrade.result index 978b4b7b314..abae156ac5e 100644 --- a/mysql-test/r/log_tables_upgrade.result +++ b/mysql-test/r/log_tables_upgrade.result @@ -24,6 +24,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -36,7 +37,6 @@ mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK mysql.renamed_general_log OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 871646d18a8..bb91d4f23c4 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -12,6 +12,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -23,7 +24,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -53,6 +53,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -64,7 +65,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -94,6 +94,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -105,7 +106,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -138,6 +138,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -149,7 +150,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -185,6 +185,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -196,7 +197,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -235,6 +235,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -246,7 +247,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -288,6 +288,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -299,7 +300,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK diff --git a/mysql-test/r/mysql_upgrade_ssl.result b/mysql-test/r/mysql_upgrade_ssl.result index 05316de317d..3b84664708c 100644 --- a/mysql-test/r/mysql_upgrade_ssl.result +++ b/mysql-test/r/mysql_upgrade_ssl.result @@ -14,6 +14,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -25,7 +26,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 38bff3e8254..b25a9be8872 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -8,6 +8,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -19,7 +20,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -36,6 +36,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -47,7 +48,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -62,6 +62,7 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK @@ -73,7 +74,6 @@ mysql.plugin OK mysql.proc OK mysql.procs_priv OK mysql.proxies_priv OK -mysql.rpl_slave_state OK mysql.servers OK mysql.table_stats OK mysql.tables_priv OK @@ -88,6 +88,7 @@ mysql.columns_priv Table is already up to date mysql.db Table is already up to date mysql.event Table is already up to date mysql.func Table is already up to date +mysql.gtid_slave_pos Table is already up to date mysql.help_category Table is already up to date mysql.help_keyword Table is already up to date mysql.help_relation Table is already up to date @@ -99,7 +100,6 @@ mysql.plugin Table is already up to date mysql.proc Table is already up to date mysql.procs_priv Table is already up to date mysql.proxies_priv Table is already up to date -mysql.rpl_slave_state Table is already up to date mysql.servers Table is already up to date mysql.table_stats Table is already up to date mysql.tables_priv Table is already up to date diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 6a6e5d4179a..a92decefbc8 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -6,6 +6,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -17,7 +18,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result index 94cf57d370d..04b20c42af3 100644 --- a/mysql-test/r/system_mysql_db_fix40123.result +++ b/mysql-test/r/system_mysql_db_fix40123.result @@ -6,6 +6,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -17,7 +18,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result index 94cf57d370d..04b20c42af3 100644 --- a/mysql-test/r/system_mysql_db_fix50030.result +++ b/mysql-test/r/system_mysql_db_fix50030.result @@ -6,6 +6,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -17,7 +18,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result index 94cf57d370d..04b20c42af3 100644 --- a/mysql-test/r/system_mysql_db_fix50117.result +++ b/mysql-test/r/system_mysql_db_fix50117.result @@ -6,6 +6,7 @@ db event func general_log +gtid_slave_pos help_category help_keyword help_relation @@ -17,7 +18,6 @@ plugin proc procs_priv proxies_priv -rpl_slave_state servers slow_log table_stats diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 3ca0cefa84a..36c11c15c95 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -74,6 +74,10 @@ def mysql general_log event_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL N def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references +def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI select,insert,update,references +def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references +def mysql gtid_slave_pos server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references +def mysql gtid_slave_pos sub_id 2 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned PRI select,insert,update,references def mysql help_category help_category_id 1 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned PRI select,insert,update,references def mysql help_category name 2 NULL NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) UNI select,insert,update,references def mysql help_category parent_category_id 3 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned select,insert,update,references @@ -157,10 +161,6 @@ def mysql proxies_priv Proxied_user 4 NO char 16 48 NULL NULL NULL utf8 utf8_bi def mysql proxies_priv Timestamp 7 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 0 NULL NULL timestamp on update CURRENT_TIMESTAMP select,insert,update,references def mysql proxies_priv User 2 NO char 16 48 NULL NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references def mysql proxies_priv With_grant 5 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) select,insert,update,references -def mysql rpl_slave_state domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI select,insert,update,references -def mysql rpl_slave_state seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references -def mysql rpl_slave_state server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references -def mysql rpl_slave_state sub_id 2 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned PRI select,insert,update,references def mysql servers Db 3 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references def mysql servers Host 2 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references def mysql servers Owner 9 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references @@ -393,6 +393,10 @@ NULL mysql general_log thread_id int NULL NULL NULL NULL int(11) NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 3.0000 mysql general_log command_type varchar 64 192 utf8 utf8_general_ci varchar(64) 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8 utf8_general_ci mediumtext +NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned +NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned +NULL mysql gtid_slave_pos seq_no bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql help_category help_category_id smallint NULL NULL NULL NULL smallint(5) unsigned 3.0000 mysql help_category name char 64 192 utf8 utf8_general_ci char(64) NULL mysql help_category parent_category_id smallint NULL NULL NULL NULL smallint(5) unsigned @@ -476,10 +480,6 @@ NULL mysql procs_priv Timestamp timestamp NULL NULL NULL NULL timestamp NULL mysql proxies_priv With_grant tinyint NULL NULL NULL NULL tinyint(1) 3.0000 mysql proxies_priv Grantor char 77 231 utf8 utf8_bin char(77) NULL mysql proxies_priv Timestamp timestamp NULL NULL NULL NULL timestamp -NULL mysql rpl_slave_state domain_id int NULL NULL NULL NULL int(10) unsigned -NULL mysql rpl_slave_state sub_id bigint NULL NULL NULL NULL bigint(20) unsigned -NULL mysql rpl_slave_state server_id int NULL NULL NULL NULL int(10) unsigned -NULL mysql rpl_slave_state seq_no bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql servers Server_name char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Host char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Db char 64 192 utf8 utf8_general_ci char(64) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index 0d9fe322c6f..badf5a6811c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -74,6 +74,10 @@ def mysql general_log event_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL N def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext +def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI +def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned +def mysql gtid_slave_pos server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned +def mysql gtid_slave_pos sub_id 2 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned PRI def mysql help_category help_category_id 1 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned PRI def mysql help_category name 2 NULL NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) UNI def mysql help_category parent_category_id 3 NULL YES smallint NULL NULL 5 0 NULL NULL NULL smallint(5) unsigned @@ -157,10 +161,6 @@ def mysql proxies_priv Proxied_user 4 NO char 16 48 NULL NULL NULL utf8 utf8_bi def mysql proxies_priv Timestamp 7 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 0 NULL NULL timestamp on update CURRENT_TIMESTAMP def mysql proxies_priv User 2 NO char 16 48 NULL NULL NULL utf8 utf8_bin char(16) PRI def mysql proxies_priv With_grant 5 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) -def mysql rpl_slave_state domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI -def mysql rpl_slave_state seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned -def mysql rpl_slave_state server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned -def mysql rpl_slave_state sub_id 2 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned PRI def mysql servers Db 3 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) def mysql servers Host 2 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) def mysql servers Owner 9 NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) @@ -393,6 +393,10 @@ NULL mysql general_log thread_id int NULL NULL NULL NULL int(11) NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 3.0000 mysql general_log command_type varchar 64 192 utf8 utf8_general_ci varchar(64) 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8 utf8_general_ci mediumtext +NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned +NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned +NULL mysql gtid_slave_pos seq_no bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql help_category help_category_id smallint NULL NULL NULL NULL smallint(5) unsigned 3.0000 mysql help_category name char 64 192 utf8 utf8_general_ci char(64) NULL mysql help_category parent_category_id smallint NULL NULL NULL NULL smallint(5) unsigned @@ -476,10 +480,6 @@ NULL mysql procs_priv Timestamp timestamp NULL NULL NULL NULL timestamp NULL mysql proxies_priv With_grant tinyint NULL NULL NULL NULL tinyint(1) 3.0000 mysql proxies_priv Grantor char 77 231 utf8 utf8_bin char(77) NULL mysql proxies_priv Timestamp timestamp NULL NULL NULL NULL timestamp -NULL mysql rpl_slave_state domain_id int NULL NULL NULL NULL int(10) unsigned -NULL mysql rpl_slave_state sub_id bigint NULL NULL NULL NULL bigint(20) unsigned -NULL mysql rpl_slave_state server_id int NULL NULL NULL NULL int(10) unsigned -NULL mysql rpl_slave_state seq_no bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql servers Server_name char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Host char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql servers Db char 64 192 utf8 utf8_general_ci char(64) diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage.result b/mysql-test/suite/funcs_1/r/is_key_column_usage.result index f54e7216296..1bc72a883ea 100644 --- a/mysql-test/suite/funcs_1/r/is_key_column_usage.result +++ b/mysql-test/suite/funcs_1/r/is_key_column_usage.result @@ -89,6 +89,8 @@ def mysql PRIMARY def mysql db User def mysql PRIMARY def mysql event db def mysql PRIMARY def mysql event name def mysql PRIMARY def mysql func name +def mysql PRIMARY def mysql gtid_slave_pos domain_id +def mysql PRIMARY def mysql gtid_slave_pos sub_id def mysql PRIMARY def mysql help_category help_category_id def mysql name def mysql help_category name def mysql PRIMARY def mysql help_keyword help_keyword_id @@ -117,8 +119,6 @@ def mysql PRIMARY def mysql proxies_priv Host def mysql PRIMARY def mysql proxies_priv User def mysql PRIMARY def mysql proxies_priv Proxied_host def mysql PRIMARY def mysql proxies_priv Proxied_user -def mysql PRIMARY def mysql rpl_slave_state domain_id -def mysql PRIMARY def mysql rpl_slave_state sub_id def mysql PRIMARY def mysql servers Server_name def mysql PRIMARY def mysql table_stats db_name def mysql PRIMARY def mysql table_stats table_name diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index b9731f3a613..c8717cc60d1 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -100,6 +100,8 @@ def mysql db mysql User def mysql event mysql PRIMARY def mysql event mysql PRIMARY def mysql func mysql PRIMARY +def mysql gtid_slave_pos mysql PRIMARY +def mysql gtid_slave_pos mysql PRIMARY def mysql help_category mysql PRIMARY def mysql help_category mysql name def mysql help_keyword mysql PRIMARY @@ -130,8 +132,6 @@ def mysql proxies_priv mysql PRIMARY def mysql proxies_priv mysql PRIMARY def mysql proxies_priv mysql PRIMARY def mysql proxies_priv mysql Grantor -def mysql rpl_slave_state mysql PRIMARY -def mysql rpl_slave_state mysql PRIMARY def mysql servers mysql PRIMARY def mysql table_stats mysql PRIMARY def mysql table_stats mysql PRIMARY diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result index d8c75373dbc..64a69104aba 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result @@ -22,6 +22,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -52,8 +54,6 @@ def mysql proxies_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 3 Proxied_host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 4 Proxied_user A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql servers 0 mysql PRIMARY 1 Server_name A #CARD# NULL NULL BTREE def mysql tables_priv 1 mysql Grantor 1 Grantor A #CARD# NULL NULL BTREE def mysql tables_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result index ac5d79f1d1a..904777a9c54 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result @@ -22,6 +22,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -52,8 +54,6 @@ def mysql proxies_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 3 Proxied_host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 4 Proxied_user A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql servers 0 mysql PRIMARY 1 Server_name A #CARD# NULL NULL BTREE def mysql tables_priv 1 mysql Grantor 1 Grantor A #CARD# NULL NULL BTREE def mysql tables_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE @@ -91,6 +91,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE +def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_category 0 mysql PRIMARY 1 help_category_id A #CARD# NULL NULL BTREE def mysql help_keyword 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -121,8 +123,6 @@ def mysql proxies_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 3 Proxied_host A #CARD# NULL NULL BTREE def mysql proxies_priv 0 mysql PRIMARY 4 Proxied_user A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE -def mysql rpl_slave_state 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql servers 0 mysql PRIMARY 1 Server_name A #CARD# NULL NULL BTREE def mysql tables_priv 1 mysql Grantor 1 Grantor A #CARD# NULL NULL BTREE def mysql tables_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index 67ab8bc5e25..b158c4863df 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -62,6 +62,7 @@ def mysql PRIMARY mysql columns_priv def mysql PRIMARY mysql db def mysql PRIMARY mysql event def mysql PRIMARY mysql func +def mysql PRIMARY mysql gtid_slave_pos def mysql PRIMARY mysql help_category def mysql name mysql help_category def mysql PRIMARY mysql help_keyword @@ -76,7 +77,6 @@ def mysql PRIMARY mysql plugin def mysql PRIMARY mysql proc def mysql PRIMARY mysql procs_priv def mysql PRIMARY mysql proxies_priv -def mysql PRIMARY mysql rpl_slave_state def mysql PRIMARY mysql servers def mysql PRIMARY mysql table_stats def mysql PRIMARY mysql tables_priv diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result index 37a3465dc72..e9862caba3a 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result @@ -12,6 +12,7 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY def mysql name mysql help_keyword UNIQUE @@ -26,7 +27,6 @@ def mysql PRIMARY mysql plugin PRIMARY KEY def mysql PRIMARY mysql proc PRIMARY KEY def mysql PRIMARY mysql procs_priv PRIMARY KEY def mysql PRIMARY mysql proxies_priv PRIMARY KEY -def mysql PRIMARY mysql rpl_slave_state PRIMARY KEY def mysql PRIMARY mysql servers PRIMARY KEY def mysql PRIMARY mysql tables_priv PRIMARY KEY def mysql PRIMARY mysql table_stats PRIMARY KEY diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result index 453a6e9bd1a..add26d13224 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result @@ -12,6 +12,7 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY def mysql name mysql help_keyword UNIQUE @@ -26,7 +27,6 @@ def mysql PRIMARY mysql plugin PRIMARY KEY def mysql PRIMARY mysql proc PRIMARY KEY def mysql PRIMARY mysql procs_priv PRIMARY KEY def mysql PRIMARY mysql proxies_priv PRIMARY KEY -def mysql PRIMARY mysql rpl_slave_state PRIMARY KEY def mysql PRIMARY mysql servers PRIMARY KEY def mysql PRIMARY mysql tables_priv PRIMARY KEY def mysql PRIMARY mysql table_stats PRIMARY KEY @@ -46,6 +46,7 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY def mysql name mysql help_keyword UNIQUE @@ -60,7 +61,6 @@ def mysql PRIMARY mysql plugin PRIMARY KEY def mysql PRIMARY mysql proc PRIMARY KEY def mysql PRIMARY mysql procs_priv PRIMARY KEY def mysql PRIMARY mysql proxies_priv PRIMARY KEY -def mysql PRIMARY mysql rpl_slave_state PRIMARY KEY def mysql PRIMARY mysql servers PRIMARY KEY def mysql PRIMARY mysql tables_priv PRIMARY KEY def mysql PRIMARY mysql table_stats PRIMARY KEY diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql.result b/mysql-test/suite/funcs_1/r/is_tables_mysql.result index c486ff070cd..d6d3d4f629e 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql.result @@ -152,6 +152,29 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql +TABLE_NAME gtid_slave_pos +TABLE_TYPE BASE TABLE +ENGINE MYISAM_OR_MARIA +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION latin1_swedish_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment Replication slave GTID state +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA mysql TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA @@ -405,29 +428,6 @@ user_comment User proxy privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME rpl_slave_state -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed -TABLE_ROWS #TBLR# -AVG_ROW_LENGTH #ARL# -DATA_LENGTH #DL# -MAX_DATA_LENGTH #MDL# -INDEX_LENGTH #IL# -DATA_FREE #DF# -AUTO_INCREMENT NULL -CREATE_TIME #CRT# -UPDATE_TIME #UT# -CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci -CHECKSUM NULL -CREATE_OPTIONS #CO# -TABLE_COMMENT #TC# -user_comment Replication slave GTID state -Separator ----------------------------------------------------- -TABLE_CATALOG def -TABLE_SCHEMA mysql TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result index 2f9083aeb63..504be66a597 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result @@ -152,6 +152,29 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql +TABLE_NAME gtid_slave_pos +TABLE_TYPE BASE TABLE +ENGINE MYISAM_OR_MARIA +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION latin1_swedish_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment Replication slave GTID state +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA mysql TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA @@ -405,29 +428,6 @@ user_comment User proxy privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME rpl_slave_state -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed -TABLE_ROWS #TBLR# -AVG_ROW_LENGTH #ARL# -DATA_LENGTH #DL# -MAX_DATA_LENGTH #MDL# -INDEX_LENGTH #IL# -DATA_FREE #DF# -AUTO_INCREMENT NULL -CREATE_TIME #CRT# -UPDATE_TIME #UT# -CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci -CHECKSUM NULL -CREATE_OPTIONS #CO# -TABLE_COMMENT #TC# -user_comment Replication slave GTID state -Separator ----------------------------------------------------- -TABLE_CATALOG def -TABLE_SCHEMA mysql TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA @@ -812,6 +812,29 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql +TABLE_NAME gtid_slave_pos +TABLE_TYPE BASE TABLE +ENGINE MYISAM_OR_MARIA +VERSION 10 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION latin1_swedish_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment Replication slave GTID state +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA mysql TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA @@ -1065,29 +1088,6 @@ user_comment User proxy privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME rpl_slave_state -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed -TABLE_ROWS #TBLR# -AVG_ROW_LENGTH #ARL# -DATA_LENGTH #DL# -MAX_DATA_LENGTH #MDL# -INDEX_LENGTH #IL# -DATA_FREE #DF# -AUTO_INCREMENT NULL -CREATE_TIME #CRT# -UPDATE_TIME #UT# -CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci -CHECKSUM NULL -CREATE_OPTIONS #CO# -TABLE_COMMENT #TC# -user_comment Replication slave GTID state -Separator ----------------------------------------------------- -TABLE_CATALOG def -TABLE_SCHEMA mysql TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA diff --git a/mysql-test/suite/multi_source/gtid.result b/mysql-test/suite/multi_source/gtid.result index 2aeec5835f7..651b9873369 100644 --- a/mysql-test/suite/multi_source/gtid.result +++ b/mysql-test/suite/multi_source/gtid.result @@ -69,13 +69,13 @@ Last_SQL_Errno 0 Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id 3 -Using_Gtid 0 +Using_Gtid No Retried_transactions 0 Max_relay_log_size 1073741824 Executed_log_entries 25 Slave_received_heartbeats 0 Slave_heartbeat_period 60.000 -Gtid_Pos 1-1-4,2-2-3 +Gtid_Slave_Pos 1-1-4,2-2-3 *** Now move slave2 to replicate from both master1 and master2 instead of just slave1 *** STOP ALL SLAVES; Warnings: @@ -84,8 +84,8 @@ INSERT INTO t1 VALUES (2, "switch1"); INSERT INTO t3 VALUES (102, "switch1 a"); INSERT INTO t2 VALUES (2, "switch1"); INSERT INTO t3 VALUES (202, "switch1 b"); -CHANGE MASTER 'slave1' TO master_port=MYPORT_1, master_host='127.0.0.1', master_user='root', master_use_gtid=1; -CHANGE MASTER 'slave2' TO master_port=MYPORT_2, master_host='127.0.0.1', master_user='root', master_use_gtid=1; +CHANGE MASTER 'slave1' TO master_port=MYPORT_1, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; +CHANGE MASTER 'slave2' TO master_port=MYPORT_2, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; SET default_master_connection = 'slave1'; START SLAVE; include/wait_for_slave_to_start.inc @@ -102,7 +102,7 @@ INSERT INTO t3 VALUES (203, "switch 2 b"); STOP SLAVE 'slave2'; INSERT INTO t2 VALUES (4, "switch 3"); INSERT INTO t3 VALUES (204, "switch 3 b"); -CHANGE MASTER TO master_port=MYPORT_4, master_host='127.0.0.1', master_user='root', master_use_gtid=1; +CHANGE MASTER TO master_port=MYPORT_4, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; START SLAVE; SELECT * FROM t1 ORDER BY a; a b diff --git a/mysql-test/suite/multi_source/gtid.test b/mysql-test/suite/multi_source/gtid.test index d6b84fb7f3e..0ab486b1f41 100644 --- a/mysql-test/suite/multi_source/gtid.test +++ b/mysql-test/suite/multi_source/gtid.test @@ -75,9 +75,9 @@ INSERT INTO t3 VALUES (202, "switch1 b"); --connection slave2 --replace_result $SERVER_MYPORT_1 MYPORT_1 -eval CHANGE MASTER 'slave1' TO master_port=$SERVER_MYPORT_1, master_host='127.0.0.1', master_user='root', master_use_gtid=1; +eval CHANGE MASTER 'slave1' TO master_port=$SERVER_MYPORT_1, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; --replace_result $SERVER_MYPORT_2 MYPORT_2 -eval CHANGE MASTER 'slave2' TO master_port=$SERVER_MYPORT_2, master_host='127.0.0.1', master_user='root', master_use_gtid=1; +eval CHANGE MASTER 'slave2' TO master_port=$SERVER_MYPORT_2, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; SET default_master_connection = 'slave1'; START SLAVE; --source include/wait_for_slave_to_start.inc @@ -118,7 +118,7 @@ INSERT INTO t3 VALUES (204, "switch 3 b"); --connection slave1 --replace_result $SERVER_MYPORT_4 MYPORT_4 -eval CHANGE MASTER TO master_port=$SERVER_MYPORT_4, master_host='127.0.0.1', master_user='root', master_use_gtid=1; +eval CHANGE MASTER TO master_port=$SERVER_MYPORT_4, master_host='127.0.0.1', master_user='root', master_use_gtid=current_pos; START SLAVE; --let $wait_condition= SELECT (SELECT COUNT(*) FROM t1)=3 AND (SELECT COUNT(*) FROM t2)=4 AND (SELECT COUNT(*) FROM t3)=7 --source include/wait_condition.inc diff --git a/mysql-test/suite/multi_source/info_logs.result b/mysql-test/suite/multi_source/info_logs.result index b5b887b0626..d2144cb8a1b 100644 --- a/mysql-test/suite/multi_source/info_logs.result +++ b/mysql-test/suite/multi_source/info_logs.result @@ -84,17 +84,17 @@ MASTER 2.2 # EOF # show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000002 599 master-bin.000001 Yes Yes 0 0 311 886 None 0 No 0 No 0 0 1 0 0 1073741824 7 0 60.000 -MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 2 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000002 599 master-bin.000001 Yes Yes 0 0 311 886 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 include/wait_for_slave_to_start.inc set default_master_connection = 'MASTER 2.2'; include/wait_for_slave_to_start.inc set default_master_connection = ''; show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000004 536 master-bin.000001 Yes Yes 0 0 311 823 None 0 No 0 No 0 0 1 0 0 1073741824 6 0 60.000 -MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000004 536 master-bin.000001 Yes Yes 0 0 311 842 None 0 No 0 No 0 0 2 0 0 1073741824 6 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000004 536 master-bin.000001 Yes Yes 0 0 311 823 None 0 No 0 No 0 0 1 No 0 1073741824 6 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000004 536 master-bin.000001 Yes Yes 0 0 311 842 None 0 No 0 No 0 0 2 No 0 1073741824 6 0 60.000 # # List of files matching '*info*' pattern # after slave server restart diff --git a/mysql-test/suite/multi_source/multisource.result b/mysql-test/suite/multi_source/multisource.result index 6aa90109d4e..dfa3b1e1bed 100644 --- a/mysql-test/suite/multi_source/multisource.result +++ b/mysql-test/suite/multi_source/multisource.result @@ -11,13 +11,13 @@ set default_master_connection = 'master1'; include/wait_for_slave_to_start.inc show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 0 +Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 0 +Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos +master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 drop database if exists db1; create database db1; use db1; @@ -75,9 +75,9 @@ master_user='root'; start slave; include/wait_for_slave_to_start.inc show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin.000002 599 master-bin.000001 Yes Yes 0 0 311 897 None 0 No 0 No 0 0 2 0 0 1073741824 7 0 60.000 0-1-4 -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 986 mysqld-relay-bin-master1.000002 1274 master-bin.000001 Yes Yes 0 0 986 1580 None 0 No 0 No 0 0 1 0 0 1073741824 17 0 60.000 0-1-4 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin.000002 599 master-bin.000001 Yes Yes 0 0 311 897 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 0-1-4 +master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 986 mysqld-relay-bin-master1.000002 1274 master-bin.000001 Yes Yes 0 0 986 1580 None 0 No 0 No 0 0 1 No 0 1073741824 17 0 60.000 0-1-4 insert into t1 (f1) values ('three'); drop database if exists db2; create database db2; @@ -105,9 +105,9 @@ master-bin.000002 367 insert into t1 (f1) values ('four'); create table db1.t3 (f1 int) engine=InnoDB; show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 919 mysqld-relay-bin.000002 1207 master-bin.000001 Yes Yes 0 0 919 1505 None 0 No 0 No 0 0 2 0 0 1073741824 17 0 60.000 0-1-7 -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000002 740 mysqld-relay-bin-master1.000004 1028 master-bin.000002 Yes Yes 0 0 740 1378 None 0 No 0 No 0 0 1 0 0 1073741824 37 0 60.000 0-1-7 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 919 mysqld-relay-bin.000002 1207 master-bin.000001 Yes Yes 0 0 919 1505 None 0 No 0 No 0 0 2 No 0 1073741824 17 0 60.000 0-1-7 +master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000002 740 mysqld-relay-bin-master1.000004 1028 master-bin.000002 Yes Yes 0 0 740 1378 None 0 No 0 No 0 0 1 No 0 1073741824 37 0 60.000 0-1-7 select * from db1.t1; i f1 1 one diff --git a/mysql-test/suite/multi_source/reset_master_slave.inc b/mysql-test/suite/multi_source/reset_master_slave.inc index 2678602291f..375f1678ab3 100644 --- a/mysql-test/suite/multi_source/reset_master_slave.inc +++ b/mysql-test/suite/multi_source/reset_master_slave.inc @@ -23,7 +23,7 @@ while ($con_name != 'No such row') --error 0,ER_FLUSH_MASTER_BINLOG_CLOSED reset master; -set global gtid_pos=''; +set global gtid_slave_pos=''; eval set default_master_connection = '$default_master'; --source include/end_include_file.inc diff --git a/mysql-test/suite/multi_source/reset_slave.result b/mysql-test/suite/multi_source/reset_slave.result index 7d2152a43f2..88bc934afaf 100644 --- a/mysql-test/suite/multi_source/reset_slave.result +++ b/mysql-test/suite/multi_source/reset_slave.result @@ -11,14 +11,14 @@ insert into t1 values (1),(2); stop slave 'master1'; show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid - 127.0.0.1 root MYPORT_1 60 master-bin.000001 800 mysqld-relay-bin-master1.000002 1088 master-bin.000001 No No 0 0 800 1394 None 0 No NULL No 0 0 1 0 + 127.0.0.1 root MYPORT_1 60 master-bin.000001 800 mysqld-relay-bin-master1.000002 1088 master-bin.000001 No No 0 0 800 1394 None 0 No NULL No 0 0 1 No mysqld-relay-bin-master1.000001 mysqld-relay-bin-master1.000002 mysqld-relay-bin-master1.index reset slave 'master1'; show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid - 127.0.0.1 root MYPORT_1 60 4 1088 No No 0 0 0 1394 None 0 No NULL No 0 0 1 0 + 127.0.0.1 root MYPORT_1 60 4 1088 No No 0 0 0 1394 None 0 No NULL No 0 0 1 No reset slave 'master1' all; show slave 'master1' status; ERROR HY000: There is no master connection 'master1' diff --git a/mysql-test/suite/multi_source/simple.result b/mysql-test/suite/multi_source/simple.result index fa738fbf712..525aaa4b0cc 100644 --- a/mysql-test/suite/multi_source/simple.result +++ b/mysql-test/suite/multi_source/simple.result @@ -10,9 +10,9 @@ Note 1937 SLAVE 'slave2' started include/wait_for_slave_to_start.inc set default_master_connection = ''; show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos -slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-slave1.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 1 0 0 1073741824 7 0 60.000 -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos +slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-slave1.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 start all slaves; stop slave 'slave1'; show slave 'slave1' status; @@ -56,22 +56,22 @@ Last_SQL_Errno 0 Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id 1 -Using_Gtid 0 +Using_Gtid No reset slave 'slave1'; show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos -slave1 127.0.0.1 root MYPORT_1 60 4 599 No No 0 0 0 904 None 0 No NULL No 0 0 1 0 0 1073741824 7 0 60.000 -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos +slave1 127.0.0.1 root MYPORT_1 60 4 599 No No 0 0 0 904 None 0 No NULL No 0 0 1 No 0 1073741824 7 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 reset slave 'slave1' all; show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 stop all slaves; Warnings: Note 1938 SLAVE 'slave2' stopped show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos -slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 No No 0 0 311 904 None 0 No NULL No 0 0 2 0 0 1073741824 7 0 60.000 +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos +slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 No No 0 0 311 904 None 0 No NULL No 0 0 2 No 0 1073741824 7 0 60.000 stop all slaves; include/reset_master_slave.inc include/reset_master_slave.inc diff --git a/mysql-test/suite/multi_source/syntax.result b/mysql-test/suite/multi_source/syntax.result index 000fcad1283..2b63db714ef 100644 --- a/mysql-test/suite/multi_source/syntax.result +++ b/mysql-test/suite/multi_source/syntax.result @@ -5,7 +5,7 @@ Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File show slave '' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Pos +Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos # # Check error handling # diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result index b1e53a4a0b5..f98a3bf322d 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result @@ -49,7 +49,7 @@ include/stop_slave.inc INSERT INTO t1 VALUES (5, "m1a"); INSERT INTO t2 VALUES (5, "i1a"); CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc SELECT * FROM t1 ORDER BY a; a b @@ -68,7 +68,7 @@ a b *** Now move B to D (C is still replicating from B) *** include/stop_slave.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc UPDATE t2 SET b="j1a" WHERE a=5; SELECT * FROM t1 ORDER BY a; @@ -92,7 +92,7 @@ INSERT INTO t2 VALUES (6, "i6b"); INSERT INTO t2 VALUES (7, "i7b"); COMMIT; CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc SELECT * FROM t2 ORDER BY a; a b diff --git a/mysql-test/suite/rpl/r/rpl_gtid_crash.result b/mysql-test/suite/rpl/r/rpl_gtid_crash.result index b4c2056f45a..ccc64b70803 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_crash.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_crash.result @@ -3,12 +3,12 @@ include/rpl_init.inc [topology=1->2] call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, 0); include/stop_slave.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; INSERT INTO t1 VALUES (2,1); INSERT INTO t1 VALUES (3,1); include/start_slave.inc @@ -20,7 +20,7 @@ DROP TABLE t1; *** Test crashing the master mysqld and check that binlog state is recovered. *** include/stop_slave.inc RESET MASTER; -SET GLOBAL gtid_pos=''; +SET GLOBAL gtid_slave_pos=''; RESET MASTER; SHOW BINLOG EVENTS IN 'master-bin.000001' LIMIT 1,1; Log_name Pos Event_type Server_id End_log_pos Info diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result index 0882f8e1872..fe69c83615e 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result @@ -1,30 +1,30 @@ include/master-slave.inc [connection master] -*** Test that we check against incorrect table definition for mysql.rpl_slave_state *** +*** Test that we check against incorrect table definition for mysql.gtid_slave_pos *** CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no VARCHAR(20); +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no VARCHAR(20); START SLAVE; INSERT INTO t1 VALUES (1); -CALL mtr.add_suppression("Slave: Failed to open mysql.rpl_slave_state"); +CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos"); include/wait_for_slave_sql_error.inc [errno=1942] include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id, domain_id); +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id, domain_id); START SLAVE; include/wait_for_slave_sql_error.inc [errno=1942] include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; START SLAVE; include/wait_for_slave_sql_error.inc [errno=1942] include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id); +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id); START SLAVE; include/wait_for_slave_sql_error.inc [errno=1942] include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (domain_id, sub_id); +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (domain_id, sub_id); include/start_slave.inc SELECT * FROM t1; a @@ -38,13 +38,22 @@ SET sql_log_bin = 0; INSERT INTO t1 VALUES (2); SET sql_log_bin = 1; INSERT INTO t1 VALUES (3); -CHANGE MASTER TO master_use_gtid=1; -SET GLOBAL gtid_pos = "0-1-1"; -ERROR HY000: Requested GTID_POS 0-1-1 conflicts with the binary log which contains a more recent GTID 0-2-11. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog -SET GLOBAL gtid_pos = ""; -ERROR HY000: Requested GTID_POS contains no value for replication domain 0. This conflicts with the binary log which contains GTID 0-2-11. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog +CHANGE MASTER TO master_use_gtid=current_pos; +BEGIN; +SET GLOBAL gtid_slave_pos = "100-100-100"; +ERROR 25000: You are not allowed to execute this command in a transaction +INSERT INTO t1 VALUES (100); +SET GLOBAL gtid_slave_pos = "100-100-100"; +ERROR 25000: You are not allowed to execute this command in a transaction +ROLLBACK; +SET GLOBAL gtid_slave_pos = "0-1-1"; +Warnings: +Warning 1947 Specified GTID 0-1-1 conflicts with the binary log which contains a more recent GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. +SET GLOBAL gtid_slave_pos = ""; +Warnings: +Warning 1948 Specified value for @@gtid_slave_pos contains no value for replication domain 0. This conflicts with the binary log which contains GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. RESET MASTER; -SET GLOBAL gtid_pos = "0-1-1"; +SET GLOBAL gtid_slave_pos = "0-1-1"; START SLAVE; SELECT * FROM t1 ORDER BY a; a @@ -54,7 +63,7 @@ a 4 *** Test slave requesting a GTID that is not present in the master's binlog *** include/stop_slave.inc -SET GLOBAL gtid_pos = "0-1-3"; +SET GLOBAL gtid_slave_pos = "0-1-3"; START SLAVE; SET sql_log_bin=0; CALL mtr.add_suppression("Got fatal error .* from master when reading data from binary log: 'Error: connecting slave requested to start from GTID .*, which is not in the master's binlog'"); @@ -63,9 +72,9 @@ include/wait_for_slave_io_error.inc [errno=1236] Slave_IO_State = '' Last_IO_Errno = '1236' Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Error: connecting slave requested to start from GTID 0-1-3, which is not in the master's binlog'' -Using_Gtid = '1' +Using_Gtid = 'Current_Pos' include/stop_slave.inc -SET GLOBAL gtid_pos = "0-1-2"; +SET GLOBAL gtid_slave_pos = "0-1-2"; START SLAVE; include/wait_for_slave_to_start.inc INSERT INTO t1 VALUES (5); diff --git a/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result index 1f600b2a536..0a55fe5a026 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result @@ -1,5 +1,5 @@ include/rpl_init.inc [topology=1->2, 1->3, 1->4, 1->5] -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB; CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) RETURNS VARCHAR(100) DETERMINISTIC @@ -10,13 +10,13 @@ SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); RETURN s; END| include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; SET gtid_domain_id= 1; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); @@ -310,7 +310,7 @@ a b 3 5 *** Now let the old master join up as slave. *** CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2, -master_user = "root", master_use_gtid = 1; +master_user = "root", master_use_gtid = current_pos; include/start_slave.inc SELECT * FROM t1 ORDER BY a; a diff --git a/mysql-test/suite/rpl/r/rpl_gtid_mdev4473.result b/mysql-test/suite/rpl/r/rpl_gtid_mdev4473.result index 1289bbb7e20..f5baa3284f3 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_mdev4473.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_mdev4473.result @@ -8,7 +8,7 @@ include/stop_slave.inc include/wait_for_slave_to_stop.inc reset slave all; CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2, -master_user='root', MASTER_USE_GTID=1; +master_user='root', MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc include/wait_for_slave_to_start.inc flush logs; @@ -16,7 +16,7 @@ insert into t1 values (3); insert into t1 values (4); flush logs; CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc select * from t1 order by n; n @@ -47,11 +47,11 @@ include/stop_slave.inc include/wait_for_slave_to_stop.inc reset slave all; CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, -master_user = 'root', MASTER_USE_GTID=1; +master_user = 'root', MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc include/stop_slave.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_mdev4474.result b/mysql-test/suite/rpl/r/rpl_gtid_mdev4474.result new file mode 100644 index 00000000000..37b5ac7ca9a --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_mdev4474.result @@ -0,0 +1,63 @@ +include/rpl_init.inc [topology=1->2->1] +# +# For now we'll only have 1->2 running +# +# Server 1 +# Stop replication 2->1 +include/stop_slave.inc +# +# Server 2 +# Use GTID for replication 1->2 +include/stop_slave.inc +change master to master_use_gtid=slave_pos; +include/start_slave.inc +# +# Create some 0-1-* and 0-2-* events in binlog of server 2 +connection server_1; +create table t1 (i int) engine=InnoDB; +insert into t1 values (1); +connection server_2; +create table t2 (i int) engine=InnoDB; +connection server_1; +insert into t1 values (2); +connection server_2; +insert into t2 values (1); +# +# All events are present in the binlog of server 2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Query # # use `test`; create table t1 (i int) engine=InnoDB +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# +slave-bin.000001 # Query # # use `test`; insert into t1 values (1) +slave-bin.000001 # Xid # # COMMIT /* XID */ +slave-bin.000001 # Gtid # # GTID #-#-# +slave-bin.000001 # Query # # use `test`; create table t2 (i int) engine=InnoDB +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# +slave-bin.000001 # Query # # use `test`; insert into t1 values (2) +slave-bin.000001 # Xid # # COMMIT /* XID */ +slave-bin.000001 # Gtid # # BEGIN GTID #-#-# +slave-bin.000001 # Query # # use `test`; insert into t2 values (1) +slave-bin.000001 # Xid # # COMMIT /* XID */ +# +# Server 1 +# Start replication 2->1 using GTID, +change master to master_use_gtid=slave_pos; +include/start_slave.inc +select * from t1 order by i; +i +1 +2 +select * from t2 order by i; +i +1 +select * from t1 order by i; +i +1 +2 +select * from t2 order by i; +i +1 +drop table t1; +drop table t2; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_nobinlog.result b/mysql-test/suite/rpl/r/rpl_gtid_nobinlog.result index 265d0ca185c..bc7be2a30b7 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_nobinlog.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_nobinlog.result @@ -24,7 +24,7 @@ slave-bin.000001 # Gtid # # BEGIN GTID #-#-# slave-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4, 2) slave-bin.000001 # Query # # COMMIT CHANGE MASTER TO master_host = '127.0.0.1', master_port = SLAVE_PORT, -master_user = 'root', master_use_gtid = 1; +master_user = 'root', master_use_gtid = current_pos; START SLAVE; SELECT * FROM t1 ORDER BY a; a b @@ -37,7 +37,7 @@ RESET SLAVE; INSERT INTO t1 VALUES (5, 1); INSERT INTO t1 VALUES (6, 1); CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -master_use_gtid = 1; +master_use_gtid = current_pos; START SLAVE; SELECT * FROM t1 ORDER BY a; a b diff --git a/mysql-test/suite/rpl/r/rpl_gtid_startpos.result b/mysql-test/suite/rpl/r/rpl_gtid_startpos.result index 4530542f080..d226ffa68f7 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_startpos.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_startpos.result @@ -6,9 +6,9 @@ RESET SLAVE; RESET MASTER; FLUSH LOGS; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc SELECT * FROM t1; a @@ -24,9 +24,9 @@ include/wait_for_purge.inc "master-bin.000003" show binary logs; Log_name File_size master-bin.000003 # -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; START SLAVE; include/wait_for_slave_io_error.inc [errno=1236] include/stop_slave.inc @@ -40,12 +40,12 @@ a SET sql_log_bin=0; call mtr.add_suppression('Could not find GTID state requested by slave in any binlog files'); SET sql_log_bin=1; -*** Test that we give error when explict @@gtid_pos=xxx that conflicts with what is in our binary log *** +*** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log *** include/stop_slave.inc INSERT INTO t1 VALUES(3); -SET GLOBAL gtid_pos='0-1-3'; +SET GLOBAL gtid_slave_pos='0-1-3'; CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, -MASTER_USE_GTID=1; +MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc SELECT * FROM t1 ORDER by a; a @@ -56,10 +56,11 @@ include/stop_slave.inc INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (10); DELETE FROM t1 WHERE a=10; -SET GLOBAL gtid_pos='0-1-4'; -ERROR HY000: Requested GTID_POS 0-1-4 conflicts with the binary log which contains a more recent GTID 0-2-6. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog +SET GLOBAL gtid_slave_pos='0-1-4'; +Warnings: +Warning 1947 Specified GTID 0-1-4 conflicts with the binary log which contains a more recent GTID 0-2-6. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. RESET MASTER; -SET GLOBAL gtid_pos='0-1-4'; +SET GLOBAL gtid_slave_pos='0-1-4'; START SLAVE; SELECT * FROM t1 ORDER by a; a @@ -73,8 +74,8 @@ include/stop_slave.inc RESET SLAVE ALL; RESET MASTER; RESET MASTER; -SET GLOBAL gtid_pos=''; -CHANGE MASTER TO master_host='127.0.0.1', master_port=MASTER_PORT, master_user='root', master_use_gtid=1; +SET GLOBAL gtid_slave_pos=''; +CHANGE MASTER TO master_host='127.0.0.1', master_port=MASTER_PORT, master_user='root', master_use_gtid=current_pos; include/start_slave.inc CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (1); @@ -89,14 +90,15 @@ SELECT * FROM t1 ORDER BY a; a 1 2 -*** MDEV-4329: GTID_POS='' is not checked for conflicts with binlog *** +*** MDEV-4329: GTID_SLAVE_POS='' is not checked for conflicts with binlog *** include/stop_slave.inc DROP TABLE t1; RESET SLAVE; -SET GLOBAL gtid_pos=""; -ERROR HY000: Requested GTID_POS contains no value for replication domain 0. This conflicts with the binary log which contains GTID 0-2-4. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog +SET GLOBAL gtid_slave_pos=""; +Warnings: +Warning 1948 Specified value for @@gtid_slave_pos contains no value for replication domain 0. This conflicts with the binary log which contains GTID 0-2-4. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. RESET MASTER; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; include/start_slave.inc SELECT * FROM t1 ORDER BY a; a @@ -107,7 +109,7 @@ SET SQL_LOG_BIN=0; DROP TABLE t1; SET SQL_LOG_BIN=1; RESET SLAVE; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; include/start_slave.inc SELECT * FROM t1 ORDER BY a; a @@ -116,11 +118,11 @@ a *** Test that RESET SLAVE clears the Using_Gtid flag. *** include/stop_slave.inc RESET SLAVE; -Using_Gtid = '0' +Using_Gtid = 'No' START SLAVE; include/wait_for_slave_sql_error.inc [errno=1050] STOP SLAVE IO_THREAD; -CHANGE MASTER TO MASTER_USE_GTID=1; +CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS; include/start_slave.inc INSERT INTO t1 VALUES(3); SELECT * FROM t1 ORDER BY a; @@ -154,7 +156,7 @@ a *** Test modifying binlog on slave and the effect on GTID state. *** include/stop_slave.inc RESET MASTER; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; RESET MASTER; TRUNCATE TABLE t1; INSERT INTO t1 VALUES (10); @@ -162,28 +164,29 @@ include/start_slave.inc SELECT * FROM t1; a 10 -SELECT '1' AS Using_Gtid; +SELECT 'Current_Pos' AS Using_Gtid; Using_Gtid -1 -SELECT '0-1-2' AS Gtid_Pos; -Gtid_Pos +Current_Pos +SELECT '0-1-2' AS Gtid_Slave_Pos; +Gtid_Slave_Pos 0-1-2 UPDATE t1 SET a=9 WHERE a=10; UPDATE t1 SET a=10 WHERE a=9; -SELECT '0-2-4' AS Gtid_Pos; -Gtid_Pos +SELECT '0-2-4' AS Gtid_Slave_Pos; +Gtid_Slave_Pos 0-2-4 include/stop_slave.inc -SET GLOBAL gtid_pos='0-1-2'; -ERROR HY000: Requested GTID_POS 0-1-2 conflicts with the binary log which contains a more recent GTID 0-2-4. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog +SET GLOBAL gtid_slave_pos='0-1-2'; +Warnings: +Warning 1947 Specified GTID 0-1-2 conflicts with the binary log which contains a more recent GTID 0-2-4. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. RESET MASTER; -SELECT '0-1-2' AS Gtid_Pos; -Gtid_Pos +SELECT '0-1-2' AS Gtid_Slave_Pos; +Gtid_Slave_Pos 0-1-2 -SET GLOBAL gtid_pos='0-1-2'; +SET GLOBAL gtid_slave_pos='0-1-2'; include/start_slave.inc -SELECT '0-1-2' AS Gtid_Pos; -Gtid_Pos +SELECT '0-1-2' AS Gtid_Slave_Pos; +Gtid_Slave_Pos 0-1-2 DROP TABLE t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index 0bb963cc2ab..50a7195a288 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -4,8 +4,8 @@ CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (1); include/stop_slave.inc Master_Log_File = 'master-bin.000001' -Using_Gtid = '0' -CHANGE MASTER TO master_use_gtid=1; +Using_Gtid = 'No' +CHANGE MASTER TO master_use_gtid=current_pos; FLUSH LOGS; include/wait_for_purge.inc "master-bin.000002" show binary logs; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_until.result b/mysql-test/suite/rpl/r/rpl_gtid_until.result index 382da1b3844..44573a29794 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_until.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_until.result @@ -1,5 +1,5 @@ include/rpl_init.inc [topology=1->2] -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) RETURNS VARCHAR(100) DETERMINISTIC BEGIN @@ -21,7 +21,7 @@ ERROR HY000: Slave is already running include/stop_slave_io.inc START SLAVE UNTIL master_gtid_pos = ""; ERROR HY000: START SLAVE UNTIL master_gtid_pos requires that slave is using GTID -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); @@ -46,7 +46,7 @@ a include/stop_slave.inc START SLAVE UNTIL master_gtid_pos = "1-10-100,2-20-200"; include/wait_for_slave_to_start.inc -Using_Gtid = '1' +Using_Gtid = 'Current_Pos' Until_Condition = 'Gtid' include/stop_slave.inc include/start_slave.inc @@ -168,7 +168,7 @@ a include/stop_slave.inc CREATE TABLE t3 (a INT); DROP TABLE t3; -START SLAVE UNTIL master_gtid_pos='1-1-15,0-1-16,2-1-14'; +START SLAVE UNTIL master_gtid_pos='1-1-15,2-1-14,0-1-16'; include/wait_for_slave_to_stop.inc SHOW CREATE TABLE t3; Table Create Table @@ -180,7 +180,7 @@ include/start_slave.inc include/stop_slave.inc RESET SLAVE ALL; RESET MASTER; -SET GLOBAL gtid_pos=''; +SET GLOBAL gtid_slave_pos=''; RESET MASTER; INSERT INTO t1 VALUES (10); INSERT INTO t1 VALUES (11); @@ -189,7 +189,7 @@ DELETE FROM t1 WHERE a >= 10; RESET MASTER; INSERT INTO t1 VALUES (10); CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, -master_user = "root", master_use_gtid = 1; +master_user = "root", master_use_gtid = current_pos; START SLAVE UNTIL master_gtid_pos = '0-1-2'; include/wait_for_slave_to_start.inc INSERT INTO t1 VALUES (11); diff --git a/mysql-test/suite/rpl/r/rpl_sync.result b/mysql-test/suite/rpl/r/rpl_sync.result index 3e825a111aa..84c100970e4 100644 --- a/mysql-test/suite/rpl/r/rpl_sync.result +++ b/mysql-test/suite/rpl/r/rpl_sync.result @@ -3,7 +3,7 @@ include/master-slave.inc [connection master] call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001"); -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; flush tables; CREATE TABLE t1(a INT, PRIMARY KEY(a)) engine=innodb; insert into t1(a) values(1); diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test index 9513acb17b6..070e0daa403 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -49,7 +49,7 @@ save_master_pos; connection server_4; --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc sync_with_master; SELECT * FROM t1 ORDER BY a; @@ -60,7 +60,7 @@ connection server_2; --source include/stop_slave.inc --replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc connection server_4; @@ -85,7 +85,7 @@ COMMIT; connection server_3; --replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc # This time, let's sync up without reference to binlog on D. --let $wait_condition= SELECT COUNT(*) = 7 FROM t2 @@ -93,7 +93,7 @@ eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4, SELECT * FROM t2 ORDER BY a; --echo *** Now change everything back to what it was, to make rpl_end.inc happy -# Also check that MASTER_USE_GTID=1 is still enabled. +# Also check that MASTER_USE_GTID=CURRENT_POS is still enabled. connection server_2; # We need to sync up server_2 before switching. If it happened to have reached # the point 'UPDATE t2 SET b="j1a" WHERE a=5' it will fail to connect to diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test index d78001aa69b..804aae1114d 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test @@ -13,7 +13,7 @@ call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, 0); --save_master_pos @@ -23,7 +23,7 @@ INSERT INTO t1 VALUES (1, 0); --source include/stop_slave.inc --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --connection server_1 INSERT INTO t1 VALUES (2,1); @@ -79,7 +79,7 @@ DROP TABLE t1; --sync_with_master --source include/stop_slave.inc RESET MASTER; -SET GLOBAL gtid_pos=''; +SET GLOBAL gtid_slave_pos=''; --connection server_1 RESET MASTER; @@ -130,7 +130,7 @@ SELECT * FROM t1 ORDER BY a; --echo *** Test crashing slave at various points and check that it recovers crash-safe. *** -# Crash the slave just before updating mysql.rpl_slave_state table. +# Crash the slave just before updating mysql.gtid_slave_pos table. --source include/stop_slave.inc --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test index 98b9e8373d5..c5f695fd5a1 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test @@ -2,47 +2,47 @@ --source include/have_debug.inc --source include/master-slave.inc ---echo *** Test that we check against incorrect table definition for mysql.rpl_slave_state *** +--echo *** Test that we check against incorrect table definition for mysql.gtid_slave_pos *** --connection master CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; --sync_slave_with_master --connection slave --source include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no VARCHAR(20); +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no VARCHAR(20); START SLAVE; --connection master INSERT INTO t1 VALUES (1); --connection slave -CALL mtr.add_suppression("Slave: Failed to open mysql.rpl_slave_state"); +CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos"); --let $slave_sql_errno=1942 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id, domain_id); +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id, domain_id); START SLAVE; --let $slave_sql_errno=1942 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; START SLAVE; --let $slave_sql_errno=1942 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (sub_id); +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id); START SLAVE; --let $slave_sql_errno=1942 --source include/wait_for_slave_sql_error.inc --source include/stop_slave.inc -ALTER TABLE mysql.rpl_slave_state DROP PRIMARY KEY; -ALTER TABLE mysql.rpl_slave_state ADD PRIMARY KEY (domain_id, sub_id); +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (domain_id, sub_id); --source include/start_slave.inc --connection master @@ -69,13 +69,22 @@ INSERT INTO t1 VALUES (2); SET sql_log_bin = 1; INSERT INTO t1 VALUES (3); -CHANGE MASTER TO master_use_gtid=1; ---error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG -SET GLOBAL gtid_pos = "0-1-1"; ---error ER_MASTER_GTID_POS_MISSING_DOMAIN -SET GLOBAL gtid_pos = ""; +CHANGE MASTER TO master_use_gtid=current_pos; +# Most not change @@GLOBAL.gtid_slave_pos in the middle of a transaction. +BEGIN; +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL gtid_slave_pos = "100-100-100"; +INSERT INTO t1 VALUES (100); +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL gtid_slave_pos = "100-100-100"; +ROLLBACK; + +# In gtid non-strict mode, we get warnings for setting @@gtid_slave_pos back +# to earlier than what is in the binlog. +SET GLOBAL gtid_slave_pos = "0-1-1"; +SET GLOBAL gtid_slave_pos = ""; RESET MASTER; -SET GLOBAL gtid_pos = "0-1-1"; +SET GLOBAL gtid_slave_pos = "0-1-1"; START SLAVE; --let $wait_condition= SELECT COUNT(*) = 4 FROM t1 @@ -85,7 +94,7 @@ SELECT * FROM t1 ORDER BY a; --echo *** Test slave requesting a GTID that is not present in the master's binlog *** --source include/stop_slave.inc -SET GLOBAL gtid_pos = "0-1-3"; +SET GLOBAL gtid_slave_pos = "0-1-3"; START SLAVE; SET sql_log_bin=0; @@ -98,7 +107,7 @@ SET sql_log_bin=1; --let $rpl_only_running_threads= 1 --source include/stop_slave.inc -SET GLOBAL gtid_pos = "0-1-2"; +SET GLOBAL gtid_slave_pos = "0-1-2"; START SLAVE; --source include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test index 68935011c20..f3cc4aca135 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test @@ -11,7 +11,7 @@ # using START SLAVE UNTIL master_gtid_pos. --connection server_1 -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB; # Function to extract one GTID from a list. @@ -31,22 +31,22 @@ delimiter ;| --connection server_2 --sync_with_master --source include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; --connection server_3 --sync_with_master --source include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; --connection server_4 --sync_with_master --source include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; --connection server_5 --sync_with_master --source include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; # Create three separate replication streams on master server_1. @@ -59,39 +59,39 @@ CHANGE MASTER TO master_use_gtid=1; SET gtid_domain_id= 1; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; ---let $d1_begin= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d1_begin= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); INSERT INTO t4 VALUES (1, 1); ---let $d1_mid= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d1_mid= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (4); INSERT INTO t4 VALUES (1, 3); ---let $d1_end= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` +--let $d1_end= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` SET gtid_domain_id= 2; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; ---let $d2_begin= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d2_begin= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (2); INSERT INTO t4 VALUES (2, 1); ---let $d2_mid= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d2_mid= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t2 VALUES (3); INSERT INTO t2 VALUES (4); INSERT INTO t4 VALUES (2, 3); ---let $d2_end= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d2_end= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` SET gtid_domain_id= 3; CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; ---let $d3_begin= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` +--let $d3_begin= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t3 VALUES (1); INSERT INTO t3 VALUES (2); INSERT INTO t4 VALUES (3, 1); ---let $d3_mid= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` +--let $d3_mid= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` INSERT INTO t3 VALUES (3); INSERT INTO t3 VALUES (4); INSERT INTO t4 VALUES (3, 3); ---let $d3_end= `SELECT extract_gtid("3", @@GLOBAL.gtid_pos)` +--let $d3_end= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` # Slave server_2 (that will be promoted to master) is in the middle @@ -135,7 +135,7 @@ SELECT * FROM t4 ORDER BY a,b; --echo *** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. *** --connection server_3 ---let $server3_pos= `SELECT @@GLOBAL.gtid_pos` +--let $server3_pos= `SELECT @@GLOBAL.gtid_slave_pos` --connection server_2 --replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3; @@ -147,7 +147,7 @@ SELECT * FROM t3 ORDER BY a; SELECT * FROM t4 ORDER BY a,b; --connection server_4 ---let $server4_pos= `SELECT @@GLOBAL.gtid_pos` +--let $server4_pos= `SELECT @@GLOBAL.gtid_slave_pos` --connection server_2 --replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4; @@ -159,7 +159,7 @@ SELECT * FROM t3 ORDER BY a; SELECT * FROM t4 ORDER BY a,b; --connection server_5 ---let $server5_pos= `SELECT @@GLOBAL.gtid_pos` +--let $server5_pos= `SELECT @@GLOBAL.gtid_slave_pos` --connection server_2 --replace_result $SERVER_MYPORT_5 SERVER_MYPORT_5 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_5; @@ -222,7 +222,7 @@ SELECT * FROM t4 ORDER BY a,b; --connection server_1 --replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, - master_user = "root", master_use_gtid = 1; + master_user = "root", master_use_gtid = current_pos; --source include/start_slave.inc --sync_with_master SELECT * FROM t1 ORDER BY a; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test index 57f1975ed77..01259eb5765 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test @@ -24,7 +24,7 @@ reset slave all; connection server_1; --replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, - master_user='root', MASTER_USE_GTID=1; + master_user='root', MASTER_USE_GTID=CURRENT_POS; source include/start_slave.inc; source include/wait_for_slave_to_start.inc; @@ -38,7 +38,7 @@ save_master_pos; connection server_3; --replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; source include/start_slave.inc; sync_with_master; @@ -56,14 +56,14 @@ reset slave all; connection server_2; --replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, - master_user = 'root', MASTER_USE_GTID=1; + master_user = 'root', MASTER_USE_GTID=CURRENT_POS; source include/start_slave.inc; connection server_3; source include/stop_slave.inc; --replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; source include/start_slave.inc; connection server_1; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf new file mode 100644 index 00000000000..2b9e70c59bc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf @@ -0,0 +1,11 @@ +!include suite/rpl/rpl_1slave_base.cnf +!include include/default_client.cnf + + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test new file mode 100644 index 00000000000..e6016b17717 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test @@ -0,0 +1,76 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_statement.inc +--let $rpl_topology=1->2->1 +--source include/rpl_init.inc + +--echo # +--echo # For now we'll only have 1->2 running + +--echo # +--echo # Server 1 +--echo # Stop replication 2->1 +--connection server_1 +--source include/stop_slave.inc + +--echo # +--echo # Server 2 +--echo # Use GTID for replication 1->2 +--connection server_2 +--source include/stop_slave.inc +change master to master_use_gtid=slave_pos; +--source include/start_slave.inc + +--echo # +--echo # Create some 0-1-* and 0-2-* events in binlog of server 2 + +--enable_connect_log + +--connection server_1 +create table t1 (i int) engine=InnoDB; +insert into t1 values (1); +--save_master_pos + +--connection server_2 +--sync_with_master +create table t2 (i int) engine=InnoDB; +--save_master_pos + +--connection server_1 +insert into t1 values (2); +--save_master_pos + +--connection server_2 +--sync_with_master +insert into t2 values (1); +--save_master_pos + +--disable_connect_log + +--echo # +--echo # All events are present in the binlog of server 2 + +--source include/show_binlog_events.inc + +--echo # +--echo # Server 1 +--echo # Start replication 2->1 using GTID, + +--connection server_1 +change master to master_use_gtid=slave_pos; +--source include/start_slave.inc +--sync_with_master + +select * from t1 order by i; +select * from t2 order by i; + +--connection server_2 +select * from t1 order by i; +select * from t2 order by i; + +--connection server_1 +drop table t1; + +--connection server_2 +drop table t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test index d8073e19fb0..9c9c8090eba 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test @@ -26,7 +26,7 @@ INSERT INTO t1 VALUES (4, 2); --connection server_1 --replace_result $SLAVE_MYPORT SLAVE_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT, - master_user = 'root', master_use_gtid = 1; + master_user = 'root', master_use_gtid = current_pos; START SLAVE; --let $wait_condition= SELECT COUNT(*) = 4 FROM t1 --source include/wait_condition.inc @@ -41,7 +41,7 @@ INSERT INTO t1 VALUES (6, 1); --connection server_2 --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - master_use_gtid = 1; + master_use_gtid = current_pos; START SLAVE; --let $wait_condition= SELECT COUNT(*) = 6 FROM t1 --source include/wait_condition.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test index c4390d3fccc..8dfb60b1b56 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test @@ -16,10 +16,10 @@ CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; --save_master_pos --connection server_2 -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc --sync_with_master SELECT * FROM t1; @@ -43,10 +43,10 @@ INSERT INTO t1 VALUES (2); --source include/show_binary_logs.inc --connection server_2 -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; START SLAVE; --let $slave_io_errno= 1236 --source include/wait_for_slave_io_error.inc @@ -62,17 +62,17 @@ SET sql_log_bin=0; call mtr.add_suppression('Could not find GTID state requested by slave in any binlog files'); SET sql_log_bin=1; ---echo *** Test that we give error when explict @@gtid_pos=xxx that conflicts with what is in our binary log *** +--echo *** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log *** --source include/stop_slave.inc --connection server_1 INSERT INTO t1 VALUES(3); --connection server_2 -SET GLOBAL gtid_pos='0-1-3'; +SET GLOBAL gtid_slave_pos='0-1-3'; --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, - MASTER_USE_GTID=1; + MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc --let $wait_condition= SELECT COUNT(*) = 3 FROM t1 --source include/wait_condition.inc @@ -84,15 +84,14 @@ INSERT INTO t1 VALUES (4); --connection server_2 # Now add some local transactions that conflict with the GTID position -# being set for GTID_POS. +# being set for @@gtid_slave_pos. INSERT INTO t1 VALUES (10); DELETE FROM t1 WHERE a=10; ---error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG -SET GLOBAL gtid_pos='0-1-4'; +SET GLOBAL gtid_slave_pos='0-1-4'; # Try again after RESET MASTER to remove the conflicting binlog. RESET MASTER; -SET GLOBAL gtid_pos='0-1-4'; +SET GLOBAL gtid_slave_pos='0-1-4'; START SLAVE; --let $wait_condition= SELECT COUNT(*) = 4 FROM t1 --source include/wait_condition.inc @@ -117,9 +116,9 @@ RESET MASTER; RESET MASTER; --connection server_2 -SET GLOBAL gtid_pos=''; +SET GLOBAL gtid_slave_pos=''; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=1; +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=current_pos; --source include/start_slave.inc --connection server_1 @@ -145,22 +144,21 @@ INSERT INTO t1 VALUES (2); SELECT * FROM t1 ORDER BY a; ---echo *** MDEV-4329: GTID_POS='' is not checked for conflicts with binlog *** +--echo *** MDEV-4329: GTID_SLAVE_POS='' is not checked for conflicts with binlog *** # Test starting the slave completely from scratch, deleting all tables and # replicating from the start of the master's binlog. This requires RESET # MASTER is run on the slave to avoid old junk in the binlog. The bug was # that the code did not catch the error of missing RESET MASTER when an -# empty GTID_POS='' was specified. +# empty GTID_SLAVE_POS='' was specified. --connection server_2 --source include/stop_slave.inc DROP TABLE t1; RESET SLAVE; ---error ER_MASTER_GTID_POS_MISSING_DOMAIN -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; RESET MASTER; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; --source include/start_slave.inc --sync_with_master @@ -176,7 +174,7 @@ SET SQL_LOG_BIN=0; DROP TABLE t1; SET SQL_LOG_BIN=1; RESET SLAVE; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; --source include/start_slave.inc --sync_with_master @@ -197,7 +195,7 @@ START SLAVE; # Going back to using GTID should fix things. STOP SLAVE IO_THREAD; -CHANGE MASTER TO MASTER_USE_GTID=1; +CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS; --source include/start_slave.inc --connection server_1 @@ -245,7 +243,7 @@ SELECT * FROM t1 ORDER BY a; --connection server_2 --source include/stop_slave.inc RESET MASTER; -SET GLOBAL gtid_pos=""; +SET GLOBAL gtid_slave_pos=""; --connection server_1 RESET MASTER; @@ -260,25 +258,24 @@ INSERT INTO t1 VALUES (10); # Will be GTID 0-1-2 SELECT * FROM t1; --let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1) eval SELECT '$value' AS Using_Gtid; ---let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Pos", 1) -eval SELECT '$value' AS Gtid_Pos; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; UPDATE t1 SET a=9 WHERE a=10; UPDATE t1 SET a=10 WHERE a=9; ---let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Pos", 1) -eval SELECT '$value' AS Gtid_Pos; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; --source include/stop_slave.inc ---error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG -SET GLOBAL gtid_pos='0-1-2'; +SET GLOBAL gtid_slave_pos='0-1-2'; RESET MASTER; ---let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Pos", 1) -eval SELECT '$value' AS Gtid_Pos; -SET GLOBAL gtid_pos='0-1-2'; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; +SET GLOBAL gtid_slave_pos='0-1-2'; --source include/start_slave.inc ---let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Pos", 1) -eval SELECT '$value' AS Gtid_Pos; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; # Clean up. --connection server_1 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 262d86a294e..0833dfe1224 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -15,7 +15,7 @@ INSERT INTO t1 VALUES (1); --let $status_items= Master_Log_File,Using_Gtid --source include/show_slave_status.inc -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; # Now try to restart the slave mysqld server without starting the slave first # threads after the CHANGE MASTER. diff --git a/mysql-test/suite/rpl/t/rpl_gtid_until.test b/mysql-test/suite/rpl/t/rpl_gtid_until.test index 3b6e238f225..68ebd464fd1 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_until.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_until.test @@ -3,7 +3,7 @@ --source include/rpl_init.inc --connection server_1 -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; # Function to extract one GTID from a list. delimiter |; CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) @@ -37,12 +37,12 @@ START SLAVE UNTIL master_gtid_pos = ""; --error ER_UNTIL_REQUIRES_USING_GTID START SLAVE UNTIL master_gtid_pos = ""; -CHANGE MASTER TO master_use_gtid=1; +CHANGE MASTER TO master_use_gtid=current_pos; --connection server_1 CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); ---let $gtid_pos=`SELECT @@GLOBAL.gtid_pos` +--let $gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos` INSERT INTO t1 VALUES(2); --connection server_2 @@ -93,8 +93,8 @@ INSERT INTO t1 VALUES (3); SET gtid_domain_id = 2; CREATE TABLE t2 (a INT); INSERT INTO t2 VALUES (3); ---let $d1_point1= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` ---let $d2_point1= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d1_point1= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point1= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` FLUSH LOGS; SET gtid_domain_id = 1; INSERT INTO t1 VALUES (4); @@ -103,15 +103,15 @@ INSERT INTO t2 VALUES (4); FLUSH LOGS; SET gtid_domain_id = 1; INSERT INTO t1 VALUES (5); ---let $d1_point2= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` ---let $d2_point2= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d1_point2= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point2= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` SET gtid_domain_id = 2; INSERT INTO t2 VALUES (5); FLUSH LOGS; SET gtid_domain_id = 1; INSERT INTO t1 VALUES (6); ---let $d1_point3= `SELECT extract_gtid("1", @@GLOBAL.gtid_pos)` ---let $d2_point3= `SELECT extract_gtid("2", @@GLOBAL.gtid_pos)` +--let $d1_point3= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point3= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` SET gtid_domain_id = 2; INSERT INTO t2 VALUES (6); SET gtid_domain_id = 0; @@ -170,7 +170,7 @@ SELECT * FROM t1 ORDER BY a; --connection server_1 CREATE TABLE t3 (a INT); ---let $until_condition=`SELECT @@GLOBAL.gtid_pos` +--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos` DROP TABLE t3; --save_master_pos @@ -187,7 +187,7 @@ SHOW CREATE TABLE t3; --source include/stop_slave.inc RESET SLAVE ALL; RESET MASTER; -SET GLOBAL gtid_pos=''; +SET GLOBAL gtid_slave_pos=''; --connection server_1 # Do it once to compute the right GTID, then throw it away and do it again @@ -195,7 +195,7 @@ SET GLOBAL gtid_pos=''; RESET MASTER; INSERT INTO t1 VALUES (10); INSERT INTO t1 VALUES (11); ---let $until_condition=`SELECT @@GLOBAL.gtid_pos` +--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos` INSERT INTO t1 VALUES (12); DELETE FROM t1 WHERE a >= 10; @@ -205,7 +205,7 @@ INSERT INTO t1 VALUES (10); --connection server_2 --replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, - master_user = "root", master_use_gtid = 1; + master_user = "root", master_use_gtid = current_pos; eval START SLAVE UNTIL master_gtid_pos = '$until_condition'; --source include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/t/rpl_sync.test b/mysql-test/suite/rpl/t/rpl_sync.test index f2f73d59086..820ec19925f 100644 --- a/mysql-test/suite/rpl/t/rpl_sync.test +++ b/mysql-test/suite/rpl/t/rpl_sync.test @@ -36,7 +36,7 @@ call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression("Recovery from master pos .* and file master-bin.000001"); # Use innodb so we do not get "table should be repaired" issues. -ALTER TABLE mysql.rpl_slave_state ENGINE=InnoDB; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; flush tables; CREATE TABLE t1(a INT, PRIMARY KEY(a)) engine=innodb; diff --git a/mysql-test/suite/sys_vars/r/gtid_binlog_pos_basic.result b/mysql-test/suite/sys_vars/r/gtid_binlog_pos_basic.result new file mode 100644 index 00000000000..6d9d0ec449d --- /dev/null +++ b/mysql-test/suite/sys_vars/r/gtid_binlog_pos_basic.result @@ -0,0 +1,9 @@ +SET GLOBAL gtid_binlog_pos= ''; +ERROR HY000: Variable 'gtid_binlog_pos' is a read only variable +SELECT variable_name FROM information_schema.global_variables +WHERE variable_name='gtid_binlog_pos'; +variable_name +GTID_BINLOG_POS +SELECT @@gtid_binlog_pos; +SELECT @@session.gtid_binlog_pos; +ERROR HY000: Variable 'gtid_binlog_pos' is a GLOBAL variable diff --git a/mysql-test/suite/sys_vars/r/gtid_current_pos_basic.result b/mysql-test/suite/sys_vars/r/gtid_current_pos_basic.result new file mode 100644 index 00000000000..3ddc20d9b8c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/gtid_current_pos_basic.result @@ -0,0 +1,9 @@ +SET GLOBAL gtid_current_pos= ''; +ERROR HY000: Variable 'gtid_current_pos' is a read only variable +SELECT variable_name FROM information_schema.global_variables +WHERE variable_name='gtid_current_pos'; +variable_name +GTID_CURRENT_POS +SELECT @@gtid_current_pos; +SELECT @@session.gtid_current_pos; +ERROR HY000: Variable 'gtid_current_pos' is a GLOBAL variable diff --git a/mysql-test/suite/sys_vars/r/gtid_pos_basic.result b/mysql-test/suite/sys_vars/r/gtid_pos_basic.result deleted file mode 100644 index b97db1b657e..00000000000 --- a/mysql-test/suite/sys_vars/r/gtid_pos_basic.result +++ /dev/null @@ -1,47 +0,0 @@ -SET @old_gtid_pos= @@gtid_pos; -SET GLOBAL gtid_pos= ''; -SELECT @@gtid_pos; -@@gtid_pos - -SET GLOBAL gtid_pos= '1-2-3'; -SELECT variable_value FROM information_schema.global_variables -WHERE variable_name='gtid_pos'; -variable_value -1-2-3 -SET @@global.gtid_pos= '1-2-4'; -SELECT @@gtid_pos; -@@gtid_pos -1-2-4 -SET GLOBAL gtid_pos= ' 1-2-3'; -SELECT @@gtid_pos; -@@gtid_pos -1-2-3 -SET GLOBAL gtid_pos= '1-2-3, 2-4-6'; -SELECT @@gtid_pos; -@@gtid_pos -1-2-3,2-4-6 -SET GLOBAL gtid_pos= '-1-2-3'; -ERROR HY000: Could not parse GTID list for GTID_POS -SET GLOBAL gtid_pos= '1-2 -3'; -ERROR HY000: Could not parse GTID list for GTID_POS -SET GLOBAL gtid_pos= '1-2-3 '; -ERROR HY000: Could not parse GTID list for GTID_POS -SET GLOBAL gtid_pos= '1-2-3,2-4'; -ERROR HY000: Could not parse GTID list for GTID_POS -SET GLOBAL gtid_pos= '0-1-10,0-2-20'; -ERROR HY000: GTID 0-2-20 and 0-1-10 conflict (duplicate domain id 0) -SET GLOBAL gtid_pos= '0-1-10,1-2-20,2-3-30,1-20-200,3-4-1'; -ERROR HY000: GTID 1-20-200 and 1-2-20 conflict (duplicate domain id 1) -SET gtid_pos= ''; -ERROR HY000: Variable 'gtid_pos' is a GLOBAL variable and should be set with SET GLOBAL -SET SESSION gtid_pos= ''; -ERROR HY000: Variable 'gtid_pos' is a GLOBAL variable and should be set with SET GLOBAL -SET GLOBAL gtid_pos= '1-2-3,2-4-6'; -SELECT @@gtid_pos; -@@gtid_pos -1-2-3,2-4-6 -SET GLOBAL gtid_pos= DEFAULT; -ERROR 42000: Variable 'gtid_pos' doesn't have a default value -SELECT @@session.gtid_pos; -ERROR HY000: Variable 'gtid_pos' is a GLOBAL variable -SET GLOBAL gtid_pos= @old_gtid_pos; diff --git a/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result b/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result new file mode 100644 index 00000000000..e3ef59b7e30 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/gtid_slave_pos_basic.result @@ -0,0 +1,47 @@ +SET @old_gtid_slave_pos= @@gtid_slave_pos; +SET GLOBAL gtid_slave_pos= ''; +SELECT @@gtid_slave_pos; +@@gtid_slave_pos + +SET GLOBAL gtid_slave_pos= '1-2-3'; +SELECT variable_value FROM information_schema.global_variables +WHERE variable_name='gtid_slave_pos'; +variable_value +1-2-3 +SET @@global.gtid_slave_pos= '1-2-4'; +SELECT @@gtid_slave_pos; +@@gtid_slave_pos +1-2-4 +SET GLOBAL gtid_slave_pos= ' 1-2-3'; +SELECT @@gtid_slave_pos; +@@gtid_slave_pos +1-2-3 +SET GLOBAL gtid_slave_pos= '1-2-3, 2-4-6'; +SELECT @@gtid_slave_pos; +@@gtid_slave_pos +1-2-3,2-4-6 +SET GLOBAL gtid_slave_pos= '-1-2-3'; +ERROR HY000: Could not parse GTID list for GTID_POS +SET GLOBAL gtid_slave_pos= '1-2 -3'; +ERROR HY000: Could not parse GTID list for GTID_POS +SET GLOBAL gtid_slave_pos= '1-2-3 '; +ERROR HY000: Could not parse GTID list for GTID_POS +SET GLOBAL gtid_slave_pos= '1-2-3,2-4'; +ERROR HY000: Could not parse GTID list for GTID_POS +SET GLOBAL gtid_slave_pos= '0-1-10,0-2-20'; +ERROR HY000: GTID 0-2-20 and 0-1-10 conflict (duplicate domain id 0) +SET GLOBAL gtid_slave_pos= '0-1-10,1-2-20,2-3-30,1-20-200,3-4-1'; +ERROR HY000: GTID 1-20-200 and 1-2-20 conflict (duplicate domain id 1) +SET gtid_slave_pos= ''; +ERROR HY000: Variable 'gtid_slave_pos' is a GLOBAL variable and should be set with SET GLOBAL +SET SESSION gtid_slave_pos= ''; +ERROR HY000: Variable 'gtid_slave_pos' is a GLOBAL variable and should be set with SET GLOBAL +SET GLOBAL gtid_slave_pos= '1-2-3,2-4-6'; +SELECT @@gtid_slave_pos; +@@gtid_slave_pos +1-2-3,2-4-6 +SET GLOBAL gtid_slave_pos= DEFAULT; +ERROR 42000: Variable 'gtid_slave_pos' doesn't have a default value +SELECT @@session.gtid_slave_pos; +ERROR HY000: Variable 'gtid_slave_pos' is a GLOBAL variable +SET GLOBAL gtid_slave_pos= @old_gtid_slave_pos; diff --git a/mysql-test/suite/sys_vars/t/gtid_binlog_pos_basic.test b/mysql-test/suite/sys_vars/t/gtid_binlog_pos_basic.test new file mode 100644 index 00000000000..452132653fc --- /dev/null +++ b/mysql-test/suite/sys_vars/t/gtid_binlog_pos_basic.test @@ -0,0 +1,15 @@ +--source include/not_embedded.inc + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET GLOBAL gtid_binlog_pos= ''; +SELECT variable_name FROM information_schema.global_variables + WHERE variable_name='gtid_binlog_pos'; + +# The value of the variable depends on the binary log, this is tested extensively +# elsewhere in rpl.rpl_gtid*.test +--disable_result_log +SELECT @@gtid_binlog_pos; +--enable_result_log + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.gtid_binlog_pos; diff --git a/mysql-test/suite/sys_vars/t/gtid_current_pos_basic.test b/mysql-test/suite/sys_vars/t/gtid_current_pos_basic.test new file mode 100644 index 00000000000..9aac7ad7c10 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/gtid_current_pos_basic.test @@ -0,0 +1,15 @@ +--source include/not_embedded.inc + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET GLOBAL gtid_current_pos= ''; +SELECT variable_name FROM information_schema.global_variables + WHERE variable_name='gtid_current_pos'; + +# The value of the variable depends on the binary log, this is tested extensively +# elsewhere in rpl.rpl_gtid*.test +--disable_result_log +SELECT @@gtid_current_pos; +--enable_result_log + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.gtid_current_pos; diff --git a/mysql-test/suite/sys_vars/t/gtid_pos_basic.test b/mysql-test/suite/sys_vars/t/gtid_pos_basic.test deleted file mode 100644 index 929fdebed20..00000000000 --- a/mysql-test/suite/sys_vars/t/gtid_pos_basic.test +++ /dev/null @@ -1,46 +0,0 @@ ---source include/not_embedded.inc - -SET @old_gtid_pos= @@gtid_pos; - -SET GLOBAL gtid_pos= ''; -SELECT @@gtid_pos; -SET GLOBAL gtid_pos= '1-2-3'; -SELECT variable_value FROM information_schema.global_variables - WHERE variable_name='gtid_pos'; -SET @@global.gtid_pos= '1-2-4'; -SELECT @@gtid_pos; - -SET GLOBAL gtid_pos= ' 1-2-3'; -SELECT @@gtid_pos; -SET GLOBAL gtid_pos= '1-2-3, 2-4-6'; -SELECT @@gtid_pos; - ---error ER_INCORRECT_GTID_STATE -SET GLOBAL gtid_pos= '-1-2-3'; ---error ER_INCORRECT_GTID_STATE -SET GLOBAL gtid_pos= '1-2 -3'; ---error ER_INCORRECT_GTID_STATE -SET GLOBAL gtid_pos= '1-2-3 '; ---error ER_INCORRECT_GTID_STATE -SET GLOBAL gtid_pos= '1-2-3,2-4'; - ---error ER_DUPLICATE_GTID_DOMAIN -SET GLOBAL gtid_pos= '0-1-10,0-2-20'; ---error ER_DUPLICATE_GTID_DOMAIN -SET GLOBAL gtid_pos= '0-1-10,1-2-20,2-3-30,1-20-200,3-4-1'; - ---error ER_GLOBAL_VARIABLE -SET gtid_pos= ''; ---error ER_GLOBAL_VARIABLE -SET SESSION gtid_pos= ''; - -SET GLOBAL gtid_pos= '1-2-3,2-4-6'; -SELECT @@gtid_pos; - ---error ER_NO_DEFAULT -SET GLOBAL gtid_pos= DEFAULT; - ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT @@session.gtid_pos; - -SET GLOBAL gtid_pos= @old_gtid_pos; diff --git a/mysql-test/suite/sys_vars/t/gtid_slave_pos_basic.test b/mysql-test/suite/sys_vars/t/gtid_slave_pos_basic.test new file mode 100644 index 00000000000..d021e335b86 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/gtid_slave_pos_basic.test @@ -0,0 +1,46 @@ +--source include/not_embedded.inc + +SET @old_gtid_slave_pos= @@gtid_slave_pos; + +SET GLOBAL gtid_slave_pos= ''; +SELECT @@gtid_slave_pos; +SET GLOBAL gtid_slave_pos= '1-2-3'; +SELECT variable_value FROM information_schema.global_variables + WHERE variable_name='gtid_slave_pos'; +SET @@global.gtid_slave_pos= '1-2-4'; +SELECT @@gtid_slave_pos; + +SET GLOBAL gtid_slave_pos= ' 1-2-3'; +SELECT @@gtid_slave_pos; +SET GLOBAL gtid_slave_pos= '1-2-3, 2-4-6'; +SELECT @@gtid_slave_pos; + +--error ER_INCORRECT_GTID_STATE +SET GLOBAL gtid_slave_pos= '-1-2-3'; +--error ER_INCORRECT_GTID_STATE +SET GLOBAL gtid_slave_pos= '1-2 -3'; +--error ER_INCORRECT_GTID_STATE +SET GLOBAL gtid_slave_pos= '1-2-3 '; +--error ER_INCORRECT_GTID_STATE +SET GLOBAL gtid_slave_pos= '1-2-3,2-4'; + +--error ER_DUPLICATE_GTID_DOMAIN +SET GLOBAL gtid_slave_pos= '0-1-10,0-2-20'; +--error ER_DUPLICATE_GTID_DOMAIN +SET GLOBAL gtid_slave_pos= '0-1-10,1-2-20,2-3-30,1-20-200,3-4-1'; + +--error ER_GLOBAL_VARIABLE +SET gtid_slave_pos= ''; +--error ER_GLOBAL_VARIABLE +SET SESSION gtid_slave_pos= ''; + +SET GLOBAL gtid_slave_pos= '1-2-3,2-4-6'; +SELECT @@gtid_slave_pos; + +--error ER_NO_DEFAULT +SET GLOBAL gtid_slave_pos= DEFAULT; + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.gtid_slave_pos; + +SET GLOBAL gtid_slave_pos= @old_gtid_slave_pos; diff --git a/mysql-test/t/system_mysql_db_fix40123.test b/mysql-test/t/system_mysql_db_fix40123.test index d013ca5d0d9..adb223a9e50 100644 --- a/mysql-test/t/system_mysql_db_fix40123.test +++ b/mysql-test/t/system_mysql_db_fix40123.test @@ -77,7 +77,7 @@ CREATE TABLE index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) N -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, rpl_slave_state, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, gtid_slave_pos, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; -- enable_query_log diff --git a/mysql-test/t/system_mysql_db_fix50030.test b/mysql-test/t/system_mysql_db_fix50030.test index 26eceec96dc..a4718c91c26 100644 --- a/mysql-test/t/system_mysql_db_fix50030.test +++ b/mysql-test/t/system_mysql_db_fix50030.test @@ -84,7 +84,7 @@ CREATE TABLE index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) N -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, rpl_slave_state, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, gtid_slave_pos, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; -- enable_query_log diff --git a/mysql-test/t/system_mysql_db_fix50117.test b/mysql-test/t/system_mysql_db_fix50117.test index 9e5ffb8c2cb..5677d6337f0 100644 --- a/mysql-test/t/system_mysql_db_fix50117.test +++ b/mysql-test/t/system_mysql_db_fix50117.test @@ -103,7 +103,7 @@ CREATE TABLE index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) N -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, rpl_slave_state, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, gtid_slave_pos, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index, proxies_priv, table_stats, column_stats, index_stats; -- enable_query_log diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 95f2741f90d..75e4de9373c 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -24,7 +24,7 @@ set sql_mode=''; -- We want this to be created with the default storage engine. -- This way, if InnoDB is used we get crash safety, and if MyISAM is used -- we avoid mixed-engine transactions. -CREATE TABLE IF NOT EXISTS rpl_slave_state (domain_id INT UNSIGNED NOT NULL, sub_id BIGINT UNSIGNED NOT NULL, server_id INT UNSIGNED NOT NULL, seq_no BIGINT UNSIGNED NOT NULL, PRIMARY KEY (domain_id, sub_id)) comment='Replication slave GTID state'; +CREATE TABLE IF NOT EXISTS gtid_slave_pos (domain_id INT UNSIGNED NOT NULL, sub_id BIGINT UNSIGNED NOT NULL, server_id INT UNSIGNED NOT NULL, seq_no BIGINT UNSIGNED NOT NULL, PRIMARY KEY (domain_id, sub_id)) comment='Replication slave GTID state'; set storage_engine=myisam; flush tables; diff --git a/sql/lex.h b/sql/lex.h index 756e7e80f7e..e269c3e4040 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -152,6 +152,7 @@ static SYMBOL symbols[] = { { "CROSS", SYM(CROSS)}, { "CUBE", SYM(CUBE_SYM)}, { "CURRENT_DATE", SYM(CURDATE)}, + { "CURRENT_POS", SYM(CURRENT_POS_SYM)}, { "CURRENT_TIME", SYM(CURTIME)}, { "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, { "CURRENT_USER", SYM(CURRENT_USER)}, @@ -517,6 +518,7 @@ static SYMBOL symbols[] = { { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, { "SLAVES", SYM(SLAVES)}, + { "SLAVE_POS", SYM(SLAVE_POS_SYM)}, { "SLOW", SYM(SLOW)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, diff --git a/sql/log.cc b/sql/log.cc index 3266934beda..238452070ff 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5520,6 +5520,18 @@ MYSQL_BIN_LOG::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size) } +bool +MYSQL_BIN_LOG::append_state_pos(String *str) +{ + bool err; + + mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + err= rpl_global_gtid_binlog_state.append_pos(str); + mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + return err; +} + + bool MYSQL_BIN_LOG::find_in_binlog_state(uint32 domain_id, uint32 server_id, rpl_gtid *out_gtid) @@ -8508,7 +8520,7 @@ binlog_background_thread(void *arg __attribute__((unused))) thd->store_globals(); /* - Load the slave replication GTID state from the mysql.rpl_slave_state + Load the slave replication GTID state from the mysql.gtid_slave_pos table. This is mostly so that we can start our seq_no counter from the highest diff --git a/sql/log.h b/sql/log.h index bd20c8aee09..f41b48eba7c 100644 --- a/sql/log.h +++ b/sql/log.h @@ -779,6 +779,7 @@ public: int read_state_from_file(); int write_state_to_file(); int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); + bool append_state_pos(String *str); bool find_in_binlog_state(uint32 domain_id, uint32 server_id, rpl_gtid *out_gtid); bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid); diff --git a/sql/log_event.cc b/sql/log_event.cc index 9fbcbb68145..f896d3521de 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4004,7 +4004,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, const_cast(rli)->gtid_sub_id= 0; gtid= rli->current_gtid; - if (rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true)) + if (rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true, false)) { rli->report(ERROR_LEVEL, ER_CANNOT_UPDATE_GTID_STATE, "Error during COMMIT: failed to update GTID state in " @@ -6895,7 +6895,7 @@ int Xid_log_event::do_apply_event(Relay_log_info const *rli) const_cast(rli)->gtid_sub_id= 0; gtid= rli->current_gtid; - err= rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true); + err= rpl_global_gtid_slave_state.record_gtid(thd, >id, sub_id, true, false); if (err) { rli->report(ERROR_LEVEL, ER_CANNOT_UPDATE_GTID_STATE, diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index a4bdeb9932b..01502c5b0f1 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -29,7 +29,7 @@ const LEX_STRING rpl_gtid_slave_state_table_name= - { C_STRING_WITH_LEN("rpl_slave_state") }; + { C_STRING_WITH_LEN("gtid_slave_pos") }; void @@ -73,7 +73,7 @@ rpl_slave_state::record_and_update_gtid(THD *thd, Relay_log_info *rli) if ((sub_id= rli->gtid_sub_id)) { rli->gtid_sub_id= 0; - if (record_gtid(thd, &rli->current_gtid, sub_id, false)) + if (record_gtid(thd, &rli->current_gtid, sub_id, false, false)) return 1; update_state_hash(sub_id, &rli->current_gtid); } @@ -186,8 +186,6 @@ rpl_slave_state::truncate_state_table(THD *thd) int err= 0; TABLE *table; - mysql_reset_thd_for_next_command(thd, 0); - tlist.init_one_table(STRING_WITH_LEN("mysql"), rpl_gtid_slave_state_table_name.str, rpl_gtid_slave_state_table_name.length, @@ -234,7 +232,7 @@ static const TABLE_FIELD_TYPE mysql_rpl_slave_state_coltypes[4]= { static const uint mysql_rpl_slave_state_pk_parts[]= {0, 1}; -static const TABLE_FIELD_DEF mysql_rpl_slave_state_tabledef= { +static const TABLE_FIELD_DEF mysql_gtid_slave_pos_tabledef= { array_elements(mysql_rpl_slave_state_coltypes), mysql_rpl_slave_state_coltypes, array_elements(mysql_rpl_slave_state_pk_parts), @@ -256,14 +254,14 @@ protected: static Gtid_db_intact gtid_table_intact; /* - Check that the mysql.rpl_slave_state table has the correct definition. + Check that the mysql.gtid_slave_pos table has the correct definition. */ int gtid_check_rpl_slave_state_table(TABLE *table) { int err; - if ((err= gtid_table_intact.check(table, &mysql_rpl_slave_state_tabledef))) + if ((err= gtid_table_intact.check(table, &mysql_gtid_slave_pos_tabledef))) my_error(ER_GTID_OPEN_TABLE_FAILED, MYF(0), "mysql", rpl_gtid_slave_state_table_name.str); return err; @@ -286,7 +284,7 @@ gtid_check_rpl_slave_state_table(TABLE *table) */ int rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - bool in_transaction) + bool in_transaction, bool in_statement) { TABLE_LIST tlist; int err= 0; @@ -297,7 +295,8 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, ulonglong thd_saved_option= thd->variables.option_bits; Query_tables_list lex_backup; - mysql_reset_thd_for_next_command(thd, 0); + if (!in_statement) + mysql_reset_thd_for_next_command(thd, 0); DBUG_EXECUTE_IF("gtid_inject_record_gtid", { @@ -626,7 +625,7 @@ gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid) */ int rpl_slave_state::load(THD *thd, char *state_from_master, size_t len, - bool reset) + bool reset, bool in_statement) { char *end= state_from_master + len; @@ -645,7 +644,7 @@ rpl_slave_state::load(THD *thd, char *state_from_master, size_t len, if (gtid_parser_helper(&state_from_master, end, >id) || !(sub_id= next_subid(gtid.domain_id)) || - record_gtid(thd, >id, sub_id, false) || + record_gtid(thd, >id, sub_id, false, in_statement) || update(gtid.domain_id, gtid.server_id, sub_id, gtid.seq_no)) return 1; if (state_from_master == end) @@ -980,6 +979,23 @@ rpl_binlog_state::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size) } +bool +rpl_binlog_state::append_pos(String *str) +{ + uint32 i; + bool first= true; + + for (i= 0; i < hash.records; ++i) + { + element *e= (element *)my_hash_element(&hash, i); + if (rpl_slave_state_tostring_helper(str, e->last_gtid, &first)) + return true; + } + + return false; +} + + slave_connection_state::slave_connection_state() { my_hash_init(&hash, &my_charset_bin, 32, diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index bd6663c0659..cc3c99f40b7 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -91,11 +91,12 @@ struct rpl_slave_state int update(uint32 domain_id, uint32 server_id, uint64 sub_id, uint64 seq_no); int truncate_state_table(THD *thd); int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - bool in_transaction); + bool in_transaction, bool in_statement); uint64 next_subid(uint32 domain_id); int tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra); bool domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid); - int load(THD *thd, char *state_from_master, size_t len, bool reset); + int load(THD *thd, char *state_from_master, size_t len, bool reset, + bool in_statement); bool is_empty(); void lock() { DBUG_ASSERT(inited); mysql_mutex_lock(&LOCK_slave_state); } @@ -150,6 +151,7 @@ struct rpl_binlog_state uint32 count(); int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size); int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); + bool append_pos(String *str); rpl_gtid *find(uint32 domain_id, uint32 server_id); }; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 92dbf68d7a2..4ffe4f37cac 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -37,7 +37,8 @@ Master_info::Master_info(LEX_STRING *connection_name_arg, checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF), connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0), slave_running(0), slave_run_id(0), sync_counter(0), - heartbeat_period(0), received_heartbeats(0), master_id(0), using_gtid(0) + heartbeat_period(0), received_heartbeats(0), master_id(0), + using_gtid(USE_GTID_NO) { host[0] = 0; user[0] = 0; password[0] = 0; ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0; @@ -152,7 +153,7 @@ void init_master_log_pos(Master_info* mi) mi->master_log_name[0] = 0; mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number - mi->using_gtid= false; + mi->using_gtid= Master_info::USE_GTID_NO; /* Intentionally init ssl_verify_server_cert to 0, no option available */ mi->ssl_verify_server_cert= 0; @@ -447,7 +448,15 @@ file '%s')", fname); while (!init_strvar_from_file(buf, sizeof(buf), &mi->file, 0)) { if (0 == strncmp(buf, STRING_WITH_LEN("using_gtid="))) - mi->using_gtid= (0 != atoi(buf + sizeof("using_gtid"))); + { + int val= atoi(buf + sizeof("using_gtid")); + if (val == Master_info::USE_GTID_CURRENT_POS) + mi->using_gtid= Master_info::USE_GTID_CURRENT_POS; + else if (val == Master_info::USE_GTID_SLAVE_POS) + mi->using_gtid= Master_info::USE_GTID_SLAVE_POS; + else + mi->using_gtid= Master_info::USE_GTID_NO; + } } } } diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 64501e96f00..916bd0dae02 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -130,10 +130,14 @@ class Master_info : public Slave_reporting_capability DYNAMIC_ARRAY ignore_server_ids; ulong master_id; /* - True if slave position is set using GTID state rather than old-style - file/offset binlog position. + Which kind of GTID position (if any) is used when connecting to master. + + Note that you can not change the numeric values of these, they are used + in master.info. */ - bool using_gtid; + enum { + USE_GTID_NO= 0, USE_GTID_CURRENT_POS= 1, USE_GTID_SLAVE_POS= 2 + } using_gtid; }; int init_master_info(Master_info* mi, const char* master_info_fname, const char* slave_info_fname, diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index d7d5710b048..539e90d7cb5 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6540,8 +6540,8 @@ ER_GTID_POSITION_NOT_FOUND_IN_BINLOG ER_CANNOT_LOAD_SLAVE_GTID_STATE eng "Failed to load replication slave GTID state from table %s.%s" ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG - eng "Requested GTID_POS %u-%u-%llu conflicts with the binary log which contains a more recent GTID %u-%u-%llu. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog" + eng "Specified GTID %u-%u-%llu conflicts with the binary log which contains a more recent GTID %u-%u-%llu. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos." ER_MASTER_GTID_POS_MISSING_DOMAIN - eng "Requested GTID_POS contains no value for replication domain %u. This conflicts with the binary log which contains GTID %u-%u-%llu. To use the requested GTID_POS, the old binlog must be removed with RESET MASTER to avoid out-of-order binlog" + eng "Specified value for @@gtid_slave_pos contains no value for replication domain %u. This conflicts with the binary log which contains GTID %u-%u-%llu. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos." ER_UNTIL_REQUIRES_USING_GTID eng "START SLAVE UNTIL master_gtid_pos requires that slave is using GTID" diff --git a/sql/slave.cc b/sql/slave.cc index 1b3154e20ab..bf7e81edf71 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -810,7 +810,8 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, while one of the threads is running, they are in use and cannot be removed. */ - if (mi->using_gtid && !mi->slave_running && !mi->rli.slave_running) + if (mi->using_gtid != Master_info::USE_GTID_NO && + !mi->slave_running && !mi->rli.slave_running) { purge_relay_logs(&mi->rli, NULL, 0, &errmsg); mi->master_log_name[0]= 0; @@ -1819,7 +1820,7 @@ after_set_capability: restart or reconnect, we might end up re-fetching and hence re-applying the same event(s) again. */ - if (mi->using_gtid && !mi->master_log_name[0]) + if (mi->using_gtid != Master_info::USE_GTID_NO && !mi->master_log_name[0]) { int rc; char str_buf[256]; @@ -1849,7 +1850,9 @@ after_set_capability: connect_state.append(STRING_WITH_LEN("SET @slave_connect_state='"), system_charset_info); - if (rpl_append_gtid_state(&connect_state, true)) + if (rpl_append_gtid_state(&connect_state, + mi->using_gtid == + Master_info::USE_GTID_CURRENT_POS)) { err_code= ER_OUTOFMEMORY; errmsg= "The slave I/O thread stops because a fatal out-of-memory " @@ -1917,7 +1920,7 @@ after_set_capability: } } } - if (!mi->using_gtid) + if (mi->using_gtid == Master_info::USE_GTID_NO) { /* If we are not using GTID to connect this time, then instead request @@ -1943,7 +1946,7 @@ after_set_capability: (master_row[0] != NULL)) { rpl_global_gtid_slave_state.load(mi->io_thd, master_row[0], - strlen(master_row[0]), false); + strlen(master_row[0]), false, false); } else if (check_io_slave_killed(mi->io_thd, mi, NULL)) goto slave_killed_err; @@ -2307,8 +2310,8 @@ static bool send_show_master_info_header(THD *thd, bool full, FN_REFLEN)); field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong), MYSQL_TYPE_LONG)); - field_list.push_back(new Item_return_int("Using_Gtid", sizeof(ulong), - MYSQL_TYPE_LONG)); + field_list.push_back(new Item_empty_string("Using_Gtid", + sizeof("Current_Pos")-1)); if (full) { field_list.push_back(new Item_return_int("Retried_transactions", @@ -2321,7 +2324,8 @@ static bool send_show_master_info_header(THD *thd, bool full, 10, MYSQL_TYPE_LONG)); field_list.push_back(new Item_float("Slave_heartbeat_period", 0.0, 3, 10)); - field_list.push_back(new Item_empty_string("Gtid_Pos", gtid_pos_length)); + field_list.push_back(new Item_empty_string("Gtid_Slave_Pos", + gtid_pos_length)); } if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -2488,7 +2492,10 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, } // Master_Server_id protocol->store((uint32) mi->master_id); - protocol->store((uint32) (mi->using_gtid != 0)); + protocol->store((mi->using_gtid==Master_info::USE_GTID_NO ? "No" : + (mi->using_gtid==Master_info::USE_GTID_SLAVE_POS ? + "Slave_Pos" : "Current_Pos")), + &my_charset_bin); if (full) { protocol->store((uint32) mi->rli.retried_trans); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4c1d917aeae..f654c00810e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -301,8 +301,10 @@ struct LEX_MASTER_INFO changed variable or if it should be left at old value */ enum {LEX_MI_UNCHANGED, LEX_MI_DISABLE, LEX_MI_ENABLE} - ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt, - use_gtid_opt; + ssl, ssl_verify_server_cert, heartbeat_opt, repl_ignore_server_ids_opt; + enum { + LEX_GTID_UNCHANGED, LEX_GTID_NO, LEX_GTID_CURRENT_POS, LEX_GTID_SLAVE_POS + } use_gtid_opt; void init() { @@ -318,9 +320,10 @@ struct LEX_MASTER_INFO pos= relay_log_pos= server_id= port= connect_retry= 0; heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= - repl_ignore_server_ids_opt= use_gtid_opt= LEX_MI_UNCHANGED; + repl_ignore_server_ids_opt= LEX_MI_UNCHANGED; gtid_pos_str.length= 0; gtid_pos_str.str= NULL; + use_gtid_opt= LEX_GTID_UNCHANGED; } }; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2e10af0aa8c..82f471d5ddf 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2511,7 +2511,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) slave_errno= ER_BAD_SLAVE_UNTIL_COND; goto err; } - if (!mi->using_gtid) + if (mi->using_gtid == Master_info::USE_GTID_NO) { slave_errno= ER_UNTIL_REQUIRES_USING_GTID; goto err; @@ -3112,12 +3112,14 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos; } - if (lex_mi->use_gtid_opt == LEX_MASTER_INFO::LEX_MI_ENABLE) - mi->using_gtid= true; - else if (lex_mi->use_gtid_opt == LEX_MASTER_INFO::LEX_MI_DISABLE || + if (lex_mi->use_gtid_opt == LEX_MASTER_INFO::LEX_GTID_SLAVE_POS) + mi->using_gtid= Master_info::USE_GTID_SLAVE_POS; + else if (lex_mi->use_gtid_opt == LEX_MASTER_INFO::LEX_GTID_CURRENT_POS) + mi->using_gtid= Master_info::USE_GTID_CURRENT_POS; + else if (lex_mi->use_gtid_opt == LEX_MASTER_INFO::LEX_GTID_NO || lex_mi->log_file_name || lex_mi->pos || lex_mi->relay_log_name || lex_mi->relay_log_pos) - mi->using_gtid= false; + mi->using_gtid= Master_info::USE_GTID_NO; /* If user did specify neither host nor port nor any log name nor any log @@ -3173,7 +3175,7 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) goto err; } - if (mi->using_gtid) + if (mi->using_gtid != Master_info::USE_GTID_NO) { /* Clear the position in the master binlogs, so that we request the @@ -3657,7 +3659,7 @@ int log_loaded_block(IO_CACHE* file) /** - Initialise the slave replication state from the mysql.rpl_slave_state table. + Initialise the slave replication state from the mysql.gtid_slave_pos table. This is called each time an SQL thread starts, but the data is only actually loaded on the first call. @@ -3669,7 +3671,7 @@ int log_loaded_block(IO_CACHE* file) The one containing the current slave state is the one with the maximal sub_id value, within each domain_id. - CREATE TABLE mysql.rpl_slave_state ( + CREATE TABLE mysql.gtid_slave_pos ( domain_id INT UNSIGNED NOT NULL, sub_id BIGINT UNSIGNED NOT NULL, server_id INT UNSIGNED NOT NULL, @@ -3705,7 +3707,7 @@ rpl_append_gtid_state(String *dest, bool use_binlog) rpl_gtid *gtid_list= NULL; uint32 num_gtids= 0; - if (opt_bin_log && + if (use_binlog && opt_bin_log && (err= mysql_bin_log.get_most_recent_gtid_list(>id_list, &num_gtids))) return err; @@ -3717,9 +3719,12 @@ rpl_append_gtid_state(String *dest, bool use_binlog) bool -rpl_gtid_pos_check(char *str, size_t len) +rpl_gtid_pos_check(THD *thd, char *str, size_t len) { + /* ToDo: Use gtid_strict_mode sysvar, when implemented. */ + static const bool gtid_strict_mode= false; slave_connection_state tmp_slave_state; + bool gave_conflict_warning= false, gave_missing_warning= false; /* Check that we can parse the supplied string. */ if (tmp_slave_state.load(str, len)) @@ -3754,18 +3759,43 @@ rpl_gtid_pos_check(char *str, size_t len) continue; if (!(slave_gtid= tmp_slave_state.find(binlog_gtid->domain_id))) { - my_error(ER_MASTER_GTID_POS_MISSING_DOMAIN, MYF(0), - binlog_gtid->domain_id, binlog_gtid->domain_id, - binlog_gtid->server_id, binlog_gtid->seq_no); - break; + if (gtid_strict_mode) + { + my_error(ER_MASTER_GTID_POS_MISSING_DOMAIN, MYF(0), + binlog_gtid->domain_id, binlog_gtid->domain_id, + binlog_gtid->server_id, binlog_gtid->seq_no); + break; + } + else if (!gave_missing_warning) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_MASTER_GTID_POS_MISSING_DOMAIN, + ER(ER_MASTER_GTID_POS_MISSING_DOMAIN), + binlog_gtid->domain_id, binlog_gtid->domain_id, + binlog_gtid->server_id, binlog_gtid->seq_no); + gave_missing_warning= true; + } } - if (slave_gtid->seq_no < binlog_gtid->seq_no) + else if (slave_gtid->seq_no < binlog_gtid->seq_no) { - my_error(ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG, MYF(0), - slave_gtid->domain_id, slave_gtid->server_id, - slave_gtid->seq_no, binlog_gtid->domain_id, - binlog_gtid->server_id, binlog_gtid->seq_no); - break; + if (gtid_strict_mode) + { + my_error(ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG, MYF(0), + slave_gtid->domain_id, slave_gtid->server_id, + slave_gtid->seq_no, binlog_gtid->domain_id, + binlog_gtid->server_id, binlog_gtid->seq_no); + break; + } + else if (!gave_conflict_warning) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG, + ER(ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG), + slave_gtid->domain_id, slave_gtid->server_id, + slave_gtid->seq_no, binlog_gtid->domain_id, + binlog_gtid->server_id, binlog_gtid->seq_no); + gave_conflict_warning= true; + } } } my_free(binlog_gtid_list); @@ -3780,7 +3810,7 @@ rpl_gtid_pos_check(char *str, size_t len) bool rpl_gtid_pos_update(THD *thd, char *str, size_t len) { - if (rpl_global_gtid_slave_state.load(thd, str, len, true)) + if (rpl_global_gtid_slave_state.load(thd, str, len, true, true)) { my_error(ER_FAILED_GTID_STATE_INIT, MYF(0)); return true; diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 3af8f721bd7..820ffed0928 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -70,7 +70,7 @@ void rpl_init_gtid_slave_state(); void rpl_deinit_gtid_slave_state(); int gtid_state_from_binlog_pos(const char *name, uint32 pos, String *out_str); int rpl_append_gtid_state(String *dest, bool use_binlog); -bool rpl_gtid_pos_check(char *str, size_t len); +bool rpl_gtid_pos_check(THD *thd, char *str, size_t len); bool rpl_gtid_pos_update(THD *thd, char *str, size_t len); #endif /* HAVE_REPLICATION */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e995b410a85..d02f87c6bab 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -916,6 +916,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CUBE_SYM /* SQL-2003-R */ %token CURDATE /* MYSQL-FUNC */ %token CURRENT_USER /* SQL-2003-R */ +%token CURRENT_POS_SYM %token CURSOR_SYM /* SQL-2003-R */ %token CURSOR_NAME_SYM /* SQL-2003-N */ %token CURTIME /* MYSQL-FUNC */ @@ -1295,6 +1296,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE %token SLAVES +%token SLAVE_POS_SYM %token SLOW %token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM @@ -2065,15 +2067,34 @@ master_file_def: /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */ Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos); } - | MASTER_USE_GTID_SYM EQ ulong_num + | MASTER_USE_GTID_SYM EQ CURRENT_POS_SYM { - if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED) + if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED) { my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"); MYSQL_YYABORT; } - Lex->mi.use_gtid_opt= $3 ? - LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE; + Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS; + } + ; + | MASTER_USE_GTID_SYM EQ SLAVE_POS_SYM + { + if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"); + MYSQL_YYABORT; + } + Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS; + } + ; + | MASTER_USE_GTID_SYM EQ NO_SYM + { + if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"); + MYSQL_YYABORT; + } + Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO; } ; @@ -13254,6 +13275,7 @@ keyword_sp: | CONSTRAINT_NAME_SYM {} | CONTEXT_SYM {} | CONTRIBUTORS_SYM {} + | CURRENT_POS_SYM {} | CPU_SYM {} | CUBE_SYM {} | CURSOR_NAME_SYM {} @@ -13440,6 +13462,7 @@ keyword_sp: | SIMPLE_SYM {} | SHARE_SYM {} | SHUTDOWN {} + | SLAVE_POS_SYM {} | SLOW {} | SNAPSHOT_SYM {} | SOFT_SYM {} diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e51fd1cc11c..9edbe789196 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1228,8 +1228,61 @@ static Sys_var_ulonglong Sys_gtid_seq_no( #ifdef HAVE_REPLICATION +static unsigned char opt_gtid_binlog_pos_dummy; +static Sys_var_gtid_binlog_pos Sys_gtid_binlog_pos( + "gtid_binlog_pos", "Last GTID logged to the binary log, per replication" + "domain", + READ_ONLY GLOBAL_VAR(opt_gtid_binlog_pos_dummy), NO_CMD_LINE); + + +uchar * +Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, LEX_STRING *base) +{ + char buf[128]; + String str(buf, sizeof(buf), system_charset_info); + char *p; + + str.length(0); + if ((opt_bin_log && mysql_bin_log.append_state_pos(&str)) || + !(p= thd->strmake(str.ptr(), str.length()))) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + return NULL; + } + + return (uchar *)p; +} + + +static unsigned char opt_gtid_current_pos_dummy; +static Sys_var_gtid_current_pos Sys_gtid_current_pos( + "gtid_current_pos", "Current GTID position of the server. Per " + "replication domain, this is either the last GTID replicated by a " + "slave thread, or the GTID logged to the binary log, whichever is " + "most recent.", + READ_ONLY GLOBAL_VAR(opt_gtid_current_pos_dummy), NO_CMD_LINE); + + +uchar * +Sys_var_gtid_current_pos::global_value_ptr(THD *thd, LEX_STRING *base) +{ + String str; + char *p; + + str.length(0); + if (rpl_append_gtid_state(&str, true) || + !(p= thd->strmake(str.ptr(), str.length()))) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + return NULL; + } + + return (uchar *)p; +} + + bool -Sys_var_gtid_pos::do_check(THD *thd, set_var *var) +Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var) { String str, *res; bool running; @@ -1242,7 +1295,12 @@ Sys_var_gtid_pos::do_check(THD *thd, set_var *var) return true; if (!(res= var->value->val_str(&str))) return true; - if (rpl_gtid_pos_check(&((*res)[0]), res->length())) + if (thd->in_active_multi_stmt_transaction()) + { + my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0)); + return true; + } + if (rpl_gtid_pos_check(thd, &((*res)[0]), res->length())) return true; if (!(var->save_result.string_value.str= @@ -1257,7 +1315,7 @@ Sys_var_gtid_pos::do_check(THD *thd, set_var *var) bool -Sys_var_gtid_pos::global_update(THD *thd, set_var *var) +Sys_var_gtid_slave_pos::global_update(THD *thd, set_var *var) { bool err; @@ -1283,13 +1341,13 @@ Sys_var_gtid_pos::global_update(THD *thd, set_var *var) uchar * -Sys_var_gtid_pos::global_value_ptr(THD *thd, LEX_STRING *base) +Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, LEX_STRING *base) { String str; char *p; str.length(0); - if (rpl_append_gtid_state(&str, true) || + if (rpl_append_gtid_state(&str, false) || !(p= thd->strmake(str.ptr(), str.length()))) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); @@ -1300,14 +1358,12 @@ Sys_var_gtid_pos::global_value_ptr(THD *thd, LEX_STRING *base) } -static unsigned char opt_gtid_pos_dummy; -static Sys_var_gtid_pos Sys_gtid_pos( - "gtid_pos", +static unsigned char opt_gtid_slave_pos_dummy; +static Sys_var_gtid_slave_pos Sys_gtid_slave_pos( + "gtid_slave_pos", "The list of global transaction IDs that were last replicated on the " - "server, one for each replication domain. This defines where a slave " - "starts replicating from on a master when connecting with global " - "transaction ID.", - GLOBAL_VAR(opt_gtid_pos_dummy), NO_CMD_LINE); + "server, one for each replication domain.", + GLOBAL_VAR(opt_gtid_slave_pos_dummy), NO_CMD_LINE); #endif diff --git a/sql/sys_vars.h b/sql/sys_vars.h index 8a92f22f3c2..d68761d91ca 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -2024,12 +2024,114 @@ public: /** - Class for @@global.gtid_pos. + Class for @@global.gtid_current_pos. */ -class Sys_var_gtid_pos: public sys_var +class Sys_var_gtid_current_pos: public sys_var { public: - Sys_var_gtid_pos(const char *name_arg, + Sys_var_gtid_current_pos(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + option.var_type= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool check_update_type(Item_result type) { + DBUG_ASSERT(false); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base); +}; + + +/** + Class for @@global.gtid_binlog_pos. +*/ +class Sys_var_gtid_binlog_pos: public sys_var +{ +public: + Sys_var_gtid_binlog_pos(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, NULL) + { + option.var_type= GET_STR; + } + bool do_check(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + return true; + } + bool check_update_type(Item_result type) { + DBUG_ASSERT(false); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(false); + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(false); + return NULL; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base); +}; + + +/** + Class for @@global.gtid_slave_pos. +*/ +class Sys_var_gtid_slave_pos: public sys_var +{ +public: + Sys_var_gtid_slave_pos(const char *name_arg, const char *comment, int flag_args, ptrdiff_t off, size_t size, CMD_LINE getopt) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, From 416aed25ed2c27acbc47ec695fda023981be53c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 May 2013 22:21:08 +0200 Subject: [PATCH 08/10] MDEV-4475: Replication from MariaDB 10.0 to 5.5 does not work The problem was the Gtid_list event which is logged to the binlog in 10.0 and is not understood by the 5.5 server. This event is supposed to be replaced with a dummy event for 5.5 servers. But the very first event logged in the very first binlog has an empty list of GTID, which makes the event too short to be replacable with an empty event. The fix is to pad the empty Gtid_list event to be big enough to be replacable by a dummy event. --- mysql-test/r/mysqldump-max.result | 8 +- mysql-test/r/stat_tables_rbr.result | 24 ++-- .../r/binlog_stm_mix_innodb_myisam.result | 4 +- .../suite/binlog/t/binlog_mysqlbinlog2.test | 24 ++-- .../suite/innodb/r/binlog_consistent.result | 68 ++++++------ .../innodb/r/group_commit_binlog_pos.result | 2 +- ...ommit_binlog_pos_no_optimize_thread.result | 2 +- mysql-test/suite/multi_source/gtid.result | 8 +- .../suite/multi_source/info_logs.result | 8 +- .../suite/multi_source/multisource.result | 60 +++++----- .../suite/multi_source/relaylog_events.result | 12 +- .../suite/multi_source/reset_slave.result | 4 +- mysql-test/suite/multi_source/simple.result | 20 ++-- .../rpl/r/rpl_mariadb_slave_capability.result | 105 +++++++++--------- .../rpl/t/rpl_mariadb_slave_capability.test | 17 ++- sql/log_event.cc | 2 +- sql/log_event.h | 9 +- 17 files changed, 196 insertions(+), 181 deletions(-) diff --git a/mysql-test/r/mysqldump-max.result b/mysql-test/r/mysqldump-max.result index 2164b513335..8d5ab551bee 100644 --- a/mysql-test/r/mysqldump-max.result +++ b/mysql-test/r/mysqldump-max.result @@ -334,10 +334,10 @@ DROP TABLE t1; DROP TABLE t2; SHOW BINLOG EVENTS LIMIT 7,3; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 591 Xid 1 618 COMMIT /* XID */ -master-bin.000001 618 Gtid 1 656 GTID 0-1-3 -master-bin.000001 656 Query 1 775 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB --- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=937; +master-bin.000001 593 Xid 1 620 COMMIT /* XID */ +master-bin.000001 620 Gtid 1 658 GTID 0-1-3 +master-bin.000001 658 Query 1 777 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB +-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=939; SELECT * FROM t1 ORDER BY a; a 1 diff --git a/mysql-test/r/stat_tables_rbr.result b/mysql-test/r/stat_tables_rbr.result index 27c326265f1..0c941bcb248 100644 --- a/mysql-test/r/stat_tables_rbr.result +++ b/mysql-test/r/stat_tables_rbr.result @@ -16,17 +16,17 @@ test.t1 analyze status OK SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 248 Server ver: #, Binlog ver: # -master-bin.000001 248 Gtid_list 1 271 [] -master-bin.000001 271 Binlog_checkpoint 1 311 master-bin.000001 -master-bin.000001 311 Gtid 1 349 GTID 0-1-1 -master-bin.000001 349 Query 1 449 use `test`; CREATE TABLE t1 (i INT) ENGINE=InnoDB -master-bin.000001 449 Gtid 1 487 GTID 0-1-2 -master-bin.000001 487 Query 1 566 use `test`; ANALYZE TABLE t1 -master-bin.000001 566 Gtid 1 604 GTID 0-1-3 -master-bin.000001 604 Query 1 708 use `test`; DROP TABLE `t1` /* generated by server */ -master-bin.000001 708 Gtid 1 746 GTID 0-1-4 -master-bin.000001 746 Query 1 882 use `test`; CREATE TABLE t1 ( a INT ) ENGINE=MyISAM PARTITION BY HASH(a) PARTITIONS 2 -master-bin.000001 882 Gtid 1 920 GTID 0-1-5 -master-bin.000001 920 Query 1 1018 use `test`; ALTER TABLE t1 ANALYZE PARTITION p1 +master-bin.000001 248 Gtid_list 1 273 [] +master-bin.000001 273 Binlog_checkpoint 1 313 master-bin.000001 +master-bin.000001 313 Gtid 1 351 GTID 0-1-1 +master-bin.000001 351 Query 1 451 use `test`; CREATE TABLE t1 (i INT) ENGINE=InnoDB +master-bin.000001 451 Gtid 1 489 GTID 0-1-2 +master-bin.000001 489 Query 1 568 use `test`; ANALYZE TABLE t1 +master-bin.000001 568 Gtid 1 606 GTID 0-1-3 +master-bin.000001 606 Query 1 710 use `test`; DROP TABLE `t1` /* generated by server */ +master-bin.000001 710 Gtid 1 748 GTID 0-1-4 +master-bin.000001 748 Query 1 884 use `test`; CREATE TABLE t1 ( a INT ) ENGINE=MyISAM PARTITION BY HASH(a) PARTITIONS 2 +master-bin.000001 884 Gtid 1 922 GTID 0-1-5 +master-bin.000001 922 Query 1 1020 use `test`; ALTER TABLE t1 ANALYZE PARTITION p1 SET use_stat_tables = DEFAULT; DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 0ae7715ff65..b4e0747a07b 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -959,10 +959,10 @@ show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Intvar # # INSERT_ID=10 -master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci +master-bin.000001 # User var # # @`b`=_latin1 0x5 COLLATE latin1_swedish_ci master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# master-bin.000001 # Intvar # # INSERT_ID=10 -master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci +master-bin.000001 # User var # # @`b`=_latin1 0x5 COLLATE latin1_swedish_ci master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @`b`) SET `b`= @b + bug27417(2) ;file_id=# master-bin.000001 # Query # # ROLLBACK drop trigger trg_del_t2; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test index 0289ef6161b..367314d9643 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog2.test @@ -54,18 +54,18 @@ select "--- offset --" as ""; --disable_query_log select "--- start-position --" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; +let $start_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 --disable_query_log select "--- stop-position --" as ""; --enable_query_log -let $stop_pos= `select @binlog_start_pos + 694`; +let $stop_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 --disable_query_log select "--- start and stop positions ---" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; -let $stop_pos= `select @binlog_start_pos + 855`; +let $start_pos= `select @binlog_start_pos + 696`; +let $stop_pos= `select @binlog_start_pos + 857`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 --disable_query_log select "--- start-datetime --" as ""; @@ -92,12 +92,12 @@ select "--- offset --" as ""; --disable_query_log select "--- start-position --" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; +let $start_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 --disable_query_log select "--- stop-position --" as ""; --enable_query_log -let $stop_pos= `select @binlog_start_pos + 132`; +let $stop_pos= `select @binlog_start_pos + 134`; --exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos $MYSQLD_DATADIR/master-bin.000001 $MYSQLD_DATADIR/master-bin.000002 --disable_query_log select "--- start-datetime --" as ""; @@ -121,18 +121,18 @@ select "--- offset --" as ""; --disable_query_log select "--- start-position --" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; +let $start_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 --disable_query_log select "--- stop-position --" as ""; --enable_query_log -let $stop_pos= `select @binlog_start_pos + 694`; +let $stop_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 --disable_query_log select "--- start and stop positions ---" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; -let $stop_pos= `select @binlog_start_pos + 810`; +let $start_pos= `select @binlog_start_pos + 696`; +let $stop_pos= `select @binlog_start_pos + 812`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos --stop-position $stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 --disable_query_log select "--- start-datetime --" as ""; @@ -156,12 +156,12 @@ select "--- offset --" as ""; --disable_query_log select "--- start-position --" as ""; --enable_query_log -let $start_pos= `select @binlog_start_pos + 694`; +let $start_pos= `select @binlog_start_pos + 696`; --exec $MYSQL_BINLOG --short-form --start-position=$start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 --disable_query_log select "--- stop-position --" as ""; --enable_query_log -let $stop_pos= `select @binlog_start_pos + 107`; +let $stop_pos= `select @binlog_start_pos + 109`; --exec $MYSQL_BINLOG --short-form --stop-position=$stop_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002 --disable_query_log select "--- start-datetime --" as ""; diff --git a/mysql-test/suite/innodb/r/binlog_consistent.result b/mysql-test/suite/innodb/r/binlog_consistent.result index aabdefa5ee3..edfa5947eb8 100644 --- a/mysql-test/suite/innodb/r/binlog_consistent.result +++ b/mysql-test/suite/innodb/r/binlog_consistent.result @@ -3,11 +3,11 @@ RESET MASTER; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb; SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 484 +master-bin.000001 486 SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value Binlog_snapshot_file master-bin.000001 -Binlog_snapshot_position 484 +Binlog_snapshot_position 486 BEGIN; INSERT INTO t1 VALUES (0, ""); # Connection con1 @@ -38,10 +38,10 @@ a b SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value Binlog_snapshot_file master-bin.000001 -Binlog_snapshot_position 986 +Binlog_snapshot_position 988 SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 1338 +master-bin.000001 1340 SELECT * FROM t2 ORDER BY a; a 2 @@ -60,7 +60,7 @@ a b SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value Binlog_snapshot_file master-bin.000001 -Binlog_snapshot_position 986 +Binlog_snapshot_position 988 SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000002 367 @@ -75,33 +75,33 @@ master-bin.000002 367 SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 4 Format_desc 1 248 Server ver: #, Binlog ver: # -master-bin.000001 248 Gtid_list 1 271 [] -master-bin.000001 271 Binlog_checkpoint 1 311 master-bin.000001 -master-bin.000001 311 Gtid 1 349 GTID 0-1-1 -master-bin.000001 349 Query 1 484 use `test`; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb -master-bin.000001 484 Gtid 1 522 GTID 0-1-2 -master-bin.000001 522 Query 1 634 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=myisam -master-bin.000001 634 Gtid 1 672 BEGIN GTID 0-1-3 -master-bin.000001 672 Query 1 760 use `test`; INSERT INTO t2 VALUES (2) -master-bin.000001 760 Query 1 829 COMMIT -master-bin.000001 829 Gtid 1 867 BEGIN GTID 0-1-4 -master-bin.000001 867 Query 1 959 use `test`; INSERT INTO t1 VALUES (0, "") -master-bin.000001 959 Xid 1 986 COMMIT /* XID */ -master-bin.000001 986 Gtid 1 1024 BEGIN GTID 0-1-5 -master-bin.000001 1024 Query 1 1112 use `test`; INSERT INTO t2 VALUES (3) -master-bin.000001 1112 Query 1 1181 COMMIT -master-bin.000001 1181 Gtid 1 1219 BEGIN GTID 0-1-6 -master-bin.000001 1219 Query 1 1311 use `test`; INSERT INTO t1 VALUES (4, "") -master-bin.000001 1311 Xid 1 1338 COMMIT /* XID */ -master-bin.000001 1338 Gtid 1 1376 BEGIN GTID 0-1-7 -master-bin.000001 1376 Query 1 1468 use `test`; INSERT INTO t1 VALUES (1, "") -master-bin.000001 1468 Xid 1 1495 COMMIT /* XID */ -master-bin.000001 1495 Gtid 1 1533 BEGIN GTID 0-1-8 -master-bin.000001 1533 Query 1 1630 use `test`; INSERT INTO t1 VALUES (2, "first") -master-bin.000001 1630 Query 1 1728 use `test`; INSERT INTO t1 VALUES (2, "second") -master-bin.000001 1728 Xid 1 1755 COMMIT /* XID */ -master-bin.000001 1755 Gtid 1 1793 BEGIN GTID 0-1-9 -master-bin.000001 1793 Query 1 1885 use `test`; INSERT INTO t1 VALUES (3, "") -master-bin.000001 1885 Xid 1 1912 COMMIT /* XID */ -master-bin.000001 1912 Rotate 1 1956 master-bin.000002;pos=4 +master-bin.000001 248 Gtid_list 1 273 [] +master-bin.000001 273 Binlog_checkpoint 1 313 master-bin.000001 +master-bin.000001 313 Gtid 1 351 GTID 0-1-1 +master-bin.000001 351 Query 1 486 use `test`; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb +master-bin.000001 486 Gtid 1 524 GTID 0-1-2 +master-bin.000001 524 Query 1 636 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=myisam +master-bin.000001 636 Gtid 1 674 BEGIN GTID 0-1-3 +master-bin.000001 674 Query 1 762 use `test`; INSERT INTO t2 VALUES (2) +master-bin.000001 762 Query 1 831 COMMIT +master-bin.000001 831 Gtid 1 869 BEGIN GTID 0-1-4 +master-bin.000001 869 Query 1 961 use `test`; INSERT INTO t1 VALUES (0, "") +master-bin.000001 961 Xid 1 988 COMMIT /* XID */ +master-bin.000001 988 Gtid 1 1026 BEGIN GTID 0-1-5 +master-bin.000001 1026 Query 1 1114 use `test`; INSERT INTO t2 VALUES (3) +master-bin.000001 1114 Query 1 1183 COMMIT +master-bin.000001 1183 Gtid 1 1221 BEGIN GTID 0-1-6 +master-bin.000001 1221 Query 1 1313 use `test`; INSERT INTO t1 VALUES (4, "") +master-bin.000001 1313 Xid 1 1340 COMMIT /* XID */ +master-bin.000001 1340 Gtid 1 1378 BEGIN GTID 0-1-7 +master-bin.000001 1378 Query 1 1470 use `test`; INSERT INTO t1 VALUES (1, "") +master-bin.000001 1470 Xid 1 1497 COMMIT /* XID */ +master-bin.000001 1497 Gtid 1 1535 BEGIN GTID 0-1-8 +master-bin.000001 1535 Query 1 1632 use `test`; INSERT INTO t1 VALUES (2, "first") +master-bin.000001 1632 Query 1 1730 use `test`; INSERT INTO t1 VALUES (2, "second") +master-bin.000001 1730 Xid 1 1757 COMMIT /* XID */ +master-bin.000001 1757 Gtid 1 1795 BEGIN GTID 0-1-9 +master-bin.000001 1795 Query 1 1887 use `test`; INSERT INTO t1 VALUES (3, "") +master-bin.000001 1887 Xid 1 1914 COMMIT /* XID */ +master-bin.000001 1914 Rotate 1 1958 master-bin.000002;pos=4 DROP TABLE t1,t2; diff --git a/mysql-test/suite/innodb/r/group_commit_binlog_pos.result b/mysql-test/suite/innodb/r/group_commit_binlog_pos.result index 26a636c02ef..c8b80a037a7 100644 --- a/mysql-test/suite/innodb/r/group_commit_binlog_pos.result +++ b/mysql-test/suite/innodb/r/group_commit_binlog_pos.result @@ -31,6 +31,6 @@ a 1 2 3 -InnoDB: Last MySQL binlog file position 0 920, file name ./master-bin.000001 +InnoDB: Last MySQL binlog file position 0 922, file name ./master-bin.000001 SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result b/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result index d88da625e79..090b574a962 100644 --- a/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result +++ b/mysql-test/suite/innodb/r/group_commit_binlog_pos_no_optimize_thread.result @@ -32,6 +32,6 @@ a 1 2 3 -InnoDB: Last MySQL binlog file position 0 920, file name ./master-bin.000001 +InnoDB: Last MySQL binlog file position 0 922, file name ./master-bin.000001 SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/multi_source/gtid.result b/mysql-test/suite/multi_source/gtid.result index 651b9873369..5f4e3807fad 100644 --- a/mysql-test/suite/multi_source/gtid.result +++ b/mysql-test/suite/multi_source/gtid.result @@ -35,9 +35,9 @@ Master_User root Master_Port MYPORT_3 Connect_Retry 60 Master_Log_File server3-bin.000001 -Read_Master_Log_Pos 1499 +Read_Master_Log_Pos 1501 Relay_Log_File mysqld-relay-bin.000002 -Relay_Log_Pos 1788 +Relay_Log_Pos 1790 Relay_Master_Log_File server3-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -50,8 +50,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 1499 -Relay_Log_Space 2086 +Exec_Master_Log_Pos 1501 +Relay_Log_Space 2088 Until_Condition None Until_Log_File Until_Log_Pos 0 diff --git a/mysql-test/suite/multi_source/info_logs.result b/mysql-test/suite/multi_source/info_logs.result index d2144cb8a1b..4ea4d363dfb 100644 --- a/mysql-test/suite/multi_source/info_logs.result +++ b/mysql-test/suite/multi_source/info_logs.result @@ -85,16 +85,16 @@ MASTER 2.2 # show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000002 599 master-bin.000001 Yes Yes 0 0 311 886 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 -MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 relay.000002 601 master-bin.000001 Yes Yes 0 0 313 888 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 relay-master@00202@002e2.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 include/wait_for_slave_to_start.inc set default_master_connection = 'MASTER 2.2'; include/wait_for_slave_to_start.inc set default_master_connection = ''; show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 relay.000004 536 master-bin.000001 Yes Yes 0 0 311 823 None 0 No 0 No 0 0 1 No 0 1073741824 6 0 60.000 -MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 relay-master@00202@002e2.000004 536 master-bin.000001 Yes Yes 0 0 311 842 None 0 No 0 No 0 0 2 No 0 1073741824 6 0 60.000 + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 relay.000004 536 master-bin.000001 Yes Yes 0 0 313 823 None 0 No 0 No 0 0 1 No 0 1073741824 6 0 60.000 +MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 relay-master@00202@002e2.000004 536 master-bin.000001 Yes Yes 0 0 313 842 None 0 No 0 No 0 0 2 No 0 1073741824 6 0 60.000 # # List of files matching '*info*' pattern # after slave server restart diff --git a/mysql-test/suite/multi_source/multisource.result b/mysql-test/suite/multi_source/multisource.result index dfa3b1e1bed..d6acc5b3ea8 100644 --- a/mysql-test/suite/multi_source/multisource.result +++ b/mysql-test/suite/multi_source/multisource.result @@ -11,13 +11,13 @@ set default_master_connection = 'master1'; include/wait_for_slave_to_start.inc show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No +Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No +Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-master1.000002 599 master-bin.000001 Yes Yes 0 0 311 905 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 drop database if exists db1; create database db1; use db1; @@ -40,18 +40,18 @@ Log_name Pos Event_type Server_id End_log_pos Info mysqld-relay-bin-master1.000002 4 Format_desc 3 248 Server version mysqld-relay-bin-master1.000002 248 Rotate 1 0 master-bin.000001;pos=4 mysqld-relay-bin-master1.000002 292 Format_desc 1 248 Server version -mysqld-relay-bin-master1.000002 536 Gtid_list 1 271 [] -mysqld-relay-bin-master1.000002 559 Binlog_checkpoint 1 311 master-bin.000001 -mysqld-relay-bin-master1.000002 599 Gtid 1 349 GTID 0-1-1 -mysqld-relay-bin-master1.000002 637 Query 1 438 drop database if exists db1 -mysqld-relay-bin-master1.000002 726 Gtid 1 476 GTID 0-1-2 -mysqld-relay-bin-master1.000002 764 Query 1 557 create database db1 -mysqld-relay-bin-master1.000002 845 Gtid 1 595 GTID 0-1-3 -mysqld-relay-bin-master1.000002 883 Query 1 748 use `db1`; create table t1 (i int auto_increment, f1 varchar(16), primary key pk (i,f1)) engine=MyISAM -mysqld-relay-bin-master1.000002 1036 Gtid 1 786 BEGIN GTID 0-1-4 -mysqld-relay-bin-master1.000002 1074 Intvar 1 814 INSERT_ID=1 -mysqld-relay-bin-master1.000002 1102 Query 1 918 use `db1`; insert into t1 (f1) values ('one'),('two') -mysqld-relay-bin-master1.000002 1206 Query 1 986 COMMIT +mysqld-relay-bin-master1.000002 536 Gtid_list 1 273 [] +mysqld-relay-bin-master1.000002 561 Binlog_checkpoint 1 313 master-bin.000001 +mysqld-relay-bin-master1.000002 601 Gtid 1 351 GTID 0-1-1 +mysqld-relay-bin-master1.000002 639 Query 1 440 drop database if exists db1 +mysqld-relay-bin-master1.000002 728 Gtid 1 478 GTID 0-1-2 +mysqld-relay-bin-master1.000002 766 Query 1 559 create database db1 +mysqld-relay-bin-master1.000002 847 Gtid 1 597 GTID 0-1-3 +mysqld-relay-bin-master1.000002 885 Query 1 750 use `db1`; create table t1 (i int auto_increment, f1 varchar(16), primary key pk (i,f1)) engine=MyISAM +mysqld-relay-bin-master1.000002 1038 Gtid 1 788 BEGIN GTID 0-1-4 +mysqld-relay-bin-master1.000002 1076 Intvar 1 816 INSERT_ID=1 +mysqld-relay-bin-master1.000002 1104 Query 1 920 use `db1`; insert into t1 (f1) values ('one'),('two') +mysqld-relay-bin-master1.000002 1208 Query 1 988 COMMIT change master 'master1' to master_port=MYPORT_2, master_host='127.0.0.1', @@ -76,8 +76,8 @@ start slave; include/wait_for_slave_to_start.inc show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin.000002 599 master-bin.000001 Yes Yes 0 0 311 897 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 0-1-4 -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 986 mysqld-relay-bin-master1.000002 1274 master-bin.000001 Yes Yes 0 0 986 1580 None 0 No 0 No 0 0 1 No 0 1073741824 17 0 60.000 0-1-4 + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin.000002 601 master-bin.000001 Yes Yes 0 0 313 899 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 0-1-4 +master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 988 mysqld-relay-bin-master1.000002 1276 master-bin.000001 Yes Yes 0 0 988 1582 None 0 No 0 No 0 0 1 No 0 1073741824 17 0 60.000 0-1-4 insert into t1 (f1) values ('three'); drop database if exists db2; create database db2; @@ -106,7 +106,7 @@ insert into t1 (f1) values ('four'); create table db1.t3 (f1 int) engine=InnoDB; show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 919 mysqld-relay-bin.000002 1207 master-bin.000001 Yes Yes 0 0 919 1505 None 0 No 0 No 0 0 2 No 0 1073741824 17 0 60.000 0-1-7 + Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 921 mysqld-relay-bin.000002 1209 master-bin.000001 Yes Yes 0 0 921 1507 None 0 No 0 No 0 0 2 No 0 1073741824 17 0 60.000 0-1-7 master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000002 740 mysqld-relay-bin-master1.000004 1028 master-bin.000002 Yes Yes 0 0 740 1378 None 0 No 0 No 0 0 1 No 0 1073741824 37 0 60.000 0-1-7 select * from db1.t1; i f1 @@ -123,18 +123,18 @@ Log_name Pos Event_type Server_id End_log_pos Info mysqld-relay-bin.000002 4 Format_desc 3 248 Server version mysqld-relay-bin.000002 248 Rotate 2 0 master-bin.000001;pos=4 mysqld-relay-bin.000002 292 Format_desc 2 248 Server version -mysqld-relay-bin.000002 536 Gtid_list 2 271 [] -mysqld-relay-bin.000002 559 Binlog_checkpoint 2 311 master-bin.000001 -mysqld-relay-bin.000002 599 Gtid 2 349 GTID 0-2-1 -mysqld-relay-bin.000002 637 Query 2 438 drop database if exists db2 -mysqld-relay-bin.000002 726 Gtid 2 476 GTID 0-2-2 -mysqld-relay-bin.000002 764 Query 2 557 create database db2 -mysqld-relay-bin.000002 845 Gtid 2 595 GTID 0-2-3 -mysqld-relay-bin.000002 883 Query 2 730 use `db2`; create table t1 (pk int auto_increment primary key, f1 int) engine=InnoDB -mysqld-relay-bin.000002 1018 Gtid 2 768 BEGIN GTID 0-2-4 -mysqld-relay-bin.000002 1056 Intvar 2 796 INSERT_ID=1 -mysqld-relay-bin.000002 1084 Query 2 892 use `db2`; insert into t1 (f1) values (1),(2) -mysqld-relay-bin.000002 1180 Xid 2 919 COMMIT /* xid= */ +mysqld-relay-bin.000002 536 Gtid_list 2 273 [] +mysqld-relay-bin.000002 561 Binlog_checkpoint 2 313 master-bin.000001 +mysqld-relay-bin.000002 601 Gtid 2 351 GTID 0-2-1 +mysqld-relay-bin.000002 639 Query 2 440 drop database if exists db2 +mysqld-relay-bin.000002 728 Gtid 2 478 GTID 0-2-2 +mysqld-relay-bin.000002 766 Query 2 559 create database db2 +mysqld-relay-bin.000002 847 Gtid 2 597 GTID 0-2-3 +mysqld-relay-bin.000002 885 Query 2 732 use `db2`; create table t1 (pk int auto_increment primary key, f1 int) engine=InnoDB +mysqld-relay-bin.000002 1020 Gtid 2 770 BEGIN GTID 0-2-4 +mysqld-relay-bin.000002 1058 Intvar 2 798 INSERT_ID=1 +mysqld-relay-bin.000002 1086 Query 2 894 use `db2`; insert into t1 (f1) values (1),(2) +mysqld-relay-bin.000002 1182 Xid 2 921 COMMIT /* xid= */ stop slave io_thread; show status like 'Slave_running'; Variable_name Value diff --git a/mysql-test/suite/multi_source/relaylog_events.result b/mysql-test/suite/multi_source/relaylog_events.result index 6b452e65176..970d7d20438 100644 --- a/mysql-test/suite/multi_source/relaylog_events.result +++ b/mysql-test/suite/multi_source/relaylog_events.result @@ -15,12 +15,12 @@ Log_name Pos Event_type Server_id End_log_pos Info mysqld-relay-bin-master1.000002 4 Format_desc 3 248 Server version mysqld-relay-bin-master1.000002 248 Rotate 1 0 master-bin.000001;pos=4 mysqld-relay-bin-master1.000002 292 Format_desc 1 248 Server version -mysqld-relay-bin-master1.000002 536 Gtid_list 1 271 [] -mysqld-relay-bin-master1.000002 559 Binlog_checkpoint 1 311 master-bin.000001 -mysqld-relay-bin-master1.000002 599 Gtid 1 349 GTID 0-1-1 -mysqld-relay-bin-master1.000002 637 Query 1 463 use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */ -mysqld-relay-bin-master1.000002 751 Gtid 1 501 GTID 0-1-2 -mysqld-relay-bin-master1.000002 789 Query 1 601 use `test`; create table t1 (i int) engine=MyISAM +mysqld-relay-bin-master1.000002 536 Gtid_list 1 273 [] +mysqld-relay-bin-master1.000002 561 Binlog_checkpoint 1 313 master-bin.000001 +mysqld-relay-bin-master1.000002 601 Gtid 1 351 GTID 0-1-1 +mysqld-relay-bin-master1.000002 639 Query 1 465 use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */ +mysqld-relay-bin-master1.000002 753 Gtid 1 503 GTID 0-1-2 +mysqld-relay-bin-master1.000002 791 Query 1 603 use `test`; create table t1 (i int) engine=MyISAM show relaylog events; Log_name Pos Event_type Server_id End_log_pos Info mysqld-relay-bin-master1.000001 4 Format_desc 3 248 Server version diff --git a/mysql-test/suite/multi_source/reset_slave.result b/mysql-test/suite/multi_source/reset_slave.result index 88bc934afaf..ae3b899cf5f 100644 --- a/mysql-test/suite/multi_source/reset_slave.result +++ b/mysql-test/suite/multi_source/reset_slave.result @@ -11,14 +11,14 @@ insert into t1 values (1),(2); stop slave 'master1'; show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid - 127.0.0.1 root MYPORT_1 60 master-bin.000001 800 mysqld-relay-bin-master1.000002 1088 master-bin.000001 No No 0 0 800 1394 None 0 No NULL No 0 0 1 No + 127.0.0.1 root MYPORT_1 60 master-bin.000001 802 mysqld-relay-bin-master1.000002 1090 master-bin.000001 No No 0 0 802 1396 None 0 No NULL No 0 0 1 No mysqld-relay-bin-master1.000001 mysqld-relay-bin-master1.000002 mysqld-relay-bin-master1.index reset slave 'master1'; show slave 'master1' status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid - 127.0.0.1 root MYPORT_1 60 4 1088 No No 0 0 0 1394 None 0 No NULL No 0 0 1 No + 127.0.0.1 root MYPORT_1 60 4 1090 No No 0 0 0 1396 None 0 No NULL No 0 0 1 No reset slave 'master1' all; show slave 'master1' status; ERROR HY000: There is no master connection 'master1' diff --git a/mysql-test/suite/multi_source/simple.result b/mysql-test/suite/multi_source/simple.result index 525aaa4b0cc..307709ffa3f 100644 --- a/mysql-test/suite/multi_source/simple.result +++ b/mysql-test/suite/multi_source/simple.result @@ -11,8 +11,8 @@ include/wait_for_slave_to_start.inc set default_master_connection = ''; show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 311 mysqld-relay-bin-slave1.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 +slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-slave1.000002 601 master-bin.000001 Yes Yes 0 0 313 906 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin-slave2.000002 601 master-bin.000001 Yes Yes 0 0 313 906 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 start all slaves; stop slave 'slave1'; show slave 'slave1' status; @@ -22,9 +22,9 @@ Master_User root Master_Port MYPORT_1 Connect_Retry 60 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 311 +Read_Master_Log_Pos 313 Relay_Log_File mysqld-relay-bin-slave1.000002 -Relay_Log_Pos 599 +Relay_Log_Pos 601 Relay_Master_Log_File master-bin.000001 Slave_IO_Running No Slave_SQL_Running No @@ -37,8 +37,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 311 -Relay_Log_Space 904 +Exec_Master_Log_Pos 313 +Relay_Log_Space 906 Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -60,18 +60,18 @@ Using_Gtid No reset slave 'slave1'; show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -slave1 127.0.0.1 root MYPORT_1 60 4 599 No No 0 0 0 904 None 0 No NULL No 0 0 1 No 0 1073741824 7 0 60.000 -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 +slave1 127.0.0.1 root MYPORT_1 60 4 601 No No 0 0 0 906 None 0 No NULL No 0 0 1 No 0 1073741824 7 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin-slave2.000002 601 master-bin.000001 Yes Yes 0 0 313 906 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 reset slave 'slave1' all; show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 Yes Yes 0 0 311 904 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 +slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin-slave2.000002 601 master-bin.000001 Yes Yes 0 0 313 906 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 stop all slaves; Warnings: Note 1938 SLAVE 'slave2' stopped show all slaves status; Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Using_Gtid Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 311 mysqld-relay-bin-slave2.000002 599 master-bin.000001 No No 0 0 311 904 None 0 No NULL No 0 0 2 No 0 1073741824 7 0 60.000 +slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin-slave2.000002 601 master-bin.000001 No No 0 0 313 906 None 0 No NULL No 0 0 2 No 0 1073741824 7 0 60.000 stop all slaves; include/reset_master_slave.inc include/reset_master_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result index f48fa1850a2..2a7ed37cf9b 100644 --- a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result +++ b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result @@ -2,65 +2,66 @@ include/master-slave.inc [connection master] set @old_master_binlog_checksum= @@global.binlog_checksum; set @old_slave_dbug= @@global.debug_dbug; -CREATE TABLE t1 (a INT PRIMARY KEY); -INSERT INTO t1 VALUES (0); -# Test slave with no capability gets dummy event, which is ignored. include/stop_slave.inc +# Test slave with no capability gets dummy event, which is ignored. SET @@global.debug_dbug='+d,simulate_slave_capability_none'; include/start_slave.inc +FLUSH LOGS; +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (0); ALTER TABLE t1 ORDER BY a; SET SESSION binlog_annotate_row_events = ON; DELETE FROM t1; INSERT INTO t1 /* A comment just to make the annotate event sufficiently long that the dummy event will need to get padded with spaces so that we can test that this works */ VALUES(1); -show binlog events in 'master-bin.000001' from limit 0, 10; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # DELETE FROM t1 -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # INSERT INTO t1 /* A comment just to make the annotate event sufficiently long that the dummy event will need to get padded with spaces so that we can test that this works */ VALUES(1) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # COMMIT -SELECT * FROM t1; -a -1 -show relaylog events in 'slave-relay-bin.000003' from limit 0,10; -Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # User var # # @`!dummyvar`=NULL -slave-relay-bin.000003 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000003 # Delete_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000003 # Query # # COMMIT -slave-relay-bin.000003 # Query # # BEGIN -slave-relay-bin.000003 # Query # # # Dummy event replacing event type 160 that slave cannot handle. -slave-relay-bin.000003 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000003 # Query # # COMMIT -set @@global.debug_dbug= @old_slave_dbug; -# Test dummy event is checksummed correctly. -set @@global.binlog_checksum = CRC32; -TRUNCATE t1; -INSERT INTO t1 VALUES(2); -show binlog events in 'master-bin.000002' from limit 0, 5; +show binlog events in 'master-bin.000002' from limit 0, 10; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000002 # Gtid # # BEGIN GTID #-#-# -master-bin.000002 # Annotate_rows # # INSERT INTO t1 VALUES(2) +master-bin.000002 # Annotate_rows # # DELETE FROM t1 +master-bin.000002 # Table_map # # table_id: # (test.t1) +master-bin.000002 # Delete_rows # # table_id: # flags: STMT_END_F +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Annotate_rows # # INSERT INTO t1 /* A comment just to make the annotate event sufficiently long that the dummy event will need to get padded with spaces so that we can test that this works */ VALUES(1) master-bin.000002 # Table_map # # table_id: # (test.t1) master-bin.000002 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000002 # Query # # COMMIT SELECT * FROM t1; a -2 -show relaylog events in 'slave-relay-bin.000005' from limit 7,5; +1 +show relaylog events in 'slave-relay-bin.000005' from limit 0,10; Log_name Pos Event_type Server_id End_log_pos Info slave-relay-bin.000005 # Query # # BEGIN -slave-relay-bin.000005 # Query # # # Dummy ev +slave-relay-bin.000005 # User var # # @`!dummyvar`=NULL +slave-relay-bin.000005 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000005 # Delete_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000005 # Query # # COMMIT +slave-relay-bin.000005 # Query # # BEGIN +slave-relay-bin.000005 # Query # # # Dummy event replacing event type 160 that slave cannot handle. slave-relay-bin.000005 # Table_map # # table_id: # (test.t1) slave-relay-bin.000005 # Write_rows # # table_id: # flags: STMT_END_F slave-relay-bin.000005 # Query # # COMMIT +set @@global.debug_dbug= @old_slave_dbug; +# Test dummy event is checksummed correctly. +set @@global.binlog_checksum = CRC32; +TRUNCATE t1; +INSERT INTO t1 VALUES(2); +show binlog events in 'master-bin.000003' from limit 0, 5; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000003 # Gtid # # BEGIN GTID #-#-# +master-bin.000003 # Annotate_rows # # INSERT INTO t1 VALUES(2) +master-bin.000003 # Table_map # # table_id: # (test.t1) +master-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000003 # Query # # COMMIT +SELECT * FROM t1; +a +2 +show relaylog events in 'slave-relay-bin.000007' from limit 7,5; +Log_name Pos Event_type Server_id End_log_pos Info +slave-relay-bin.000007 # Query # # BEGIN +slave-relay-bin.000007 # Query # # # Dummy ev +slave-relay-bin.000007 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000007 # Write_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000007 # Query # # COMMIT # Test that slave which cannot tolerate holes in binlog stream but # knows the event does not get dummy event include/stop_slave.inc @@ -68,23 +69,23 @@ SET @@global.debug_dbug='+d,simulate_slave_capability_old_53'; include/start_slave.inc ALTER TABLE t1 ORDER BY a; UPDATE t1 SET a = 3; -show binlog events in 'master-bin.000002' from limit 0, 5; +show binlog events in 'master-bin.000003' from limit 0, 5; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000002 # Gtid # # BEGIN GTID #-#-# -master-bin.000002 # Annotate_rows # # UPDATE t1 SET a = 3 -master-bin.000002 # Table_map # # table_id: # (test.t1) -master-bin.000002 # Update_rows # # table_id: # flags: STMT_END_F -master-bin.000002 # Query # # COMMIT +master-bin.000003 # Gtid # # BEGIN GTID #-#-# +master-bin.000003 # Annotate_rows # # UPDATE t1 SET a = 3 +master-bin.000003 # Table_map # # table_id: # (test.t1) +master-bin.000003 # Update_rows # # table_id: # flags: STMT_END_F +master-bin.000003 # Query # # COMMIT SELECT * FROM t1; a 3 -show relaylog events in 'slave-relay-bin.000006' from limit 0,5; +show relaylog events in 'slave-relay-bin.000008' from limit 0,5; Log_name Pos Event_type Server_id End_log_pos Info -slave-relay-bin.000006 # Query # # BEGIN -slave-relay-bin.000006 # Annotate_rows # # UPDATE t1 SET a = 3 -slave-relay-bin.000006 # Table_map # # table_id: # (test.t1) -slave-relay-bin.000006 # Update_rows # # table_id: # flags: STMT_END_F -slave-relay-bin.000006 # Query # # COMMIT +slave-relay-bin.000008 # Query # # BEGIN +slave-relay-bin.000008 # Annotate_rows # # UPDATE t1 SET a = 3 +slave-relay-bin.000008 # Table_map # # table_id: # (test.t1) +slave-relay-bin.000008 # Update_rows # # table_id: # flags: STMT_END_F +slave-relay-bin.000008 # Query # # COMMIT select @@global.log_slave_updates; @@global.log_slave_updates 1 diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test index b8ca409e25b..99a371eac44 100644 --- a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test +++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test @@ -6,16 +6,23 @@ connection master; set @old_master_binlog_checksum= @@global.binlog_checksum; set @old_slave_dbug= @@global.debug_dbug; -CREATE TABLE t1 (a INT PRIMARY KEY); -INSERT INTO t1 VALUES (0); -sync_slave_with_master; +# MDEV-4475: Cannot replicate to old server when binlog contains +# empty Gtid_list event +# +# Test this by binlog rotation before we log any GTIDs. connection slave; - ---echo # Test slave with no capability gets dummy event, which is ignored. --source include/stop_slave.inc +--echo # Test slave with no capability gets dummy event, which is ignored. SET @@global.debug_dbug='+d,simulate_slave_capability_none'; --source include/start_slave.inc + +connection master; +FLUSH LOGS; +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (0); +sync_slave_with_master; + connection master; # Add a dummy event just to have something to sync_slave_with_master on. # Otherwise we occasionally get different $relaylog_start, depending on diff --git a/sql/log_event.cc b/sql/log_event.cc index f896d3521de..35c1ab90836 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6374,7 +6374,7 @@ Gtid_list_log_event::to_packet(String *packet) DBUG_ASSERT(count < 1<<28); - needed_length= packet->length() + 4 + count*element_size; + needed_length= packet->length() + get_data_size(); if (packet->reserve(needed_length)) return true; p= (uchar *)packet->ptr() + packet->length();; diff --git a/sql/log_event.h b/sql/log_event.h index 21d60cac928..b5b488f320d 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3181,7 +3181,14 @@ public: const Format_description_log_event *description_event); ~Gtid_list_log_event() { my_free(list); } Log_event_type get_type_code() { return GTID_LIST_EVENT; } - int get_data_size() { return GTID_LIST_HEADER_LEN + count*element_size; } + int get_data_size() { + /* + Replacing with dummy event, needed for older slaves, requires a minimum + of 6 bytes in the body. + */ + return (count==0 ? + GTID_LIST_HEADER_LEN+2 : GTID_LIST_HEADER_LEN+count*element_size); + } bool is_valid() const { return list != NULL; } #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) bool to_packet(String *packet); From f5319394e3dee146f112b41674ffa188d5e89150 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 May 2013 06:32:00 +0200 Subject: [PATCH 09/10] MDEV-4475 follow-up patch: Add forgotten initialisation of the padding for empty Gtid_List event --- sql/log_event.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/log_event.cc b/sql/log_event.cc index 35c1ab90836..f4e34dd9224 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6381,6 +6381,9 @@ Gtid_list_log_event::to_packet(String *packet) packet->length(needed_length); int4store(p, (count & ((1<<28)-1)) | gl_flags); p += 4; + /* Initialise the padding for empty Gtid_list. */ + if (count == 0) + int2store(p, 0); for (i= 0; i < count; ++i) { int4store(p, list[i].domain_id); From ee2b7db3f88f6882022a8aa71b30043ed8b40792 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 May 2013 13:28:31 +0200 Subject: [PATCH 10/10] MDEV-4478: Implement GTID "strict mode" When @@GLOBAL.gtid_strict_mode=1, then certain operations result in error that would otherwise result in out-of-order binlog files between servers. GTID sequence numbers are now allocated independently per domain; this results in less/no holes in GTID sequences, increasing the likelyhood that diverging binlogs will be caught by the slave when GTID strict mode is enabled. --- mysql-test/r/mysqld--help.result | 5 + .../suite/perfschema/r/all_instances.result | 1 - mysql-test/suite/rpl/r/rpl_gtid_crash.result | 4 +- .../suite/rpl/r/rpl_gtid_errorhandling.result | 6 + .../rpl/r/rpl_gtid_master_promote.result | 14 +- .../suite/rpl/r/rpl_gtid_stop_start.result | 4 +- mysql-test/suite/rpl/r/rpl_gtid_strict.result | 182 +++++++++++++ mysql-test/suite/rpl/r/rpl_gtid_until.result | 10 +- .../suite/rpl/t/rpl_gtid_errorhandling.test | 8 +- mysql-test/suite/rpl/t/rpl_gtid_strict.test | 178 +++++++++++++ .../sys_vars/r/gtid_strict_mode_basic.result | 29 +++ .../sys_vars/t/gtid_strict_mode_basic.test | 21 ++ sql/log.cc | 99 +++---- sql/log.h | 4 +- sql/log_event.cc | 9 + sql/mysqld.cc | 13 +- sql/mysqld.h | 5 +- sql/rpl_gtid.cc | 242 ++++++++++++++---- sql/rpl_gtid.h | 13 +- sql/rpl_rli.cc | 12 +- sql/share/errmsg-utf8.txt | 4 + sql/slave.cc | 59 ++++- sql/sql_repl.cc | 116 +++++++-- sql/sys_vars.cc | 31 ++- 24 files changed, 898 insertions(+), 171 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_strict.result create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_strict.test create mode 100644 mysql-test/suite/sys_vars/r/gtid_strict_mode_basic.result create mode 100644 mysql-test/suite/sys_vars/t/gtid_strict_mode_basic.test diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 70b93e7025f..d9cdf3c3240 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -207,6 +207,10 @@ The following options may be given as the first argument: multiple masters), each independent source server must use a distinct domain_id. For simple tree-shaped replication topologies, it can be left at its default, 0. + --gtid-strict-mode Enforce strict seq_no ordering of events in the binary + log. Slave stops with an error if it encounters an event + that would cause it to generate an out-of-order binlog if + executed. -?, --help Display this help and exit. --histogram-size=# Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. @@ -966,6 +970,7 @@ gdb FALSE general-log FALSE group-concat-max-len 1024 gtid-domain-id 0 +gtid-strict-mode FALSE help TRUE histogram-size 0 histogram-type SINGLE_PREC_HB diff --git a/mysql-test/suite/perfschema/r/all_instances.result b/mysql-test/suite/perfschema/r/all_instances.result index cfe39188769..8ecb8dfe602 100644 --- a/mysql-test/suite/perfschema/r/all_instances.result +++ b/mysql-test/suite/perfschema/r/all_instances.result @@ -55,7 +55,6 @@ wait/synch/mutex/sql/LOCK_global_index_stats wait/synch/mutex/sql/LOCK_global_system_variables wait/synch/mutex/sql/LOCK_global_table_stats wait/synch/mutex/sql/LOCK_global_user_client_stats -wait/synch/mutex/sql/LOCK_gtid_counter wait/synch/mutex/sql/LOCK_open wait/synch/mutex/sql/LOCK_plugin wait/synch/mutex/sql/LOCK_prepared_stmt_count diff --git a/mysql-test/suite/rpl/r/rpl_gtid_crash.result b/mysql-test/suite/rpl/r/rpl_gtid_crash.result index ccc64b70803..ef98c66bee0 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_crash.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_crash.result @@ -41,7 +41,7 @@ master-bin.000002 # master-bin.000003 # SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000003 # Gtid_list # # [1-1-3,2-1-4,0-1-1] +master-bin.000003 # Gtid_list # # [1-1-2,2-1-1,0-1-1] SET SESSION debug_dbug="+d,crash_dispatch_command_before"; SELECT 1; Got one of the listed errors @@ -53,7 +53,7 @@ master-bin.000003 # master-bin.000004 # SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000004 # Gtid_list # # [1-1-3,0-1-1,2-1-4] +master-bin.000004 # Gtid_list # # [1-1-2,0-1-1,2-1-1] SELECT * FROM t1 ORDER BY a; a 1 diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result index fe69c83615e..59f288d4afd 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_errorhandling.result @@ -46,6 +46,12 @@ INSERT INTO t1 VALUES (100); SET GLOBAL gtid_slave_pos = "100-100-100"; ERROR 25000: You are not allowed to execute this command in a transaction ROLLBACK; +SET GLOBAL gtid_strict_mode= 1; +SET GLOBAL gtid_slave_pos = "0-1-1"; +ERROR HY000: Specified GTID 0-1-1 conflicts with the binary log which contains a more recent GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. +SET GLOBAL gtid_slave_pos = ""; +ERROR HY000: Specified value for @@gtid_slave_pos contains no value for replication domain 0. This conflicts with the binary log which contains GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. +SET GLOBAL gtid_strict_mode= 0; SET GLOBAL gtid_slave_pos = "0-1-1"; Warnings: Warning 1947 Specified GTID 0-1-1 conflicts with the binary log which contains a more recent GTID 0-2-11. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos. diff --git a/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result index 0a55fe5a026..132c01f5f55 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_master_promote.result @@ -41,10 +41,10 @@ INSERT INTO t4 VALUES (3, 1); INSERT INTO t3 VALUES (3); INSERT INTO t3 VALUES (4); INSERT INTO t4 VALUES (3, 3); -START SLAVE UNTIL master_gtid_pos= "1-1-7,2-1-14,3-1-21"; -START SLAVE UNTIL master_gtid_pos= "1-1-4,2-1-14,3-1-24"; -START SLAVE UNTIL master_gtid_pos= "2-1-11,3-1-21,1-1-10"; -START SLAVE UNTIL master_gtid_pos= "3-1-18,1-1-7,2-1-17"; +START SLAVE UNTIL master_gtid_pos= "1-1-4,2-1-4,3-1-4"; +START SLAVE UNTIL master_gtid_pos= "1-1-1,2-1-4,3-1-7"; +START SLAVE UNTIL master_gtid_pos= "2-1-1,3-1-4,1-1-7"; +START SLAVE UNTIL master_gtid_pos= "3-1-1,1-1-4,2-1-7"; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -119,7 +119,7 @@ a b 2 3 *** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. *** CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3; -START SLAVE UNTIL master_gtid_pos = "1-1-4,0-1-3,3-1-24,2-1-14"; +START SLAVE UNTIL master_gtid_pos = "1-1-1,0-1-3,3-1-7,2-1-4"; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -142,7 +142,7 @@ a b 3 1 3 3 CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4; -START SLAVE UNTIL master_gtid_pos = "1-1-10,0-1-3,3-1-21,2-1-11"; +START SLAVE UNTIL master_gtid_pos = "1-1-7,0-1-3,3-1-4,2-1-1"; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -168,7 +168,7 @@ a b 3 1 3 3 CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_5; -START SLAVE UNTIL master_gtid_pos = "1-1-7,0-1-3,3-1-18,2-1-17"; +START SLAVE UNTIL master_gtid_pos = "1-1-4,0-1-3,3-1-1,2-1-7"; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index 50a7195a288..dcfdc567736 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -32,10 +32,10 @@ master-bin.000003 # Gtid_list # # [0-1-3] FLUSH LOGS; SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000004 # Gtid_list # # [1-1-5,0-1-4] +master-bin.000004 # Gtid_list # # [1-1-1,0-1-4] SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000005 # Gtid_list # # [1-1-5,0-1-4] +master-bin.000005 # Gtid_list # # [1-1-1,0-1-4] show binary logs; Log_name File_size master-bin.000002 # diff --git a/mysql-test/suite/rpl/r/rpl_gtid_strict.result b/mysql-test/suite/rpl/r/rpl_gtid_strict.result new file mode 100644 index 00000000000..d197e0a9213 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_strict.result @@ -0,0 +1,182 @@ +include/rpl_init.inc [topology=1->2] +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 0; +call mtr.add_suppression("Error writing file .*errno: 1950"); +SET sql_log_bin= 1; +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +include/stop_slave.inc +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode=1; +CHANGE MASTER TO master_use_gtid=slave_pos; +include/start_slave.inc +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1) +master-bin.000001 # Xid # # COMMIT /* XID */ +SET server_id= 3; +SET gtid_seq_no= 3; +ERROR HY000: An attempt was made to binlog GTID 0-3-3 which would create an out-of-order sequence number with existing GTID 0-1-3, and gtid strict mode is enabled. +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 3; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +INSERT INTO t1 VALUES (2); +ERROR HY000: An attempt was made to binlog GTID 0-3-3 which would create an out-of-order sequence number with existing GTID 0-1-3, and gtid strict mode is enabled. +SET gtid_seq_no= 2; +ERROR HY000: An attempt was made to binlog GTID 0-3-2 which would create an out-of-order sequence number with existing GTID 0-1-3, and gtid strict mode is enabled. +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 2; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +INSERT INTO t1 VALUES (3); +ERROR HY000: An attempt was made to binlog GTID 0-3-2 which would create an out-of-order sequence number with existing GTID 0-1-3, and gtid strict mode is enabled. +SET server_id= 1; +SET gtid_seq_no= 4; +INSERT INTO t1 VALUES (4); +SELECT * FROM t1 ORDER BY 1; +a +1 +4 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4) +master-bin.000001 # Xid # # COMMIT /* XID */ +*** Test non-transactional GTID error (cannot be rolled back). *** +SET server_id= 3; +SET gtid_seq_no= 1; +ERROR HY000: An attempt was made to binlog GTID 0-3-1 which would create an out-of-order sequence number with existing GTID 0-1-4, and gtid strict mode is enabled. +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; +ERROR HY000: An attempt was made to binlog GTID 0-3-1 which would create an out-of-order sequence number with existing GTID 0-1-4, and gtid strict mode is enabled. +SET sql_log_bin= 0; +DROP TABLE t2; +SET sql_log_bin= 1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; +SET gtid_seq_no= 1; +ERROR HY000: An attempt was made to binlog GTID 0-3-1 which would create an out-of-order sequence number with existing GTID 0-3-5, and gtid strict mode is enabled. +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +INSERT INTO t2 VALUES (1); +ERROR HY000: An attempt was made to binlog GTID 0-3-1 which would create an out-of-order sequence number with existing GTID 0-3-5, and gtid strict mode is enabled. +SET server_id= 1; +SET gtid_seq_no= 6; +INSERT INTO t2 VALUES (2); +SELECT * FROM t2 ORDER BY a; +a +1 +2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (2) +master-bin.000001 # Query # # COMMIT +*** Test that slave stops if it tries to apply a GTID that would create out-of-order binlog GTID sequence numbers. *** +SELECT * FROM t1 ORDER BY a; +a +1 +4 +SELECT * FROM t2 ORDER BY a; +a +2 +SET sql_log_bin= 0; +call mtr.add_suppression("An attempt was made to binlog GTID .* which would create an out-of-order sequence number with existing GTID .*, and gtid strict mode is enabled"); +call mtr.add_suppression("The binlog on the master is missing the GTID [-0-9]+ requested by the slave"); +SET sql_log_bin= 1; +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +include/wait_for_slave_sql_error.inc [errno=1950] +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +include/start_slave.inc +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t1 ORDER BY a; +a +1 +4 +5 +6 +INSERT INTO t1 VALUES (7); +CREATE TABLE t3 (a INT PRIMARY KEY); +include/wait_for_slave_sql_error.inc [errno=1950] +SHOW CREATE TABLE t3; +ERROR 42S02: Table 'test.t3' doesn't exist +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +include/start_slave.inc +SET GLOBAL gtid_strict_mode=1; +SHOW CREATE TABLE t3; +Table t3 +Create Table CREATE TABLE `t3` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (8); +INSERT INTO t2 VALUES (3); +include/wait_for_slave_sql_error.inc [errno=1950] +SELECT * FROM t2 ORDER BY a; +a +2 +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +include/start_slave.inc +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t2 ORDER BY a; +a +2 +3 +*** Check slave requests starting from a hole on the master. *** +include/stop_slave.inc +INSERT INTO t1 VALUES (10); +SET gtid_seq_no= 100; +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +SET GLOBAL gtid_slave_pos= "0-1-50"; +START SLAVE; +include/wait_for_slave_io_error.inc [errno=1236] +STOP SLAVE SQL_THREAD; +SET GLOBAL gtid_strict_mode= 0; +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +4 +5 +6 +7 +8 +11 +12 +SET GLOBAL gtid_strict_mode= 1; +DROP TABLE t1, t2, t3; +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_until.result b/mysql-test/suite/rpl/r/rpl_gtid_until.result index 44573a29794..53100af4c71 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_until.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_until.result @@ -79,7 +79,7 @@ master-bin.000001 # master-bin.000002 # master-bin.000003 # master-bin.000004 # -START SLAVE UNTIL master_gtid_pos='1-1-11,2-1-12'; +START SLAVE UNTIL master_gtid_pos='1-1-3,2-1-4'; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -93,7 +93,7 @@ a 3 4 5 -START SLAVE UNTIL master_gtid_pos='1-1-13,2-1-8'; +START SLAVE UNTIL master_gtid_pos='1-1-4,2-1-2'; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -108,7 +108,7 @@ a 3 4 5 -START SLAVE UNTIL master_gtid_pos='1-1-11'; +START SLAVE UNTIL master_gtid_pos='1-1-3'; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -144,7 +144,7 @@ FLUSH LOGS; SET gtid_domain_id = 1; INSERT INTO t1 VALUES (7); SET gtid_domain_id = 0; -START SLAVE UNTIL master_gtid_pos='1-1-13'; +START SLAVE UNTIL master_gtid_pos='1-1-4'; include/wait_for_slave_to_stop.inc SELECT * FROM t1 ORDER BY a; a @@ -168,7 +168,7 @@ a include/stop_slave.inc CREATE TABLE t3 (a INT); DROP TABLE t3; -START SLAVE UNTIL master_gtid_pos='1-1-15,2-1-14,0-1-16'; +START SLAVE UNTIL master_gtid_pos='1-1-5,2-1-5,0-1-6'; include/wait_for_slave_to_stop.inc SHOW CREATE TABLE t3; Table Create Table diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test index c5f695fd5a1..f36f7fa8010 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test @@ -80,7 +80,13 @@ SET GLOBAL gtid_slave_pos = "100-100-100"; ROLLBACK; # In gtid non-strict mode, we get warnings for setting @@gtid_slave_pos back -# to earlier than what is in the binlog. +# to earlier than what is in the binlog. In strict mode, we get an error. +SET GLOBAL gtid_strict_mode= 1; +--error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG +SET GLOBAL gtid_slave_pos = "0-1-1"; +--error ER_MASTER_GTID_POS_MISSING_DOMAIN +SET GLOBAL gtid_slave_pos = ""; +SET GLOBAL gtid_strict_mode= 0; SET GLOBAL gtid_slave_pos = "0-1-1"; SET GLOBAL gtid_slave_pos = ""; RESET MASTER; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_strict.test b/mysql-test/suite/rpl/t/rpl_gtid_strict.test new file mode 100644 index 00000000000..afcb179da78 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_strict.test @@ -0,0 +1,178 @@ +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 0; +call mtr.add_suppression("Error writing file .*errno: 1950"); + +SET sql_log_bin= 1; + +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +--connection server_2 +--source include/stop_slave.inc +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode=1; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--source include/show_binlog_events.inc + +SET server_id= 3; +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 3; +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 3; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t1 VALUES (2); + +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 2; +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 2; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t1 VALUES (3); +SET server_id= 1; +SET gtid_seq_no= 4; +INSERT INTO t1 VALUES (4); +SELECT * FROM t1 ORDER BY 1; +--source include/show_binlog_events.inc + +--echo *** Test non-transactional GTID error (cannot be rolled back). *** +SET server_id= 3; +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 1; +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +--error ER_GTID_STRICT_OUT_OF_ORDER +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; +# The table is still created, DDL cannot be rolled back. +# Fix it up for replication. +SET sql_log_bin= 0; +DROP TABLE t2; +SET sql_log_bin= 1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; + +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 1; +SET SESSION debug_dbug="+d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug="-d,ignore_set_gtid_seq_no_check"; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t2 VALUES (1); +# The value is still inserted, cannot be rolled back. +SET server_id= 1; +SET gtid_seq_no= 6; +INSERT INTO t2 VALUES (2); +SELECT * FROM t2 ORDER BY a; +--source include/show_binlog_events.inc + + +--echo *** Test that slave stops if it tries to apply a GTID that would create out-of-order binlog GTID sequence numbers. *** + +--save_master_pos +--connection server_2 +--sync_with_master + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SET sql_log_bin= 0; +call mtr.add_suppression("An attempt was made to binlog GTID .* which would create an out-of-order sequence number with existing GTID .*, and gtid strict mode is enabled"); +call mtr.add_suppression("The binlog on the master is missing the GTID [-0-9]+ requested by the slave"); +SET sql_log_bin= 1; + +# Create some out-of-order stuff on slave. +INSERT INTO t1 VALUES (5); + +--connection server_1 +INSERT INTO t1 VALUES (6); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t1 ORDER BY a; + +INSERT INTO t1 VALUES (7); +--connection server_1 +CREATE TABLE t3 (a INT PRIMARY KEY); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +--error ER_NO_SUCH_TABLE +--query_vertical SHOW CREATE TABLE t3 +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +--query_vertical SHOW CREATE TABLE t3 + +INSERT INTO t1 VALUES (8); +--connection server_1 +INSERT INTO t2 VALUES (3); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +SELECT * FROM t2 ORDER BY a; +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t2 ORDER BY a; + + +--echo *** Check slave requests starting from a hole on the master. *** +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (10); +SET gtid_seq_no= 100; +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +--save_master_pos + +--connection server_2 +SET GLOBAL gtid_slave_pos= "0-1-50"; +START SLAVE; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc +STOP SLAVE SQL_THREAD; +SET GLOBAL gtid_strict_mode= 0; +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t1 ORDER BY a; +SET GLOBAL gtid_strict_mode= 1; + + +# Clean up. +--connection server_1 +DROP TABLE t1, t2, t3; +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +--connection server_2 +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/gtid_strict_mode_basic.result b/mysql-test/suite/sys_vars/r/gtid_strict_mode_basic.result new file mode 100644 index 00000000000..25afe97f4c9 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/gtid_strict_mode_basic.result @@ -0,0 +1,29 @@ +select @@global.gtid_strict_mode; +@@global.gtid_strict_mode +0 +select @@session.gtid_strict_mode; +ERROR HY000: Variable 'gtid_strict_mode' is a GLOBAL variable +show global variables like 'gtid_strict_mode'; +Variable_name Value +gtid_strict_mode OFF +show session variables like 'gtid_strict_mode'; +Variable_name Value +gtid_strict_mode OFF +select * from information_schema.global_variables where variable_name='gtid_strict_mode'; +VARIABLE_NAME VARIABLE_VALUE +GTID_STRICT_MODE OFF +select * from information_schema.session_variables where variable_name='gtid_strict_mode'; +VARIABLE_NAME VARIABLE_VALUE +GTID_STRICT_MODE OFF +SET @old= @@GLOBAL.gtid_strict_mode; +set global gtid_strict_mode=1; +select @@global.gtid_strict_mode; +@@global.gtid_strict_mode +1 +set global gtid_strict_mode=0; +select @@global.gtid_strict_mode; +@@global.gtid_strict_mode +0 +set global gtid_strict_mode=@old; +set session gtid_strict_mode=1; +ERROR HY000: Variable 'gtid_strict_mode' is a GLOBAL variable and should be set with SET GLOBAL diff --git a/mysql-test/suite/sys_vars/t/gtid_strict_mode_basic.test b/mysql-test/suite/sys_vars/t/gtid_strict_mode_basic.test new file mode 100644 index 00000000000..c6287dcd6bc --- /dev/null +++ b/mysql-test/suite/sys_vars/t/gtid_strict_mode_basic.test @@ -0,0 +1,21 @@ +--source include/not_embedded.inc +# +# only global +# +select @@global.gtid_strict_mode; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.gtid_strict_mode; +show global variables like 'gtid_strict_mode'; +show session variables like 'gtid_strict_mode'; +select * from information_schema.global_variables where variable_name='gtid_strict_mode'; +select * from information_schema.session_variables where variable_name='gtid_strict_mode'; + +SET @old= @@GLOBAL.gtid_strict_mode; +set global gtid_strict_mode=1; +select @@global.gtid_strict_mode; +set global gtid_strict_mode=0; +select @@global.gtid_strict_mode; +set global gtid_strict_mode=@old; + +--error ER_GLOBAL_VARIABLE +set session gtid_strict_mode=1; diff --git a/sql/log.cc b/sql/log.cc index 238452070ff..c3ea089af69 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3841,9 +3841,6 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log) if (!is_relay_log) { rpl_global_gtid_binlog_state.reset(); - mysql_mutex_lock(&LOCK_gtid_counter); - global_gtid_counter= 0; - mysql_mutex_unlock(&LOCK_gtid_counter); } /* Start logging with a new file */ @@ -5367,9 +5364,11 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, bool is_transactional) { rpl_gtid gtid; - uint64 seq_no; + uint32 domain_id= thd->variables.gtid_domain_id; + uint32 server_id= thd->variables.server_id; + uint64 seq_no= thd->variables.gtid_seq_no; + int err; - seq_no= thd->variables.gtid_seq_no; /* Reset the session variable gtid_seq_no, to reduce the risk of accidentally producing a duplicate GTID. @@ -5377,34 +5376,36 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, thd->variables.gtid_seq_no= 0; if (seq_no != 0) { - /* - If we see a higher sequence number, use that one as the basis of any - later generated sequence numbers. - */ - bump_seq_no_counter_if_needed(seq_no); + /* Use the specified sequence number. */ + gtid.domain_id= domain_id; + gtid.server_id= server_id; + gtid.seq_no= seq_no; + mysql_mutex_lock(&LOCK_rpl_gtid_state); + err= rpl_global_gtid_binlog_state.update(>id, opt_gtid_strict_mode); + mysql_mutex_unlock(&LOCK_rpl_gtid_state); + if (err && thd->stmt_da->sql_errno()==ER_GTID_STRICT_OUT_OF_ORDER) + errno= ER_GTID_STRICT_OUT_OF_ORDER; } else { - mysql_mutex_lock(&LOCK_gtid_counter); - seq_no= ++global_gtid_counter; - mysql_mutex_unlock(&LOCK_gtid_counter); + /* Allocate the next sequence number for the GTID. */ + mysql_mutex_lock(&LOCK_rpl_gtid_state); + err= rpl_global_gtid_binlog_state.update_with_next_gtid(domain_id, + server_id, >id); + mysql_mutex_unlock(&LOCK_rpl_gtid_state); + seq_no= gtid.seq_no; } - gtid.seq_no= seq_no; - gtid.domain_id= thd->variables.gtid_domain_id; + if (err) + return true; - Gtid_log_event gtid_event(thd, gtid.seq_no, gtid.domain_id, standalone, + Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone, LOG_EVENT_SUPPRESS_USE_F, is_transactional); - gtid.server_id= gtid_event.server_id; /* Write the event to the binary log. */ if (gtid_event.write(&mysql_bin_log.log_file)) return true; status_var_add(thd->status_var.binlog_bytes_written, gtid_event.data_written); - /* Update the replication state (last GTID in each replication domain). */ - mysql_mutex_lock(&LOCK_rpl_gtid_state); - rpl_global_gtid_binlog_state.update(>id); - mysql_mutex_unlock(&LOCK_rpl_gtid_state); return false; } @@ -5505,9 +5506,6 @@ end: end_io_cache(&cache); if (opened) mysql_file_close(file_no, MYF(0)); - /* Pick the next unused seq_no from the loaded binlog state. */ - bump_seq_no_counter_if_needed( - rpl_global_gtid_binlog_state.seq_no_from_state()); return err; } @@ -5549,33 +5547,44 @@ bool MYSQL_BIN_LOG::lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid) { - rpl_binlog_state::element *elem; - bool res; + rpl_gtid *found_gtid; + bool res= false; mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); - elem= (rpl_binlog_state::element *) - my_hash_search(&rpl_global_gtid_binlog_state.hash, - (const uchar *)&domain_id, 0); - if (elem) + if ((found_gtid= rpl_global_gtid_binlog_state.find_most_recent(domain_id))) { + *out_gtid= *found_gtid; res= true; - *out_gtid= *elem->last_gtid; } - else - res= false; mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); return res; } -void -MYSQL_BIN_LOG::bump_seq_no_counter_if_needed(uint64 seq_no) +int +MYSQL_BIN_LOG::bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no) { - mysql_mutex_lock(&LOCK_gtid_counter); - if (global_gtid_counter < seq_no) - global_gtid_counter= seq_no; - mysql_mutex_unlock(&LOCK_gtid_counter); + int err; + + mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + err= rpl_global_gtid_binlog_state.bump_seq_no_if_needed(domain_id, seq_no); + mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + return err; +} + + +bool +MYSQL_BIN_LOG::check_strict_gtid_sequence(uint32 domain_id, uint32 server_id, + uint64 seq_no) +{ + bool err; + + mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + err= rpl_global_gtid_binlog_state.check_strict_sequence(domain_id, server_id, + seq_no); + mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state); + return err; } @@ -5648,7 +5657,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) my_org_b_tell= my_b_tell(file); mysql_mutex_lock(&LOCK_log); prev_binlog_id= current_binlog_id; - write_gtid_event(thd, true, using_trans); + if (write_gtid_event(thd, true, using_trans)) + goto err; } else { @@ -6717,8 +6727,8 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) */ DBUG_ASSERT(!cache_mngr->stmt_cache.empty() || !cache_mngr->trx_cache.empty()); - current->error= write_transaction_or_stmt(current); - + if ((current->error= write_transaction_or_stmt(current))) + current->commit_errno= errno; strmake(cache_mngr->last_commit_pos_file, log_file_name, sizeof(cache_mngr->last_commit_pos_file)-1); commit_offset= my_b_write_tell(&log_file); @@ -8264,9 +8274,6 @@ int TC_LOG_BINLOG::open(const char *opt_name) error= recover(&log_info, log_name, &log, (Format_description_log_event *)ev); state_read= true; - /* Pick the next unused seq_no from the recovered binlog state. */ - bump_seq_no_counter_if_needed( - rpl_global_gtid_binlog_state.seq_no_from_state()); } else error= read_state_from_file(); @@ -8748,7 +8755,7 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name, gtid.domain_id= gev->domain_id; gtid.server_id= gev->server_id; gtid.seq_no= gev->seq_no; - if (rpl_global_gtid_binlog_state.update(>id)) + if (rpl_global_gtid_binlog_state.update(>id, false)) goto err2; } break; diff --git a/sql/log.h b/sql/log.h index f41b48eba7c..018ac64eff7 100644 --- a/sql/log.h +++ b/sql/log.h @@ -783,7 +783,9 @@ public: bool find_in_binlog_state(uint32 domain_id, uint32 server_id, rpl_gtid *out_gtid); bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid); - void bump_seq_no_counter_if_needed(uint64 seq_no); + int bump_seq_no_counter_if_needed(uint32 domain_id, uint64 seq_no); + bool check_strict_gtid_sequence(uint32 domain_id, uint32 server_id, + uint64 seq_no); }; class Log_event_handler diff --git a/sql/log_event.cc b/sql/log_event.cc index f4e34dd9224..0a21ae6d279 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6214,6 +6214,15 @@ Gtid_log_event::do_apply_event(Relay_log_info const *rli) thd->variables.gtid_domain_id= this->domain_id; thd->variables.gtid_seq_no= this->seq_no; + if (opt_gtid_strict_mode && opt_bin_log && opt_log_slave_updates) + { + /* Need to reset prior "ok" status to give an error. */ + thd->clear_error(); + thd->stmt_da->reset_diagnostics_area(); + if (mysql_bin_log.check_strict_gtid_sequence(this->domain_id, + this->server_id, this->seq_no)) + return 1; + } if (flags2 & FL_STANDALONE) return 0; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 963f259f486..1102a527546 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -677,7 +677,7 @@ mysql_mutex_t mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats, LOCK_global_table_stats, LOCK_global_index_stats; -mysql_mutex_t LOCK_gtid_counter, LOCK_rpl_gtid_state; +mysql_mutex_t LOCK_rpl_gtid_state; /** The below lock protects access to two global server variables: @@ -776,7 +776,7 @@ PSI_mutex_key key_LOCK_stats, key_LOCK_global_index_stats, key_LOCK_wakeup_ready; -PSI_mutex_key key_LOCK_gtid_counter, key_LOCK_rpl_gtid_state; +PSI_mutex_key key_LOCK_rpl_gtid_state; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; @@ -821,7 +821,6 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_global_table_stats, "LOCK_global_table_stats", PSI_FLAG_GLOBAL}, { &key_LOCK_global_index_stats, "LOCK_global_index_stats", PSI_FLAG_GLOBAL}, { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0}, - { &key_LOCK_gtid_counter, "LOCK_gtid_counter", PSI_FLAG_GLOBAL}, { &key_LOCK_rpl_gtid_state, "LOCK_rpl_gtid_state", PSI_FLAG_GLOBAL}, { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0}, { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL}, @@ -1294,10 +1293,7 @@ struct st_VioSSLFd *ssl_acceptor_fd; */ uint connection_count= 0, extra_connection_count= 0; -/** - Running counter for generating new GTIDs locally. -*/ -uint64 global_gtid_counter= 0; +my_bool opt_gtid_strict_mode= FALSE; /* Function declarations */ @@ -1977,7 +1973,6 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_global_user_client_stats); mysql_mutex_destroy(&LOCK_global_table_stats); mysql_mutex_destroy(&LOCK_global_index_stats); - mysql_mutex_destroy(&LOCK_gtid_counter); mysql_mutex_destroy(&LOCK_rpl_gtid_state); #ifdef HAVE_OPENSSL mysql_mutex_destroy(&LOCK_des_key_file); @@ -4089,8 +4084,6 @@ static int init_thread_environment() &LOCK_global_table_stats, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_global_index_stats, &LOCK_global_index_stats, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_LOCK_gtid_counter, - &LOCK_gtid_counter, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_rpl_gtid_state, &LOCK_rpl_gtid_state, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_LOCK_prepare_ordered, &LOCK_prepare_ordered, diff --git a/sql/mysqld.h b/sql/mysqld.h index c4b62c84603..9c9bf71fec8 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -253,7 +253,7 @@ extern PSI_mutex_key key_LOCK_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, key_LOCK_global_index_stats, key_LOCK_wakeup_ready; -extern PSI_mutex_key key_LOCK_gtid_counter, key_LOCK_rpl_gtid_state; +extern PSI_mutex_key key_LOCK_rpl_gtid_state; extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, @@ -345,7 +345,7 @@ extern mysql_mutex_t LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_system_variables, LOCK_user_conn, LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count; -extern mysql_mutex_t LOCK_gtid_counter, LOCK_rpl_gtid_state; +extern mysql_mutex_t LOCK_rpl_gtid_state; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count; #ifdef HAVE_OPENSSL extern mysql_mutex_t LOCK_des_key_file; @@ -541,6 +541,7 @@ extern handlerton *maria_hton; extern uint extra_connection_count; extern uint64 global_gtid_counter; +extern my_bool opt_gtid_strict_mode; extern my_bool opt_userstat_running, debug_assert_if_crashed_table; extern uint mysqld_extra_port; extern ulong opt_progress_report_time; diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 01502c5b0f1..b34b890060b 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -370,7 +370,10 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, } table->file->ha_index_end(); - mysql_bin_log.bump_seq_no_counter_if_needed(gtid->seq_no); + if(!err && opt_bin_log && + (err= mysql_bin_log.bump_seq_no_counter_if_needed(gtid->domain_id, + gtid->seq_no))) + my_error(ER_OUT_OF_RESOURCES, MYF(0)); end: @@ -719,7 +722,7 @@ rpl_binlog_state::load(struct rpl_gtid *list, uint32 count) reset(); for (i= 0; i < count; ++i) { - if (update(&(list[i]))) + if (update(&(list[i]), false)) return true; } return false; @@ -741,48 +744,111 @@ rpl_binlog_state::~rpl_binlog_state() Returns 0 for ok, 1 for error. */ int -rpl_binlog_state::update(const struct rpl_gtid *gtid) +rpl_binlog_state::update(const struct rpl_gtid *gtid, bool strict) { - rpl_gtid *lookup_gtid; element *elem; - elem= (element *)my_hash_search(&hash, (const uchar *)(>id->domain_id), 0); - if (elem) + if ((elem= (element *)my_hash_search(&hash, + (const uchar *)(>id->domain_id), 0))) { - /* - By far the most common case is that successive events within same - replication domain have the same server id (it changes only when - switching to a new master). So save a hash lookup in this case. - */ - if (likely(elem->last_gtid->server_id == gtid->server_id)) + if (strict && elem->last_gtid && elem->last_gtid->seq_no >= gtid->seq_no) { - elem->last_gtid->seq_no= gtid->seq_no; - return 0; - } - - lookup_gtid= (rpl_gtid *) - my_hash_search(&elem->hash, (const uchar *)>id->server_id, 0); - if (lookup_gtid) - { - lookup_gtid->seq_no= gtid->seq_no; - elem->last_gtid= lookup_gtid; - return 0; - } - - /* Allocate a new GTID and insert it. */ - lookup_gtid= (rpl_gtid *)my_malloc(sizeof(*lookup_gtid), MYF(MY_WME)); - if (!lookup_gtid) - return 1; - memcpy(lookup_gtid, gtid, sizeof(*lookup_gtid)); - if (my_hash_insert(&elem->hash, (const uchar *)lookup_gtid)) - { - my_free(lookup_gtid); + my_error(ER_GTID_STRICT_OUT_OF_ORDER, MYF(0), gtid->domain_id, + gtid->server_id, gtid->seq_no, elem->last_gtid->domain_id, + elem->last_gtid->server_id, elem->last_gtid->seq_no); return 1; } - elem->last_gtid= lookup_gtid; + if (elem->seq_no_counter < gtid->seq_no) + elem->seq_no_counter= gtid->seq_no; + if (!elem->update_element(gtid)) + return 0; + } + else if (!alloc_element(gtid)) + return 0; + + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + return 1; +} + + +/* + Fill in a new GTID, allocating next sequence number, and update state + accordingly. +*/ +int +rpl_binlog_state::update_with_next_gtid(uint32 domain_id, uint32 server_id, + rpl_gtid *gtid) +{ + element *elem; + + gtid->domain_id= domain_id; + gtid->server_id= server_id; + + if ((elem= (element *)my_hash_search(&hash, (const uchar *)(&domain_id), 0))) + { + gtid->seq_no= ++elem->seq_no_counter; + if (!elem->update_element(gtid)) + return 0; + } + else + { + gtid->seq_no= 1; + if (!alloc_element(gtid)) + return 0; + } + + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + return 1; +} + + +/* Helper functions for update. */ +int +rpl_binlog_state::element::update_element(const rpl_gtid *gtid) +{ + rpl_gtid *lookup_gtid; + + /* + By far the most common case is that successive events within same + replication domain have the same server id (it changes only when + switching to a new master). So save a hash lookup in this case. + */ + if (likely(last_gtid && last_gtid->server_id == gtid->server_id)) + { + last_gtid->seq_no= gtid->seq_no; return 0; } + lookup_gtid= (rpl_gtid *) + my_hash_search(&hash, (const uchar *)>id->server_id, 0); + if (lookup_gtid) + { + lookup_gtid->seq_no= gtid->seq_no; + last_gtid= lookup_gtid; + return 0; + } + + /* Allocate a new GTID and insert it. */ + lookup_gtid= (rpl_gtid *)my_malloc(sizeof(*lookup_gtid), MYF(MY_WME)); + if (!lookup_gtid) + return 1; + memcpy(lookup_gtid, gtid, sizeof(*lookup_gtid)); + if (my_hash_insert(&hash, (const uchar *)lookup_gtid)) + { + my_free(lookup_gtid); + return 1; + } + last_gtid= lookup_gtid; + return 0; +} + + +int +rpl_binlog_state::alloc_element(const rpl_gtid *gtid) +{ + element *elem; + rpl_gtid *lookup_gtid; + /* First time we see this domain_id; allocate a new element. */ elem= (element *)my_malloc(sizeof(*elem), MYF(MY_WME)); lookup_gtid= (rpl_gtid *)my_malloc(sizeof(*lookup_gtid), MYF(MY_WME)); @@ -793,6 +859,7 @@ rpl_binlog_state::update(const struct rpl_gtid *gtid) offsetof(rpl_gtid, server_id), sizeof(uint32), NULL, my_free, HASH_UNIQUE); elem->last_gtid= lookup_gtid; + elem->seq_no_counter= gtid->seq_no; memcpy(lookup_gtid, gtid, sizeof(*lookup_gtid)); if (0 == my_hash_insert(&elem->hash, (const uchar *)lookup_gtid)) { @@ -812,23 +879,64 @@ rpl_binlog_state::update(const struct rpl_gtid *gtid) } -uint64 -rpl_binlog_state::seq_no_from_state() +/* + Check that a new GTID can be logged without creating an out-of-order + sequence number with existing GTIDs. +*/ +bool +rpl_binlog_state::check_strict_sequence(uint32 domain_id, uint32 server_id, + uint64 seq_no) { - ulong i, j; - uint64 seq_no= 0; + element *elem; - for (i= 0; i < hash.records; ++i) + if ((elem= (element *)my_hash_search(&hash, + (const uchar *)(&domain_id), 0)) && + elem->last_gtid && elem->last_gtid->seq_no >= seq_no) { - element *e= (element *)my_hash_element(&hash, i); - for (j= 0; j < e->hash.records; ++j) - { - const rpl_gtid *gtid= (const rpl_gtid *)my_hash_element(&e->hash, j); - if (gtid->seq_no > seq_no) - seq_no= gtid->seq_no; - } + my_error(ER_GTID_STRICT_OUT_OF_ORDER, MYF(0), domain_id, server_id, seq_no, + elem->last_gtid->domain_id, elem->last_gtid->server_id, + elem->last_gtid->seq_no); + return 1; } - return seq_no; + return 0; +} + + +/* + When we see a new GTID that will not be binlogged (eg. slave thread + with --log-slave-updates=0), then we need to remember to allocate any + GTID seq_no of our own within that domain starting from there. + + Returns 0 if ok, non-zero if out-of-memory. +*/ +int +rpl_binlog_state::bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no) +{ + element *elem; + + if ((elem= (element *)my_hash_search(&hash, (const uchar *)(&domain_id), 0))) + { + if (elem->seq_no_counter < seq_no) + elem->seq_no_counter= seq_no; + return 0; + } + + /* We need to allocate a new, empty element to remember the next seq_no. */ + if (!(elem= (element *)my_malloc(sizeof(*elem), MYF(MY_WME)))) + return 1; + + elem->domain_id= domain_id; + my_hash_init(&elem->hash, &my_charset_bin, 32, + offsetof(rpl_gtid, server_id), sizeof(uint32), NULL, my_free, + HASH_UNIQUE); + elem->last_gtid= NULL; + elem->seq_no_counter= seq_no; + if (0 == my_hash_insert(&hash, (const uchar *)elem)) + return 0; + + my_hash_free(&elem->hash); + my_free(elem); + return 1; } @@ -849,6 +957,11 @@ rpl_binlog_state::write_to_iocache(IO_CACHE *dest) { size_t res; element *e= (element *)my_hash_element(&hash, i); + if (!e->last_gtid) + { + DBUG_ASSERT(e->hash.records == 0); + continue; + } for (j= 0; j <= e->hash.records; ++j) { const rpl_gtid *gtid; @@ -890,7 +1003,7 @@ rpl_binlog_state::read_from_iocache(IO_CACHE *src) end= buf + res; if (gtid_parser_helper(&p, end, >id)) return 1; - if (update(>id)) + if (update(>id, false)) return 1; } return 0; @@ -906,6 +1019,17 @@ rpl_binlog_state::find(uint32 domain_id, uint32 server_id) return (rpl_gtid *)my_hash_search(&elem->hash, (const uchar *)&server_id, 0); } +rpl_gtid * +rpl_binlog_state::find_most_recent(uint32 domain_id) +{ + element *elem; + + elem= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0); + if (elem && elem->last_gtid) + return elem->last_gtid; + return NULL; +} + uint32 rpl_binlog_state::count() @@ -929,6 +1053,11 @@ rpl_binlog_state::get_gtid_list(rpl_gtid *gtid_list, uint32 list_size) for (i= 0; i < hash.records; ++i) { element *e= (element *)my_hash_element(&hash, i); + if (!e->last_gtid) + { + DBUG_ASSERT(e->hash.records==0); + continue; + } for (j= 0; j <= e->hash.records; ++j) { const rpl_gtid *gtid; @@ -965,16 +1094,22 @@ int rpl_binlog_state::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size) { uint32 i; + uint32 alloc_size, out_size; - *size= hash.records; - if (!(*list= (rpl_gtid *)my_malloc(*size * sizeof(rpl_gtid), MYF(MY_WME)))) + alloc_size= hash.records; + if (!(*list= (rpl_gtid *)my_malloc(alloc_size * sizeof(rpl_gtid), + MYF(MY_WME)))) return 1; - for (i= 0; i < *size; ++i) + out_size= 0; + for (i= 0; i < alloc_size; ++i) { element *e= (element *)my_hash_element(&hash, i); - memcpy(&((*list)[i]), e->last_gtid, sizeof(rpl_gtid)); + if (!e->last_gtid) + continue; + memcpy(&((*list)[out_size++]), e->last_gtid, sizeof(rpl_gtid)); } + *size= out_size; return 0; } @@ -988,7 +1123,8 @@ rpl_binlog_state::append_pos(String *str) for (i= 0; i < hash.records; ++i) { element *e= (element *)my_hash_element(&hash, i); - if (rpl_slave_state_tostring_helper(str, e->last_gtid, &first)) + if (e->last_gtid && + rpl_slave_state_tostring_helper(str, e->last_gtid, &first)) return true; } diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index cc3c99f40b7..fefce684c2c 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -131,6 +131,10 @@ struct rpl_binlog_state HASH hash; /* Containing all server_id for one domain_id */ /* The most recent entry in the hash. */ rpl_gtid *last_gtid; + /* Counter to allocate next seq_no for this domain. */ + uint64 seq_no_counter; + + int update_element(const rpl_gtid *gtid); }; /* Mapping from domain_id to collection of elements. */ HASH hash; @@ -144,8 +148,12 @@ struct rpl_binlog_state void reset(); void free(); bool load(struct rpl_gtid *list, uint32 count); - int update(const struct rpl_gtid *gtid); - uint64 seq_no_from_state(); + int update(const struct rpl_gtid *gtid, bool strict); + int update_with_next_gtid(uint32 domain_id, uint32 server_id, + rpl_gtid *gtid); + int alloc_element(const rpl_gtid *gtid); + bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no); + int bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no); int write_to_iocache(IO_CACHE *dest); int read_from_iocache(IO_CACHE *src); uint32 count(); @@ -153,6 +161,7 @@ struct rpl_binlog_state int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); bool append_pos(String *str); rpl_gtid *find(uint32 domain_id, uint32 server_id); + rpl_gtid *find_most_recent(uint32 domain_id); }; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index d27a80313ac..03ec77e1433 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1397,7 +1397,6 @@ rpl_load_gtid_slave_state(THD *thd) HASH hash; int err= 0; uint32 i; - uint64 highest_seq_no= 0; DBUG_ENTER("rpl_load_gtid_slave_state"); rpl_global_gtid_slave_state.lock(); @@ -1450,8 +1449,6 @@ rpl_load_gtid_slave_state(THD *thd) DBUG_PRINT("info", ("Read slave state row: %u-%u-%lu sub_id=%lu\n", (unsigned)domain_id, (unsigned)server_id, (ulong)seq_no, (ulong)sub_id)); - if (seq_no > highest_seq_no) - highest_seq_no= seq_no; if ((rec= my_hash_search(&hash, (const uchar *)&domain_id, 0))) { @@ -1495,6 +1492,14 @@ rpl_load_gtid_slave_state(THD *thd) rpl_global_gtid_slave_state.unlock(); goto end; } + if (opt_bin_log && + mysql_bin_log.bump_seq_no_counter_if_needed(entry->gtid.domain_id, + entry->gtid.seq_no)) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + rpl_global_gtid_slave_state.unlock(); + goto end; + } } rpl_global_gtid_slave_state.loaded= true; rpl_global_gtid_slave_state.unlock(); @@ -1514,7 +1519,6 @@ end: thd->mdl_context.release_transactional_locks(); } my_hash_free(&hash); - mysql_bin_log.bump_seq_no_counter_if_needed(highest_seq_no); DBUG_RETURN(err); } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 539e90d7cb5..f08ba26fa4d 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6545,3 +6545,7 @@ ER_MASTER_GTID_POS_MISSING_DOMAIN eng "Specified value for @@gtid_slave_pos contains no value for replication domain %u. This conflicts with the binary log which contains GTID %u-%u-%llu. If MASTER_GTID_POS=CURRENT_POS is used, the binlog position will override the new value of @@gtid_slave_pos." ER_UNTIL_REQUIRES_USING_GTID eng "START SLAVE UNTIL master_gtid_pos requires that slave is using GTID" +ER_GTID_STRICT_OUT_OF_ORDER + eng "An attempt was made to binlog GTID %u-%u-%llu which would create an out-of-order sequence number with existing GTID %u-%u-%llu, and gtid strict mode is enabled." +ER_GTID_START_FROM_BINLOG_HOLE + eng "The binlog on the master is missing the GTID %u-%u-%llu requested by the slave (even though both a prior and a subsequent sequence number does exist), and GTID strict mode is enabled" diff --git a/sql/slave.cc b/sql/slave.cc index bf7e81edf71..10411f9a5a5 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1824,8 +1824,8 @@ after_set_capability: { int rc; char str_buf[256]; - String connect_state(str_buf, sizeof(str_buf), system_charset_info); - connect_state.length(0); + String query_str(str_buf, sizeof(str_buf), system_charset_info); + query_str.length(0); /* Read the master @@GLOBAL.gtid_domain_id variable. @@ -1848,9 +1848,9 @@ after_set_capability: mysql_free_result(master_res); master_res= NULL; - connect_state.append(STRING_WITH_LEN("SET @slave_connect_state='"), - system_charset_info); - if (rpl_append_gtid_state(&connect_state, + query_str.append(STRING_WITH_LEN("SET @slave_connect_state='"), + system_charset_info); + if (rpl_append_gtid_state(&query_str, mi->using_gtid == Master_info::USE_GTID_CURRENT_POS)) { @@ -1860,9 +1860,9 @@ after_set_capability: sprintf(err_buff, "%s Error: Out of memory", errmsg); goto err; } - connect_state.append(STRING_WITH_LEN("'"), system_charset_info); + query_str.append(STRING_WITH_LEN("'"), system_charset_info); - rc= mysql_real_query(mysql, connect_state.ptr(), connect_state.length()); + rc= mysql_real_query(mysql, query_str.ptr(), query_str.length()); if (rc) { err_code= mysql_errno(mysql); @@ -1883,12 +1883,45 @@ after_set_capability: } } + query_str.length(0); + if (query_str.append(STRING_WITH_LEN("SET @slave_gtid_strict_mode="), + system_charset_info) || + query_str.append_ulonglong(opt_gtid_strict_mode != false)) + { + err_code= ER_OUTOFMEMORY; + errmsg= "The slave I/O thread stops because a fatal out-of-memory " + "error is encountered when it tries to set @slave_gtid_strict_mode."; + sprintf(err_buff, "%s Error: Out of memory", errmsg); + goto err; + } + + rc= mysql_real_query(mysql, query_str.ptr(), query_str.length()); + if (rc) + { + err_code= mysql_errno(mysql); + if (is_network_error(err_code)) + { + mi->report(ERROR_LEVEL, err_code, + "Setting @slave_gtid_strict_mode failed with error: %s", + mysql_error(mysql)); + goto network_err; + } + else + { + /* Fatal error */ + errmsg= "The slave I/O thread stops because a fatal error is " + "encountered when it tries to set @slave_gtid_strict_mode."; + sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); + goto err; + } + } + if (mi->rli.until_condition == Relay_log_info::UNTIL_GTID) { - connect_state.length(0); - connect_state.append(STRING_WITH_LEN("SET @slave_until_gtid='"), - system_charset_info); - if (mi->rli.until_gtid_pos.append_to_string(&connect_state)) + query_str.length(0); + query_str.append(STRING_WITH_LEN("SET @slave_until_gtid='"), + system_charset_info); + if (mi->rli.until_gtid_pos.append_to_string(&query_str)) { err_code= ER_OUTOFMEMORY; errmsg= "The slave I/O thread stops because a fatal out-of-memory " @@ -1896,9 +1929,9 @@ after_set_capability: sprintf(err_buff, "%s Error: Out of memory", errmsg); goto err; } - connect_state.append(STRING_WITH_LEN("'"), system_charset_info); + query_str.append(STRING_WITH_LEN("'"), system_charset_info); - rc= mysql_real_query(mysql, connect_state.ptr(), connect_state.length()); + rc= mysql_real_query(mysql, query_str.ptr(), query_str.length()); if (rc) { err_code= mysql_errno(mysql); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 82f471d5ddf..5ed73bf81f3 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -614,6 +614,19 @@ get_slave_connect_state(THD *thd, String *out_str) } +static bool +get_slave_gtid_strict_mode(THD *thd) +{ + bool null_value; + + const LEX_STRING name= { C_STRING_WITH_LEN("slave_gtid_strict_mode") }; + user_var_entry *entry= + (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name.str, + name.length); + return entry && entry->val_int(&null_value) && !null_value; +} + + /* Get the value of the @slave_until_gtid user variable into the supplied String (this is the GTID position specified for START SLAVE UNTIL @@ -876,8 +889,6 @@ contains_all_slave_gtid(slave_connection_state *st, Gtid_list_log_event *glev) Give an error if the slave requests something that we do not have in our binlog. - - T */ static int @@ -1465,13 +1476,13 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, enum_gtid_skip_type *gtid_skip_group, slave_connection_state *until_gtid_state, enum_gtid_until_state *gtid_until_group, - rpl_binlog_state *until_binlog_state) + rpl_binlog_state *until_binlog_state, + bool slave_gtid_strict_mode, rpl_gtid *error_gtid) { my_off_t pos; size_t len= packet->length(); - if (event_type == GTID_LIST_EVENT && using_gtid_state && - (gtid_state->count() > 0 || until_gtid_state)) + if (event_type == GTID_LIST_EVENT && using_gtid_state && until_gtid_state) { rpl_gtid *gtid_list; uint32 list_len; @@ -1481,11 +1492,17 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, Gtid_list_log_event::peek(packet->ptr()+ev_offset, len - ev_offset, current_checksum_alg, >id_list, &list_len)) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed to read Gtid_list_log_event: corrupt binlog"; + } err= until_binlog_state->load(gtid_list, list_len); my_free(gtid_list); if (err) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed in internal GTID book-keeping: Out of memory"; + } } /* Skip GTID event groups until we reach slave position within a domain_id. */ @@ -1503,10 +1520,16 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, current_checksum_alg, &event_gtid.domain_id, &event_gtid.server_id, &event_gtid.seq_no, &flags2)) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed to read Gtid_log_event: corrupt binlog"; + } - if (until_binlog_state->update(&event_gtid)) + if (until_binlog_state->update(&event_gtid, false)) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed in internal GTID book-keeping: Out of memory"; + } if (gtid_state->count() > 0) { @@ -1518,13 +1541,30 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, event_gtid.seq_no <= gtid->seq_no) *gtid_skip_group = (flags2 & Gtid_log_event::FL_STANDALONE ? GTID_SKIP_STANDALONE : GTID_SKIP_TRANSACTION); - /* - Delete this entry if we have reached slave start position (so we will - not skip subsequent events and won't have to look them up and check). - */ if (event_gtid.server_id == gtid->server_id && event_gtid.seq_no >= gtid->seq_no) + { + /* + In strict mode, it is an error if the slave requests to start in + a "hole" in the master's binlog: a GTID that does not exist, even + though both the prior and subsequent seq_no exists for same + domain_id and server_id. + */ + if (slave_gtid_strict_mode && event_gtid.seq_no > gtid->seq_no) + { + my_errno= ER_GTID_START_FROM_BINLOG_HOLE; + *error_gtid= *gtid; + return "The binlog on the master is missing the GTID requested " + "by the slave (even though both a prior and a subsequent " + "sequence number does exist), and GTID strict mode is enabled."; + } + /* + Delete this entry if we have reached slave start position (so we + will not skip subsequent events and won't have to look them up + and check). + */ gtid_state->remove(gtid); + } } } @@ -1626,7 +1666,10 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, a no-operation on the slave. */ if (Query_log_event::dummy_event(packet, ev_offset, current_checksum_alg)) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed to replace row annotate event with dummy: too small event."; + } } } @@ -1645,8 +1688,11 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, ev_offset, current_checksum_alg); if (err) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed to replace GTID event with backwards-compatible event: " "currupt event."; + } if (!need_dummy) return NULL; } @@ -1673,8 +1719,11 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, binlog positions. */ if (Query_log_event::dummy_event(packet, ev_offset, current_checksum_alg)) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; return "Failed to replace binlog checkpoint or gtid list event with " "dummy: too small event."; + } } } @@ -1698,20 +1747,32 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, pos= my_b_tell(log); if (RUN_HOOK(binlog_transmit, before_send_event, (thd, flags, packet, log_file_name, pos))) + { + my_errno= ER_UNKNOWN_ERROR; return "run 'before_send_event' hook failed"; + } if (my_net_write(net, (uchar*) packet->ptr(), len)) + { + my_errno= ER_UNKNOWN_ERROR; return "Failed on my_net_write()"; + } DBUG_PRINT("info", ("log event code %d", (*packet)[LOG_EVENT_OFFSET+1] )); if (event_type == LOAD_EVENT) { if (send_file(thd)) + { + my_errno= ER_UNKNOWN_ERROR; return "failed in send_file()"; + } } if (RUN_HOOK(binlog_transmit, after_send_event, (thd, flags, packet))) + { + my_errno= ER_UNKNOWN_ERROR; return "Failed to run hook 'after_send_event'"; + } return NULL; /* Success */ } @@ -1747,6 +1808,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, enum_gtid_skip_type gtid_skip_group= GTID_SKIP_NOT; enum_gtid_until_state gtid_until_group= GTID_UNTIL_NOT_DONE; rpl_binlog_state until_binlog_state; + bool slave_gtid_strict_mode; uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; int old_max_allowed_packet= thd->variables.max_allowed_packet; @@ -1778,9 +1840,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, connect_gtid_state.length(0); using_gtid_state= get_slave_connect_state(thd, &connect_gtid_state); DBUG_EXECUTE_IF("simulate_non_gtid_aware_master", using_gtid_state= false;); - if (using_gtid_state && - get_slave_until_gtid(thd, &slave_until_gtid_str)) - until_gtid_state= &until_gtid_state_obj; + if (using_gtid_state) + { + slave_gtid_strict_mode= get_slave_gtid_strict_mode(thd); + if(get_slave_until_gtid(thd, &slave_until_gtid_str)) + until_gtid_state= &until_gtid_state_obj; + } /* We want to corrupt the first event, in Log_event::read_log_event(). @@ -2134,10 +2199,10 @@ impossible position"; current_checksum_alg, using_gtid_state, >id_state, >id_skip_group, until_gtid_state, >id_until_group, - &until_binlog_state))) + &until_binlog_state, + slave_gtid_strict_mode, &error_gtid))) { errmsg= tmp_msg; - my_errno= ER_UNKNOWN_ERROR; goto err; } if (until_gtid_state && @@ -2315,10 +2380,10 @@ impossible position"; current_checksum_alg, using_gtid_state, >id_state, >id_skip_group, until_gtid_state, - >id_until_group, &until_binlog_state))) + >id_until_group, &until_binlog_state, + slave_gtid_strict_mode, &error_gtid))) { errmsg= tmp_msg; - my_errno= ER_UNKNOWN_ERROR; goto err; } if ( @@ -2430,6 +2495,17 @@ err: /* Use this error code so slave will know not to try reconnect. */ my_errno = ER_MASTER_FATAL_ERROR_READING_BINLOG; } + else if (my_errno == ER_GTID_START_FROM_BINLOG_HOLE) + { + my_snprintf(error_text, sizeof(error_text), + "The binlog on the master is missing the GTID %u-%u-%llu " + "requested by the slave (even though both a prior and a " + "subsequent sequence number does exist), and GTID strict mode " + "is enabled", + error_gtid.domain_id, error_gtid.server_id, error_gtid.seq_no); + /* Use this error code so slave will know not to try reconnect. */ + my_errno = ER_MASTER_FATAL_ERROR_READING_BINLOG; + } else if (my_errno == ER_CANNOT_LOAD_SLAVE_GTID_STATE) { my_snprintf(error_text, sizeof(error_text), @@ -3721,8 +3797,6 @@ rpl_append_gtid_state(String *dest, bool use_binlog) bool rpl_gtid_pos_check(THD *thd, char *str, size_t len) { - /* ToDo: Use gtid_strict_mode sysvar, when implemented. */ - static const bool gtid_strict_mode= false; slave_connection_state tmp_slave_state; bool gave_conflict_warning= false, gave_missing_warning= false; @@ -3759,7 +3833,7 @@ rpl_gtid_pos_check(THD *thd, char *str, size_t len) continue; if (!(slave_gtid= tmp_slave_state.find(binlog_gtid->domain_id))) { - if (gtid_strict_mode) + if (opt_gtid_strict_mode) { my_error(ER_MASTER_GTID_POS_MISSING_DOMAIN, MYF(0), binlog_gtid->domain_id, binlog_gtid->domain_id, @@ -3778,7 +3852,7 @@ rpl_gtid_pos_check(THD *thd, char *str, size_t len) } else if (slave_gtid->seq_no < binlog_gtid->seq_no) { - if (gtid_strict_mode) + if (opt_gtid_strict_mode) { my_error(ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG, MYF(0), slave_gtid->domain_id, slave_gtid->server_id, diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 9edbe789196..f520c43e10c 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1215,6 +1215,26 @@ static Sys_var_uint Sys_gtid_domain_id( BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super)); + +static bool check_gtid_seq_no(sys_var *self, THD *thd, set_var *var) +{ + uint32 domain_id, server_id; + uint64_t seq_no; + + if (check_has_super(self, thd, var)) + return true; + domain_id= thd->variables.gtid_domain_id; + server_id= thd->variables.server_id; + seq_no= (uint64)var->value->val_uint(); + DBUG_EXECUTE_IF("ignore_set_gtid_seq_no_check", return 0;); + if (opt_gtid_strict_mode && opt_bin_log && + mysql_bin_log.check_strict_gtid_sequence(domain_id, server_id, seq_no)) + return true; + + return false; +} + + static Sys_var_ulonglong Sys_gtid_seq_no( "gtid_seq_no", "Internal server usage, for replication with global transaction id. " @@ -1224,7 +1244,7 @@ static Sys_var_ulonglong Sys_gtid_seq_no( SESSION_ONLY(gtid_seq_no), NO_CMD_LINE, VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(check_has_super)); + ON_CHECK(check_gtid_seq_no)); #ifdef HAVE_REPLICATION @@ -1364,6 +1384,15 @@ static Sys_var_gtid_slave_pos Sys_gtid_slave_pos( "The list of global transaction IDs that were last replicated on the " "server, one for each replication domain.", GLOBAL_VAR(opt_gtid_slave_pos_dummy), NO_CMD_LINE); + + +static Sys_var_mybool Sys_gtid_strict_mode( + "gtid_strict_mode", + "Enforce strict seq_no ordering of events in the binary log. Slave " + "stops with an error if it encounters an event that would cause it to " + "generate an out-of-order binlog if executed.", + GLOBAL_VAR(opt_gtid_strict_mode), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); #endif