1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

BUG#31168: @@hostname does not replicate

Problem: in mixed and statement mode, a query that refers to a
system variable will use the slave's value when replayed on
slave. So if the value of a system variable is inserted into a
table, the slave will differ from the master.
Fix: mark statements that refer to a system variable as "unsafe",
meaning they will be replicated by row in mixed mode and produce a warning
in statement mode. There are some exceptions: some variables are actually
replicated. Those should *not* be marked as unsafe.
BUG#34732: mysqlbinlog does not print default values for auto_increment variables
Problem: mysqlbinlog does not print default values for some variables,
including auto_increment_increment and others. So if a client executing
the output of mysqlbinlog has different default values, replication will
be wrong.
Fix: Always print default values for all variables that are replicated.
I need to fix the two bugs at the same time, because the test cases would
fail if I only fixed one of them.


include/m_ctype.h:
  Added definition of ILLEGAL_CHARSET_INFO_NUMBER. We just need a symbol
  for a number that will never be used by any charset. ~0U should be safe
  since charset numbers are sequential, starting from 0.
mysql-test/include/commit.inc:
  Upated test to avoid making statements unsafe.
mysql-test/r/commit_1innodb.result:
  Updated test needs updated result file.
mysql-test/r/mysqlbinlog.result:
  Updated result file.
mysql-test/r/mysqlbinlog2.result:
  Updated result file.
mysql-test/r/user_var-binlog.result:
  Updated result file.
mysql-test/suite/binlog/r/binlog_base64_flag.result:
  Updated result file.
mysql-test/suite/binlog/r/binlog_stm_ctype_ucs.result:
  Updated result file.
mysql-test/suite/binlog/r/binlog_unsafe.result:
  Modified test file needs modified result file.
mysql-test/suite/binlog/t/binlog_base64_flag.test:
  Need to filter out pseudo_thread_id from result since it is
  nondeterministic.
mysql-test/suite/binlog/t/binlog_unsafe.test:
  Add tests that using variables is unsafe. The 'CREATE VIEW' tests didn't
  make sense, so I removed them. SHOW WARNINGS is not necessary either,
  because we get warnings for each statement in the result file.
mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result:
  Updated result file.
mysql-test/suite/rpl/r/rpl_skip_error.result:
  Updated result file.
mysql-test/suite/rpl/t/rpl_skip_error.test:
  The test used @@server_id, which is not safe to replicate, so it would
  have given a warning. The way it used @@server_id was hackish (issue a
  query on master that removes rows only on master), so I replaced it by a
  more robust way to do the same thing (connect to slave and insert the
  rows only there).
  Also clarified what the test case does.
mysql-test/t/mysqlbinlog2.test:
  Use --short-form instead of manually filtering out nondeterministic stuff
  from mysqlbinlog (because we added the nondeterministic @@pseudo_thread_id
  to the output).
sql/item_func.cc:
  Added method of Item_func_get_system_var that indicates whether the given
  system variable will be written to the binlog or not.
sql/item_func.h:
  Added method of Item_func_get_system_var that indicates whether the given
  system variable will be written to the binlog or not.
sql/log_event.cc:
   - auto_increment_offset was not written to the binlog if
  auto_increment_increment=1
   - mysqlbinlog did not output default values for some variables
  (BUG#34732). In st_print_event_info, we remember for each variable whether
  it has been printed or not. This is achieved in different ways for
  different variables:
      - For auto_increment_*, lc_time_names, charset_database_number,
        we set the default values in st_print_event_info to something
        illegal, so that it will look like they have changed the first time
        they are seen.
      - For charset, sql_mode, pseudo_thread_id, we add a flag to
        st_print_event_info which indicates whether the variable has been
        printed.
      - Since pseudo_thread_id is now printed more often, and its value is
        not guaranteed to be constant across different runs of the same
        test script, I replaced it by a constant if --short-form is used.
   - Moved st_print_event_info constructor from log_event.h to log_event.cc,
  since it now depends on ILLEGAL_CHARSET_NUMBER, which is defined in
  m_ctype.h, which is better to include from a .cc file than from a header
  file.
sql/log_event.h:
  Added fields to st_print_event_info that indicate whether some of the
  variables have been written or not. Since the initialization of
  charset_database_number now depends on ILLEGAL_CHARSET_INFO_NUMBER, which
  is defined in a header file, which we'd better not include from this
  header file -- I moved the constructor from here to log_event.cc.
sql/set_var.cc:
  System variables now have a flag binlog_status, which indicates if they
  are written to the binlog. If nothing is specified, all variables are
  marked as not written to the binlog (NOT_IN_BINLOG) when created. In this
  file, the variables that are written to the binlog are marked with
  SESSION_VARIABLE_IN_BINLOG.
sql/set_var.h:
  Added flag binlog_status to class sys_var. Added a getter and a
  constructor parameter that sets it.
  Since I had to change sys_var_thd_enum constructor anyways, I simplified
  it to use default values of arguments instead of three copies of the
  constructor.
sql/sql_yacc.yy:
  Mark statements that refer to a system variable as "unsafe",
  meaning they will be replicated by row in mixed mode. Added comment to
  explain strange piece of code just above.
mysql-test/include/diff_tables.inc:
  New auxiliary test file that tests whether two tables (possibly one on
  master and one on slave) differ.
mysql-test/suite/rpl/r/rpl_variables.result:
  New test case needs new result file.
mysql-test/suite/rpl/r/rpl_variables_stm.result:
  New test file needs new result file.
mysql-test/suite/rpl/t/rpl_variables.test:
  Test that INSERT of @@variables is replicated correctly (by switching to
  row-based mode).
mysql-test/suite/rpl/t/rpl_variables_stm.test:
  Test that replication of @@variables which are replicated explicitly works
  as expected in statement mode (without giving warnings).
This commit is contained in:
unknown
2008-03-07 13:59:36 +01:00
parent f613588c2b
commit 875ad6d8b8
27 changed files with 3576 additions and 265 deletions

View File

@ -1,14 +1,182 @@
SET BINLOG_FORMAT=STATEMENT;
CREATE TABLE t1 (a CHAR(40));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE t3 (b INT AUTO_INCREMENT PRIMARY KEY);
CREATE VIEW v1(a,b) AS SELECT a,b FROM t2,t3;
INSERT INTO t1 SELECT UUID();
==== Setup tables ====
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a CHAR(40));
CREATE TABLE t3 (a INT AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE trigger_table (a CHAR(7));
CREATE TABLE trigger_table2 (a INT);
==== Non-deterministic statements ====
INSERT DELAYED INTO t1 VALUES (5);
==== Some variables that *should* be unsafe ====
---- Insert directly ----
INSERT INTO t1 VALUES (@@global.sync_binlog);
Warnings:
Warning 1592 Statement is not safe to log in statement format.
SHOW WARNINGS;
Level Warning
Code 1592
Message Statement is not safe to log in statement format.
DROP TABLE t1,t2,t3;
INSERT INTO t1 VALUES (@@session.insert_id);
Warnings:
Warning 1592 Statement is not safe to log in statement format.
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
Warnings:
Warning 1592 Statement is not safe to log in statement format.
INSERT INTO t2 SELECT UUID();
Warnings:
Warning 1592 Statement is not safe to log in statement format.
INSERT INTO t2 VALUES (@@global.init_slave);
Warnings:
Warning 1592 Statement is not safe to log in statement format.
INSERT INTO t2 VALUES (@@hostname);
Warnings:
Warning 1592 Statement is not safe to log in statement format.
---- Insert from stored procedure ----
CREATE PROCEDURE proc()
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
END|
CALL proc();
Warnings:
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
---- Insert from stored function ----
CREATE FUNCTION func()
RETURNS INT
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
RETURN 0;
END|
SELECT func();
func()
0
Warnings:
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
---- Insert from trigger ----
CREATE TRIGGER trig
BEFORE INSERT ON trigger_table
FOR EACH ROW
BEGIN
INSERT INTO t1 VALUES (@@global.sync_binlog);
INSERT INTO t1 VALUES (@@session.insert_id);
INSERT INTO t1 VALUES (@@global.auto_increment_increment);
INSERT INTO t2 SELECT UUID();
INSERT INTO t2 VALUES (@@global.init_slave);
INSERT INTO t2 VALUES (@@hostname);
END|
INSERT INTO trigger_table VALUES ('bye.');
Warnings:
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
---- Insert from prepared statement ----
PREPARE p1 FROM 'INSERT INTO t1 VALUES (@@global.sync_binlog)';
PREPARE p2 FROM 'INSERT INTO t1 VALUES (@@session.insert_id)';
PREPARE p3 FROM 'INSERT INTO t1 VALUES (@@global.auto_increment_increment)';
PREPARE p4 FROM 'INSERT INTO t2 SELECT UUID()';
PREPARE p5 FROM 'INSERT INTO t2 VALUES (@@global.init_slave)';
PREPARE p6 FROM 'INSERT INTO t2 VALUES (@@hostname)';
EXECUTE p1;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
EXECUTE p2;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
EXECUTE p3;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
EXECUTE p4;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
EXECUTE p5;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
EXECUTE p6;
Warnings:
Warning 1592 Statement is not safe to log in statement format.
---- Insert from nested call of triggers / functions / procedures ----
CREATE PROCEDURE proc1()
INSERT INTO trigger_table VALUES ('ha!')|
CREATE FUNCTION func2()
RETURNS INT
BEGIN
CALL proc1();
RETURN 0;
END|
CREATE TRIGGER trig3
BEFORE INSERT ON trigger_table2
FOR EACH ROW
BEGIN
DECLARE tmp INT;
SELECT func2() INTO tmp;
END|
CREATE PROCEDURE proc4()
INSERT INTO trigger_table2 VALUES (1)|
CREATE FUNCTION func5()
RETURNS INT
BEGIN
CALL proc4;
RETURN 0;
END|
PREPARE prep6 FROM 'SELECT func5()'|
EXECUTE prep6;
func5()
0
Warnings:
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
Warning 1592 Statement is not safe to log in statement format.
==== Variables that should *not* be unsafe ====
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.foreign_key_checks);
INSERT INTO t1 VALUES (@@session.sql_auto_is_null);
INSERT INTO t1 VALUES (@@session.unique_checks);
INSERT INTO t2 VALUES (@@session.sql_mode);
INSERT INTO t1 VALUES (@@session.auto_increment_increment);
INSERT INTO t1 VALUES (@@session.auto_increment_offset);
INSERT INTO t2 VALUES (@@session.character_set_client);
INSERT INTO t2 VALUES (@@session.collation_connection);
INSERT INTO t2 VALUES (@@session.collation_server);
INSERT INTO t2 VALUES (@@session.time_zone);
INSERT INTO t2 VALUES (@@session.lc_time_names);
INSERT INTO t2 VALUES (@@session.collation_database);
INSERT INTO t2 VALUES (@@session.timestamp);
INSERT INTO t2 VALUES (@@session.last_insert_id);
SET @my_var= 4711;
INSERT INTO t1 VALUES (@my_var);
SET insert_id=12;
INSERT INTO t3 VALUES (NULL);
==== Clean up ====
DROP PROCEDURE proc;
DROP FUNCTION func;
DROP TRIGGER trig;
DROP PROCEDURE proc1;
DROP FUNCTION func2;
DROP TRIGGER trig3;
DROP PROCEDURE proc4;
DROP FUNCTION func5;
DROP PREPARE prep6;
DROP TABLE t1, t2, t3, trigger_table, trigger_table2;
DROP VIEW v1;