diff options
-rw-r--r-- | mysql-test/main/mysqlbinlog.result | 16 | ||||
-rw-r--r-- | mysql-test/std_data/mdev29078-mysql-bin.000001 | bin | 0 -> 920 bytes | |||
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_base64_flag.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_old_master_29078.result | 92 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_old_master_29078.test | 49 | ||||
-rw-r--r-- | sql/log_event.cc | 23 | ||||
-rw-r--r-- | sql/log_event.h | 34 | ||||
-rw-r--r-- | sql/log_event_client.cc | 10 | ||||
-rw-r--r-- | sql/log_event_server.cc | 4 |
10 files changed, 191 insertions, 40 deletions
diff --git a/mysql-test/main/mysqlbinlog.result b/mysql-test/main/mysqlbinlog.result index 0822e126a88..8e6411a5fab 100644 --- a/mysql-test/main/mysqlbinlog.result +++ b/mysql-test/main/mysqlbinlog.result @@ -724,7 +724,7 @@ ROLLBACK/*!*/; use `test`/*!*/; SET TIMESTAMP=1253783037/*!*/; SET @@session.pseudo_thread_id=999999999/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -778,7 +778,7 @@ DELIMITER /*!*/; ROLLBACK/*!*/; SET TIMESTAMP=1253783037/*!*/; SET @@session.pseudo_thread_id=999999999/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -813,7 +813,7 @@ ROLLBACK /* added by mysqlbinlog */; DELIMITER /*!*/; SET TIMESTAMP=1266652094/*!*/; SET @@session.pseudo_thread_id=999999999/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -855,7 +855,7 @@ ROLLBACK /* added by mysqlbinlog */; DELIMITER /*!*/; SET TIMESTAMP=1266652094/*!*/; SET @@session.pseudo_thread_id=999999999/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -973,7 +973,7 @@ AAAAAAAAAAAAAAAAAAAgrgJSFzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC # Event: Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1375907364/*!*/; SET @@session.pseudo_thread_id=1/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -1056,7 +1056,7 @@ AAAAAAAAAAAAAAAAAAA/rQJSGzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC # Event: Query thread_id=1 exec_time=1 error_code=0 SET TIMESTAMP=1375907141/*!*/; SET @@session.pseudo_thread_id=1/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -1139,7 +1139,7 @@ AAAAAAAAAAAAAAAAAAAnrAJSHzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC # Event: Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1375906879/*!*/; SET @@session.pseudo_thread_id=1/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; @@ -1222,7 +1222,7 @@ AAAAAAAAAAAAAAAAAABbsAJSEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC # Event: Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1375907933/*!*/; SET @@session.pseudo_thread_id=1/*!*/; -SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; diff --git a/mysql-test/std_data/mdev29078-mysql-bin.000001 b/mysql-test/std_data/mdev29078-mysql-bin.000001 Binary files differnew file mode 100644 index 00000000000..efcbb0c9832 --- /dev/null +++ b/mysql-test/std_data/mdev29078-mysql-bin.000001 diff --git a/mysql-test/suite/binlog/r/binlog_base64_flag.result b/mysql-test/suite/binlog/r/binlog_base64_flag.result index 1a417668338..a79ae45981e 100644 --- a/mysql-test/suite/binlog/r/binlog_base64_flag.result +++ b/mysql-test/suite/binlog/r/binlog_base64_flag.result @@ -59,7 +59,7 @@ ROLLBACK/*!*/; <#> use `test`/*!*/; SET TIMESTAMP=1196959712/*!*/; -<#>SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=0/*!*/; +<#>SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C latin1 *//*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_old_master_29078.result b/mysql-test/suite/rpl/r/rpl_old_master_29078.result new file mode 100644 index 00000000000..072baa90a87 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_old_master_29078.result @@ -0,0 +1,92 @@ +# +# MDEV-29078 For old binary logs explicit_defaults_for_timestamp presumed to be OFF, server value ignored +# +include/master-slave.inc +[connection master] +connection slave; +include/stop_slave.inc +connection master; +flush binary logs; +create table t2 (a timestamp); +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +ROLLBACK/*!*/; +use `test`/*!*/; +SET TIMESTAMP=1658586280/*!*/; +SET @@session.pseudo_thread_id=999999999/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; +SET @@session.sql_mode=1411383296/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C utf8 *//*!*/; +SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +create table t1 (f1 timestamp, f2 timestamp) +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=1658586288/*!*/; +insert t1 values (NULL, NULL) +/*!*/; +SET TIMESTAMP=1658586288/*!*/; +COMMIT +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=1658586335/*!*/; +insert t1 () values () +/*!*/; +SET TIMESTAMP=1658586335/*!*/; +COMMIT +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +connection slave; +set global explicit_defaults_for_timestamp=1; +reset slave; +include/start_slave.inc +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` timestamp NULL DEFAULT NULL, + `f2` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` timestamp NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +set time_zone='+2:00'; +select * from t1; +f1 f2 +NULL NULL +NULL NULL +drop table t1; +include/stop_slave.inc +set global explicit_defaults_for_timestamp=0; +reset slave; +include/start_slave.inc +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `f2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from t1; +f1 f2 +2022-07-23 16:24:48 2022-07-23 16:24:48 +2022-07-23 16:25:35 0000-00-00 00:00:00 +drop table t1; +connection master; +drop table t2; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt b/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt new file mode 100644 index 00000000000..3efc6fb8e29 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_old_master_29078-master.opt @@ -0,0 +1 @@ +--version=10.5.99 diff --git a/mysql-test/suite/rpl/t/rpl_old_master_29078.test b/mysql-test/suite/rpl/t/rpl_old_master_29078.test new file mode 100644 index 00000000000..b19fd6466e5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_old_master_29078.test @@ -0,0 +1,49 @@ +--echo # +--echo # MDEV-29078 For old binary logs explicit_defaults_for_timestamp presumed to be OFF, server value ignored +--echo # + +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +flush binary logs; +create table t2 (a timestamp); + +--save_master_pos + +--remove_file $datadir/master-bin.000001 +--copy_file $MYSQL_TEST_DIR/std_data/mdev29078-mysql-bin.000001 $datadir/master-bin.000001 + +--exec $MYSQL_BINLOG --short-form $datadir/master-bin.000001 + +--connection slave + +set global explicit_defaults_for_timestamp=1; +reset slave; +--source include/start_slave.inc +--sync_with_master +show create table t1; +show create table t2; +set time_zone='+2:00'; +select * from t1; +drop table t1; +--source include/stop_slave.inc + +set global explicit_defaults_for_timestamp=0; +reset slave; +--source include/start_slave.inc +--sync_with_master +show create table t1; +show create table t2; +select * from t1; +drop table t1; + +--connection master +drop table t2; + +--source include/rpl_end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index b35ed1884cb..092ddfb8010 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2195,6 +2195,7 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) break; } calc_server_version_split(); + deduct_options_written_to_bin_log(); checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; reset_crypto(); } @@ -2255,6 +2256,7 @@ Format_description_log_event(const char* buf, { checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; } + deduct_options_written_to_bin_log(); reset_crypto(); DBUG_VOID_RETURN; @@ -2331,6 +2333,27 @@ void Format_description_log_event::calc_server_version_split() } +void Format_description_log_event::deduct_options_written_to_bin_log() +{ + options_written_to_bin_log= OPTION_AUTO_IS_NULL | OPTION_NOT_AUTOCOMMIT | + OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS; + if (!server_version_split.version_is_valid() || + server_version_split.kind == master_version_split::KIND_MYSQL || + server_version_split < Version(10,5,2)) + return; + options_written_to_bin_log|= OPTION_IF_EXISTS; + if (server_version_split[0] == 10) + { + const static char v[10]={99,99,99,99,99,17,9,5,4,2}; + if (server_version_split[1] < 10 && + server_version_split[2] < v[server_version_split[1]]) + return; + } + options_written_to_bin_log|= OPTION_EXPLICIT_DEF_TIMESTAMP; + + DBUG_ASSERT(options_written_to_bin_log == OPTIONS_WRITTEN_TO_BIN_LOG); +} + /** @return TRUE is the event's version is earlier than one that introduced the replication event checksum. FALSE otherwise. diff --git a/sql/log_event.h b/sql/log_event.h index c395aa3d0c7..4c2ee3e484e 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -508,33 +508,16 @@ class String; be written to the binlog. OPTIONS_WRITTEN_TO_BIN_LOG could be written into the Format_description_log_event, so that if later we don't want to replicate a variable we did replicate, or the - contrary, it's doable. But it should not be too hard to decide once - for all of what we replicate and what we don't, among the fixed 32 - bits of thd->options. - - I (Guilhem) have read through every option's usage, and it looks - like OPTION_AUTO_IS_NULL and OPTION_NO_FOREIGN_KEYS are the only - ones which alter how the query modifies the table. It's good to - replicate OPTION_RELAXED_UNIQUE_CHECKS too because otherwise, the - slave may insert data slower than the master, in InnoDB. - OPTION_BIG_SELECTS is not needed (the slave thread runs with - max_join_size=HA_POS_ERROR) and OPTION_BIG_TABLES is not needed - either, as the manual says (because a too big in-memory temp table - is automatically written to disk). + contrary, it's doable. But it should not be too hard to deduct + the value of OPTIONS_WRITTEN_TO_BIN_LOG from the master's version. + + This is done in deduct_options_written_to_bin_log(). + You *must* update it, when changing the definition below. */ #define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_EXPLICIT_DEF_TIMESTAMP |\ OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \ OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT | OPTION_IF_EXISTS) -/* Shouldn't be defined before */ -#define EXPECTED_OPTIONS \ - ((1ULL << 14) | (1ULL << 26) | (1ULL << 27) | (1ULL << 19) | (1ULL << 24) | (1ULL << 28)) - -#if OPTIONS_WRITTEN_TO_BIN_LOG != EXPECTED_OPTIONS -#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values! -#endif -#undef EXPECTED_OPTIONS /* You shouldn't use this one */ - #define CHECKSUM_CRC32_SIGNATURE_LEN 4 /** defined statically while there is just one alg implemented @@ -1832,10 +1815,7 @@ protected: <td>The flags in @c thd->options, binary AND-ed with @c OPTIONS_WRITTEN_TO_BIN_LOG. The @c thd->options bitfield contains options for "SELECT". @c OPTIONS_WRITTEN identifies those options - that need to be written to the binlog (not all do). Specifically, - @c OPTIONS_WRITTEN_TO_BIN_LOG equals (@c OPTION_AUTO_IS_NULL | @c - OPTION_NO_FOREIGN_KEY_CHECKS | @c OPTION_RELAXED_UNIQUE_CHECKS | - @c OPTION_NOT_AUTOCOMMIT), or 0x0c084000 in hex. + that need to be written to the binlog (not all do). These flags correspond to the SQL variables SQL_AUTO_IS_NULL, FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, and AUTOCOMMIT, documented in @@ -2826,6 +2806,7 @@ public: }; master_version_split server_version_split; const uint8 *event_type_permutation; + uint32 options_written_to_bin_log; Format_description_log_event(uint8 binlog_ver, const char* server_ver=0); Format_description_log_event(const char* buf, uint event_len, @@ -2873,6 +2854,7 @@ public: } void calc_server_version_split(); + void deduct_options_written_to_bin_log(); static bool is_version_before_checksum(const master_version_split *version_split); protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index 0e42744e7b8..8f3b97d9682 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -1885,6 +1885,7 @@ bool Query_log_event::print_query_header(IO_CACHE* file, if (unlikely(tmp)) /* some bits have changed */ { bool need_comma= 0; + ulonglong mask= glob_description_event->options_written_to_bin_log; if (my_b_write_string(file, "SET ") || print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2, "@@session.foreign_key_checks", &need_comma)|| @@ -1896,10 +1897,11 @@ bool Query_log_event::print_query_header(IO_CACHE* file, "@@session.autocommit", &need_comma) || print_set_option(file, tmp, OPTION_NO_CHECK_CONSTRAINT_CHECKS, ~flags2, "@@session.check_constraint_checks", &need_comma) || - print_set_option(file, tmp, OPTION_IF_EXISTS, flags2, - "@@session.sql_if_exists", &need_comma)|| - print_set_option(file, tmp, OPTION_EXPLICIT_DEF_TIMESTAMP, flags2, - "@@session.explicit_defaults_for_timestamp", &need_comma)|| + print_set_option(file, tmp, mask & OPTION_IF_EXISTS, flags2, + "@@session.sql_if_exists", &need_comma) || + print_set_option(file, tmp, mask & OPTION_EXPLICIT_DEF_TIMESTAMP, flags2, + "@@session.explicit_defaults_for_timestamp", + &need_comma) || my_b_printf(file,"%s\n", print_event_info->delimiter)) goto err; print_event_info->flags2= flags2; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 72702daab36..c16ca88fea0 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -1718,7 +1718,9 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, OPTIONS_WRITTEN_TO_BIN_LOG must take their value from flags2. */ - thd->variables.option_bits= flags2|(thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG); + ulonglong mask= rli->relay_log.description_event_for_exec->options_written_to_bin_log; + thd->variables.option_bits= (flags2 & mask) | + (thd->variables.option_bits & ~mask); } /* else, we are in a 3.23/4.0 binlog; we previously received a |