mariadb/mysql-test/t/rpl_switch_stm_row_mixed.test

567 lines
17 KiB
Text
Raw Normal View History

Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
#
# rpl_switch_stm_row_mixed tests covers
#
# - switching explicitly between STATEMENT, ROW, and MIXED binlog format
# showing when it is possible and when not.
# - switching from MIXED to RBR implicitly listing all use cases,
# e.g a query invokes UUID(), thereafter to serve as the definition
# of MIXED binlog format
# - correctness of execution
Bug#22067 rpl_rbr_to_sbr and some other fail if NDB is default storage A query SET @@GLOBAL.binlog_format = ... returns an error when NDB is the default storage. This fails some tests invoking the set binlog_format explicitly. because the var turns to be read-only. In the following are files and method to fix if needed. t/ ndb_binlog_basic2.test # here the failure is benign rpl_rbr_to_sbr.test # does not check any ndb features => . # => not_ndb_default is enough rpl_row_basic_8partition.test # set binlog_format can be replaced rpl_switch_stm_row_mixed.test # does not check any ndb features => . # => not_ndb_default is enough two more invoking invoke extra/rpl_truncate_helper.test rpl_truncate_2myisam # to be fixed with not_ndb_default rpl_truncate_3innodb # same as above . # because there is a dedicated to ndb . . # rpl_truncate_7ndb* suit. Adapting/testing a new implement --source include/safe_set_to_maybe_ro_var.inc to avoid abort due to the error using binlog_format as application. BitKeeper/etc/ignore: Added mysql-test/t/rpl_truncate_4ndb.test to the ignore list mysql-test/r/rpl_row_basic_8partition.result: new results mysql-test/t/rpl_rbr_to_sbr.test: # does not check any ndb features => not_ndb_default is enough mysql-test/t/rpl_row_basic_8partition.test: set binlog_format can be read-only because of e.g default storage ndb. adapting/testing a new implement --source include/safe_set_to_maybe_ro_var.inc to avoid abort due to the error. Note, that it this particular test we could simply remove SET binlog_format because there is have_binlog_format_row require, as the test is about RBR. Futhermore utilizing safe_set_to_maybe_ro_var is redundat as well as long as we keep non_ndb_default guard. The latter is introduced because of ndb partitioning per-key limitation #19259: rpl_ndb_dd_partitions fails on solaris. The page is updated to refer to this test's. mysql-test/t/rpl_switch_stm_row_mixed.test: excluding ndb option, no ndb features mysql-test/t/rpl_truncate_2myisam.test: ndb checks truncate separately mysql-test/t/rpl_truncate_3innodb.test: ndb checks truncate separately mysql-test/include/safe_set_to_maybe_ro_var.inc: pseudo-macro to make read-only global/session vars "settable" in sense that SET var= val won't produce any error nor aborts testing.
2006-09-15 16:25:13 +02:00
-- source include/not_ndb_default.inc
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
-- source include/master-slave.inc
connection master;
--disable_warnings
drop database if exists mysqltest1;
create database mysqltest1;
--enable_warnings
use mysqltest1;
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
# play with switching
set session binlog_format=mixed;
show session variables like "binlog_format%";
set session binlog_format=statement;
show session variables like "binlog_format%";
set session binlog_format=row;
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
show session variables like "binlog_format%";
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
set global binlog_format=DEFAULT;
show global variables like "binlog_format%";
set global binlog_format=MIXED;
show global variables like "binlog_format%";
set global binlog_format=STATEMENT;
show global variables like "binlog_format%";
set global binlog_format=ROW;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
show global variables like "binlog_format%";
show session variables like "binlog_format%";
select @@global.binlog_format, @@session.binlog_format;
CREATE TABLE t1 (a varchar(100));
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
set @string="emergency_1_";
insert into t1 values("work_2_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat(UUID(),"work_3_"));
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat("for_4_",UUID()));
insert into t1 select "yesterday_5_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
# verify that temp tables prevent a switch to SBR
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
create temporary table tmp(a char(100));
insert into tmp values("see_6_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
set binlog_format=statement;
insert into t1 select * from tmp;
drop temporary table tmp;
# Now we go to SBR
set binlog_format=statement;
show global variables like "binlog_format%";
show session variables like "binlog_format%";
select @@global.binlog_format, @@session.binlog_format;
set global binlog_format=statement;
show global variables like "binlog_format%";
show session variables like "binlog_format%";
select @@global.binlog_format, @@session.binlog_format;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
set @string="emergency_7_";
insert into t1 values("work_8_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("work_9_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("for_10_");
insert into t1 select "yesterday_11_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
# test statement (is not default after wl#3368)
set binlog_format=statement;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
select @@global.binlog_format, @@session.binlog_format;
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
set global binlog_format=statement;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
select @@global.binlog_format, @@session.binlog_format;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
set @string="emergency_12_";
insert into t1 values("work_13_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("work_14_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("for_15_");
insert into t1 select "yesterday_16_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
# and now the mixed mode
set global binlog_format=mixed;
select @@global.binlog_format, @@session.binlog_format;
Bug #16567 binlog_format option does not show when doing ./mysqd --help --verbose Implementing this feature connected to wl#3368 mixed binlog_format default. Supplied by my.cnf or explicitly in command line option gets be displayed. When not supplied `(No default value)' is displayed, even though --log-bin might be supplied. The option is different object from @@global.binlog_format variable. The default `mixed' for the latter is dependant on presence of `--log-bin' option, otherwise the value of the var is set to NULL (undefined): var := opt | MIXED when binlog-in-use var := NULL otherwise (no binlog, no format) Comments on NDB and mixed format updated, also dependency the option on --log-bin aka binlog-in-use is worded. Making t/rpl_switch_stm_row_mixed.test to interprete DEFAULT for binlog_format as MIXED. Comments on what the test covers are added. todo/fixme: turning @@global.binlog_format to be read-only when it's set to NULL (no binlog). todo/fixme: options dependacy (acyclic) graph, particularly to solve a task of setting defaults values for the leaf nodes only when parents' nodes are set. mysql-test/r/rpl_switch_stm_row_mixed.result: changed mysql-test/t/rpl_switch_stm_row_mixed.test: correcting interpretation of DEFAULT for binlog_format, comments on test purpose, switching binlog_format section is formed. sql/mysqld.cc: introducing command line option parser's opt_binlog_format and its default. necessary code for transfering text value from command line arg into the system variable @@global.binlog_format.
2007-01-15 15:01:00 +01:00
set binlog_format=default;
select @@global.binlog_format, @@session.binlog_format;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
set @string="emergency_17_";
insert into t1 values("work_18_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat(UUID(),"work_19_"));
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat("for_20_",UUID()));
insert into t1 select "yesterday_21_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat(UUID(),"work_22_"));
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat("for_23_",UUID()));
insert into t1 select "yesterday_24_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
# Test of CREATE TABLE SELECT
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
create table t2 select rpad(UUID(),100,' ');
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
create table t3 select 1 union select UUID();
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
# what if UUID() is first:
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
# inside a stored procedure
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
delimiter |;
create procedure foo()
begin
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("work_25_");
insert into t1 values(concat("for_26_",UUID()));
insert into t1 select "yesterday_27_";
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
end|
create procedure foo2()
begin
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(concat("emergency_28_",UUID()));
insert into t1 values("work_29_");
insert into t1 values(concat("for_30_",UUID()));
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
set session binlog_format=row; # accepted for stored procs
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values("more work_31_");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
set session binlog_format=mixed;
end|
create function foo3() returns bigint unsigned
begin
set session binlog_format=row; # rejected for stored funcs
insert into t1 values("alarm");
return 100;
end|
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
create procedure foo4(x varchar(100))
begin
insert into t1 values(concat("work_250_",x));
insert into t1 select "yesterday_270_";
end|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
delimiter ;|
call foo();
call foo2();
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
call foo4("hello");
call foo4(UUID());
call foo4("world");
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
# test that can't SET in a stored function
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
select foo3();
select * from t1 where a="alarm";
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
# Tests of stored functions/triggers/views for BUG#20930 "Mixed
# binlogging mode does not work with stored functions, triggers,
# views"
# Function which calls procedure
drop function foo3;
delimiter |;
create function foo3() returns bigint unsigned
begin
insert into t1 values("foo3_32_");
call foo();
return 100;
end|
delimiter ;|
insert into t2 select foo3();
prepare stmt1 from 'insert into t2 select foo3()';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
# Test if stored function calls stored function which calls procedure
# which requires row-based.
delimiter |;
create function foo4() returns bigint unsigned
begin
insert into t2 select foo3();
return 100;
end|
delimiter ;|
select foo4();
prepare stmt1 from 'select foo4()';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
# A simple stored function
delimiter |;
create function foo5() returns bigint unsigned
begin
insert into t2 select UUID();
return 100;
end|
delimiter ;|
select foo5();
prepare stmt1 from 'select foo5()';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
# A simple stored function where UUID() is in the argument
delimiter |;
create function foo6(x varchar(100)) returns bigint unsigned
begin
insert into t2 select x;
return 100;
end|
delimiter ;|
select foo6("foo6_1_");
select foo6(concat("foo6_2_",UUID()));
prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
# Test of views using UUID()
create view v1 as select uuid();
create table t11 (data varchar(255));
insert into t11 select * from v1;
# Test of querying INFORMATION_SCHEMA which parses the view's body,
# to verify that it binlogs statement-based (is not polluted by
# the parsing of the view's body).
insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11');
prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
# Test of triggers with UUID()
delimiter |;
create trigger t11_bi before insert on t11 for each row
begin
set NEW.data = concat(NEW.data,UUID());
end|
delimiter ;|
insert into t11 values("try_560_");
# Test that INSERT DELAYED works in mixed mode (BUG#20649)
Fix for BUG#20649 "mixed replication mode does not work with INSERT DELAYED". The bug was that if the server was running in mixed binlogging mode, and an INSERT DELAYED used some needing-row-based components like UUID(), the server didn't binlog this row-based but statement-based, which thus failed to insert correct data on the slave. This changeset implements that when a delayed_insert thread is created, if the server's global binlog mode is "mixed", that thread will use row-based. This also fixes BUG#20633 "INSERT DELAYED RAND() or @user_var does not replicate statement-based": we don't fix it in statement-based mode (would require bookeeping of rand seeds and user variables used by each row), but at least it will now work in mixed mode (as row-based will be used). We re-enable rpl_switch_stm_row_mixed.test (so BUG#18590 which was about re-enabling this test, will be closed) to test the fixes. Between when it was disabled and now, some good changes to row-based binlogging (no generation of table map events for non-changed tables) induce changes in the test's result file. mysql-test/r/rpl_switch_stm_row_mixed.result: result update. Note that some pieces of binlog are gone, not due to my test but to changes to the row-based binlogging code (non-changed tables don't generate table map binlog events now) done while the test was disabled. mysql-test/t/disabled.def: this test works now mysql-test/t/rpl_switch_stm_row_mixed.test: testing fix to make INSERT DELAYED work in mixed mode sql/sql_insert.cc: In mixed binlogging mode, the delayed_insert system thread now always uses row-based binlogging. This makes replication of INSERT DELAYED VALUES(RAND()) or VALUES(@a) work in mixed mode (it does not in statement-based).
2006-07-06 17:54:04 +02:00
insert delayed into t2 values("delay_1_");
insert delayed into t2 values(concat("delay_2_",UUID()));
insert delayed into t2 values("delay_6_");
# Test for BUG#20633 (INSERT DELAYED RAND()/user_variable does not
# replicate fine in statement-based ; we test that in mixed mode it
# works).
insert delayed into t2 values(rand());
set @a=2.345;
insert delayed into t2 values(@a);
sleep 4; # time for the delayed inserts to reach disk
Fix for BUG#20649 "mixed replication mode does not work with INSERT DELAYED". The bug was that if the server was running in mixed binlogging mode, and an INSERT DELAYED used some needing-row-based components like UUID(), the server didn't binlog this row-based but statement-based, which thus failed to insert correct data on the slave. This changeset implements that when a delayed_insert thread is created, if the server's global binlog mode is "mixed", that thread will use row-based. This also fixes BUG#20633 "INSERT DELAYED RAND() or @user_var does not replicate statement-based": we don't fix it in statement-based mode (would require bookeeping of rand seeds and user variables used by each row), but at least it will now work in mixed mode (as row-based will be used). We re-enable rpl_switch_stm_row_mixed.test (so BUG#18590 which was about re-enabling this test, will be closed) to test the fixes. Between when it was disabled and now, some good changes to row-based binlogging (no generation of table map events for non-changed tables) induce changes in the test's result file. mysql-test/r/rpl_switch_stm_row_mixed.result: result update. Note that some pieces of binlog are gone, not due to my test but to changes to the row-based binlogging code (non-changed tables don't generate table map binlog events now) done while the test was disabled. mysql-test/t/disabled.def: this test works now mysql-test/t/rpl_switch_stm_row_mixed.test: testing fix to make INSERT DELAYED work in mixed mode sql/sql_insert.cc: In mixed binlogging mode, the delayed_insert system thread now always uses row-based binlogging. This makes replication of INSERT DELAYED VALUES(RAND()) or VALUES(@a) work in mixed mode (it does not in statement-based).
2006-07-06 17:54:04 +02:00
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
# If you want to do manual testing of the mixed mode regarding UDFs (not
# testable automatically as quite platform- and compiler-dependent),
# you just need to set the variable below to 1, and to
# "make udf_example.so" in sql/, and to copy sql/udf_example.so to
# MYSQL_TEST_DIR/lib/mysql.
let $you_want_to_test_UDF=0;
if ($you_want_to_test_UDF)
{
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
prepare stmt1 from 'insert into t1 select metaphon(?)';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
set @string="emergency_133_";
insert into t1 values("work_134_");
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(metaphon("work_135_"));
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
execute stmt1 using @string;
deallocate prepare stmt1;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
insert into t1 values(metaphon("for_136_"));
insert into t1 select "yesterday_137_";
create table t6 select metaphon("for_138_");
create table t7 select 1 union select metaphon("for_139_");
create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for_140_") union select 3);
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
create table t9 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
}
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
create table t20 select * from t1; # save for comparing later
create table t21 select * from t2;
create table t22 select * from t3;
drop table t1,t2,t3;
# This tests the fix to
# BUG#19630 stored function inserting into two auto_increment breaks statement-based binlog
# We verify that under the mixed binlog mode, a stored function
# modifying at least two tables having an auto_increment column,
# is binlogged row-based. Indeed in statement-based binlogging,
# only the auto_increment value generated for the first table
# is recorded in the binlog, the value generated for the 2nd table
# lacking.
create table t1 (a int primary key auto_increment, b varchar(100));
create table t2 (a int primary key auto_increment, b varchar(100));
create table t3 (b varchar(100));
delimiter |;
create function f (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
insert into t2 values(null,x);
return 1;
end|
delimiter ;|
select f("try_41_");
# Two operations which compensate each other except that their net
# effect is that they advance the auto_increment counter of t2 on slave:
sync_slave_with_master;
use mysqltest1;
insert into t2 values(2,null),(3,null),(4,null);
delete from t2 where a>=2;
connection master;
# this is the call which didn't replicate well
select f("try_42_");
sync_slave_with_master;
# now use prepared statement and test again, just to see that the RBB
# mode isn't set at PREPARE but at EXECUTE.
insert into t2 values(3,null),(4,null);
delete from t2 where a>=3;
connection master;
prepare stmt1 from 'select f(?)';
set @string="try_43_";
insert into t1 values(null,"try_44_"); # should be SBB
execute stmt1 using @string; # should be RBB
deallocate prepare stmt1;
sync_slave_with_master;
# verify that if only one table has auto_inc, it does not trigger RBB
# (we'll check in binlog further below)
connection master;
create table t12 select * from t1; # save for comparing later
drop table t1;
create table t1 (a int, b varchar(100), key(a));
select f("try_45_");
# restore table's key
create table t13 select * from t1;
drop table t1;
create table t1 (a int primary key auto_increment, b varchar(100));
# now test if it's two functions, each of them inserts in one table
drop function f;
fixes after merge. Updates to test's results. We now reset the THD members related to auto_increment+binlog in MYSQL_LOG::write(). This is better than in THD::cleanup_after_query(), which was not able to distinguish between SELECT myfunc1(),myfunc2() and INSERT INTO t SELECT myfunc1(),myfunc2() from a binlogging point of view. Rows_log_event::exec_event() now calls lex_start() instead of mysql_init_query() because the latter now does too much (it resets the binlog format). mysql-test/extra/rpl_tests/rpl_insert_id.test: fix after merge mysql-test/mysql-test-run.pl: -v does not bring useful information when running valgrind; I remove it; if you think it's useful add it back. mysql-test/r/binlog_stm_mix_innodb_myisam.result: Position columns of SHOW BINLOG EVENTS are replaced by # (more robust if the size of an event changes). mysql-test/r/rpl_insert_id.result: fix after merge mysql-test/r/rpl_loaddata.result: The binlog positions change, because one event disappeared; indeed there was this in the binlog (in the current 5.1!): SET INSERT_ID=2; SET INSERT_ID=1; SET TIMESTAMP=1152540671; load data LOCAL INFILE '/tmp/SQL_LOAD_MB-1-2' INTO table t1; Two INSERT_ID events, useless and a bug. Goes away afer cleaning up auto_increment handling. mysql-test/r/rpl_switch_stm_row_mixed.result: INSERT_ID=5 appears, it's a consequence of having merged the fix for BUG#20341 "stored function inserting into one auto_increment puts bad data in slave". In mixed mode, if one substatement of a stored procedure requires row-based, the entire procedure uses row-based (was already true for stored functions); this is a consequence of not doing the resetting of binlog format inside lock_tables() (which didn't work with how the slave thread executes row-based binlog events). mysql-test/t/rpl_switch_stm_row_mixed.test: removing the multi-row delayed insert because in RBR the number of events which it generates, is not repeatable (probably depends on how the delayed thread groups rows, i.e. dependent on timing). sql/ha_partition.cc: update to new prototype sql/ha_partition.h: update to new prototype of the handler:: method. sql/handler.cc: after-merge fixes (manually merging part which was hard to merge in fmtool) sql/log.cc: When we write to the binary log, THD's parameters which influenced this write are reset: stmt_depends_on_first_successful_insert_id_in_prev_stmt and auto_inc_intervals_in_cur_stmt_for_binlog. This is so that future writes are not influenced by those and can write their own values. As a consequence, when we don't write to the binlog we do not reset. This is to abide by the rule that in a complex statement (using triggers etc), the first top- or substatement to generate auto_increment ids wins their writing to the binlog (that writing may be done by the statement itself or by the caller); so for example for INSERT INTO t SELECT myfunc() where myfunc() inserts into auto_increment and INSERT INTO t does not, myfunc() will fill auto_inc_intervals_in_cur_stmt_for_binlog, which will not be reset when myfunc() ends, then INSERT INTO t will write to the binlog and thus write the preserved auto_inc_intervals_in_cur_stmt_for_binlog. sql/log_event.cc: mysql_init_query() does too much now to be called in Rows_log_event::exec_event (it call mysql_reset_thd_for_next_command() which may switch the binlog format now). It's ok to call it in Table_map_log_event::exec_event() but its call must be before setting the binlog format to "row". sql/sql_base.cc: Resetting the binlog format in lock_tables() was a bad idea of mine; it causes problems in execution of row-based binlog events, where the thread sets the binlog format by itself and does not want a next lock_tables() to reset the binlog format. It is also misleading, for a function named lock_tables(), to reset the binlog format. As a consequence of this change, in mixed binlogging mode, a routine is logged either entirely statement-based or entirely row-based, we don't switch in the middle (this was already true for prelocked routines, now it's also true for stored procedures). sql/sql_class.cc: resetting of auto_increment variables used for binlogging is now done when writing to the binary log, no need to do the resetting at the end of the statement. It is also more correct this way; consider SELECT myfunc1(),myfunc2(); where both functions insert into the same auto_increment column. Binlogging is done in 2 events: "SELECT myfunc1()" and "SELECT myfunc2()". So each of those needs to have, in binlog, the INSERT_ID which it inserted. But as the 2 function calls are executed under prelocked mode, the old code didn't reset auto_inc_intervals_in_cur_stmt_for_binlog after the first SELECT was binlogged, and so the INSERT_ID of the first SELECT was binlogged for the first SELECT and (wrong) also for the 2nd SELECT event. stmt_depends_on_first_... has the same logic. sql/sql_class.h: clearer comment sql/sql_delete.cc: unneeded #ifdef. As we temporarily change the binlog format to "statement" before calling mysql_delete(), we must restore it afterwards. sql/sql_insert.cc: after-merge fixes. No need to reset auto_inc_intervals_in_cur_stmt_for_binlog for every row in the delayed insert system thread, because we already reset it when writing to the binlog. sql/sql_parse.cc: unneeded #ifdef
2006-07-10 18:41:03 +02:00
# we need a unique key to have sorting of rows by mysqldump
create table t14 (unique (a)) select * from t2;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
truncate table t2;
delimiter |;
create function f1 (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
return 1;
end|
create function f2 (x varchar(100)) returns int deterministic
begin
insert into t2 values(null,x);
return 1;
end|
delimiter ;|
select f1("try_46_"),f2("try_47_");
sync_slave_with_master;
insert into t2 values(2,null),(3,null),(4,null);
delete from t2 where a>=2;
connection master;
# Test with SELECT and INSERT
select f1("try_48_"),f2("try_49_");
insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_")));
sync_slave_with_master;
# verify that if f2 does only read on an auto_inc table, this does not
# switch to RBB
connection master;
drop function f2;
delimiter |;
create function f2 (x varchar(100)) returns int deterministic
begin
declare y int;
insert into t1 values(null,x);
set y = (select count(*) from t2);
return y;
end|
delimiter ;|
select f1("try_53_"),f2("try_54_");
sync_slave_with_master;
# And now, a normal statement with a trigger (no stored functions)
connection master;
drop function f2;
delimiter |;
create trigger t1_bi before insert on t1 for each row
begin
insert into t2 values(null,"try_55_");
end|
delimiter ;|
insert into t1 values(null,"try_56_");
# and now remove one auto_increment and verify SBB
alter table t1 modify a int, drop primary key;
insert into t1 values(null,"try_57_");
sync_slave_with_master;
# Test for BUG#20499 "mixed mode with temporary table breaks binlog"
# Slave used to have only 2 rows instead of 3.
connection master;
CREATE TEMPORARY TABLE t15 SELECT UUID();
create table t16 like t15;
INSERT INTO t16 SELECT * FROM t15;
# we'll verify that this one is done RBB
insert into t16 values("try_65_");
drop table t15;
# we'll verify that this one is done SBB
insert into t16 values("try_66_");
sync_slave_with_master;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
# and now compare:
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
connection master;
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
# first check that data on master is sensible
select count(*) from t1;
select count(*) from t2;
select count(*) from t3;
select count(*) from t4;
select count(*) from t5;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
select count(*) from t11;
select count(*) from t20;
select count(*) from t21;
select count(*) from t22;
select count(*) from t12;
select count(*) from t13;
fixes after merge. Updates to test's results. We now reset the THD members related to auto_increment+binlog in MYSQL_LOG::write(). This is better than in THD::cleanup_after_query(), which was not able to distinguish between SELECT myfunc1(),myfunc2() and INSERT INTO t SELECT myfunc1(),myfunc2() from a binlogging point of view. Rows_log_event::exec_event() now calls lex_start() instead of mysql_init_query() because the latter now does too much (it resets the binlog format). mysql-test/extra/rpl_tests/rpl_insert_id.test: fix after merge mysql-test/mysql-test-run.pl: -v does not bring useful information when running valgrind; I remove it; if you think it's useful add it back. mysql-test/r/binlog_stm_mix_innodb_myisam.result: Position columns of SHOW BINLOG EVENTS are replaced by # (more robust if the size of an event changes). mysql-test/r/rpl_insert_id.result: fix after merge mysql-test/r/rpl_loaddata.result: The binlog positions change, because one event disappeared; indeed there was this in the binlog (in the current 5.1!): SET INSERT_ID=2; SET INSERT_ID=1; SET TIMESTAMP=1152540671; load data LOCAL INFILE '/tmp/SQL_LOAD_MB-1-2' INTO table t1; Two INSERT_ID events, useless and a bug. Goes away afer cleaning up auto_increment handling. mysql-test/r/rpl_switch_stm_row_mixed.result: INSERT_ID=5 appears, it's a consequence of having merged the fix for BUG#20341 "stored function inserting into one auto_increment puts bad data in slave". In mixed mode, if one substatement of a stored procedure requires row-based, the entire procedure uses row-based (was already true for stored functions); this is a consequence of not doing the resetting of binlog format inside lock_tables() (which didn't work with how the slave thread executes row-based binlog events). mysql-test/t/rpl_switch_stm_row_mixed.test: removing the multi-row delayed insert because in RBR the number of events which it generates, is not repeatable (probably depends on how the delayed thread groups rows, i.e. dependent on timing). sql/ha_partition.cc: update to new prototype sql/ha_partition.h: update to new prototype of the handler:: method. sql/handler.cc: after-merge fixes (manually merging part which was hard to merge in fmtool) sql/log.cc: When we write to the binary log, THD's parameters which influenced this write are reset: stmt_depends_on_first_successful_insert_id_in_prev_stmt and auto_inc_intervals_in_cur_stmt_for_binlog. This is so that future writes are not influenced by those and can write their own values. As a consequence, when we don't write to the binlog we do not reset. This is to abide by the rule that in a complex statement (using triggers etc), the first top- or substatement to generate auto_increment ids wins their writing to the binlog (that writing may be done by the statement itself or by the caller); so for example for INSERT INTO t SELECT myfunc() where myfunc() inserts into auto_increment and INSERT INTO t does not, myfunc() will fill auto_inc_intervals_in_cur_stmt_for_binlog, which will not be reset when myfunc() ends, then INSERT INTO t will write to the binlog and thus write the preserved auto_inc_intervals_in_cur_stmt_for_binlog. sql/log_event.cc: mysql_init_query() does too much now to be called in Rows_log_event::exec_event (it call mysql_reset_thd_for_next_command() which may switch the binlog format now). It's ok to call it in Table_map_log_event::exec_event() but its call must be before setting the binlog format to "row". sql/sql_base.cc: Resetting the binlog format in lock_tables() was a bad idea of mine; it causes problems in execution of row-based binlog events, where the thread sets the binlog format by itself and does not want a next lock_tables() to reset the binlog format. It is also misleading, for a function named lock_tables(), to reset the binlog format. As a consequence of this change, in mixed binlogging mode, a routine is logged either entirely statement-based or entirely row-based, we don't switch in the middle (this was already true for prelocked routines, now it's also true for stored procedures). sql/sql_class.cc: resetting of auto_increment variables used for binlogging is now done when writing to the binary log, no need to do the resetting at the end of the statement. It is also more correct this way; consider SELECT myfunc1(),myfunc2(); where both functions insert into the same auto_increment column. Binlogging is done in 2 events: "SELECT myfunc1()" and "SELECT myfunc2()". So each of those needs to have, in binlog, the INSERT_ID which it inserted. But as the 2 function calls are executed under prelocked mode, the old code didn't reset auto_inc_intervals_in_cur_stmt_for_binlog after the first SELECT was binlogged, and so the INSERT_ID of the first SELECT was binlogged for the first SELECT and (wrong) also for the 2nd SELECT event. stmt_depends_on_first_... has the same logic. sql/sql_class.h: clearer comment sql/sql_delete.cc: unneeded #ifdef. As we temporarily change the binlog format to "statement" before calling mysql_delete(), we must restore it afterwards. sql/sql_insert.cc: after-merge fixes. No need to reset auto_inc_intervals_in_cur_stmt_for_binlog for every row in the delayed insert system thread, because we already reset it when writing to the binlog. sql/sql_parse.cc: unneeded #ifdef
2006-07-10 18:41:03 +02:00
select count(*) from t14;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
select count(*) from t16;
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
if ($you_want_to_test_UDF)
{
select count(*) from t6;
select count(*) from t7;
select count(*) from t8;
select count(*) from t9;
}
sync_slave_with_master;
#
# Bug#20863 If binlog format is changed between update and unlock of
# tables, wrong binlog
#
connection master;
DROP TABLE IF EXISTS t11;
SET SESSION BINLOG_FORMAT=STATEMENT;
CREATE TABLE t11 (song VARCHAR(255));
LOCK TABLES t11 WRITE;
SET SESSION BINLOG_FORMAT=ROW;
INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict');
SET SESSION BINLOG_FORMAT=STATEMENT;
INSERT INTO t11 VALUES('Careful With That Axe, Eugene');
UNLOCK TABLES;
--query_vertical SELECT * FROM t11
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
sync_slave_with_master;
USE mysqltest1;
--query_vertical SELECT * FROM t11
connection master;
DROP TABLE IF EXISTS t12;
SET SESSION BINLOG_FORMAT=MIXED;
CREATE TABLE t12 (data LONG);
LOCK TABLES t12 WRITE;
INSERT INTO t12 VALUES(UUID());
UNLOCK TABLES;
--replace_column 2 # 5 #
--replace_regex /table_id: [0-9]+/table_id: #/
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
show binlog events from 102;
sync_slave_with_master;
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
# as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement), and new binlog format called "mixed" (which is statement-based except if only row-based is correct, in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release): SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default; the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha. It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below). The added tests test the possibility or impossibility to SET, their effects, and the mixed mode, including in prepared statements and in stored procedures and functions. Caveats: a) The mixed mode will not work for stored functions: in mixed mode, a stored function will always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()). b) for the same reason, changing the thread's binlog format inside a stored function is refused with an error message. c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask Dmitri). Additionally, as the binlog format is now changeable by each user for his session, I remove the implication which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1 (not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled phantom protection). Plus fixes for compiler warnings. mysql-test/r/rpl_row_4_bytes.result: update mysql-test/t/rpl_row_4_bytes.test: don't influence next tests sql/ha_archive.cc: please pay attention to this structure when you change it... sql/ha_berkeley.cc: please pay attention to this structure when you change it... sql/ha_blackhole.cc: please pay attention to this structure when you change it... sql/ha_federated.cc: please pay attention to this structure when you change it... sql/ha_heap.cc: please pay attention to this structure when you change it... sql/ha_innodb.cc: please pay attention to this structure when you change it... sql/ha_myisam.cc: please pay attention to this structure when you change it... sql/ha_myisammrg.cc: please pay attention to this structure when you change it... sql/ha_ndbcluster_binlog.cc: no more global 'binlog_row_based' sql/ha_partition.cc: please pay attention to this structure when you change it... sql/handler.cc: please pay attention to this structure when you change it... sql/handler.h: it's good to initialize statically (to get no compiler warning) even if to a null value. sql/item_func.cc: UDFs require row-based if this is the "mixed" binlog format. sql/item_strfunc.cc: UUID() requires row-based binlogging if this is the "mixed" binlog format sql/log.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log.h: the enum enum_binlog_format moves to log.h from mysqld.cc as we need it in several places. sql/log_event.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/log_event.h: this global variable not used anymore sql/mysql_priv.h: these global variables not used anymore sql/mysqld.cc: simplification in the handling of --binlog-format (but with no user-visible change), thanks to the new global system variable. RBR does not anymore turn on --log-bin-trust-function-creators and --innodb-locks-unsafe-for-binlog as these are global options and RBR is now settable per session. sql/partition_info.cc: compiler warnings sql/set_var.cc: new class of thread's variable, to handle the binlog_format (like sys_var_thd_enum except that is_readonly() is overriden for more checks before update). compiler warnings (ok'd by Serg) sql/set_var.h: new class for the thread's binlog_format (see set_var.cc) sql/share/errmsg.txt: some messages for when one can't toggle from one binlog format to another sql/sp_head.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_base.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_class.cc: When a THD is initialized, we set its current_stmt_binlog_row_based sql/sql_class.h: new THD::variables.binlog_format (the value of the session variable set by SET or inherited from the global value), and THD::current_stmt_binlog_row_based which tells if the current statement does row-based or statement-based binlogging. Both members are needed as the 2nd one cannot be derived only from the first one (the statement's type plays a role too), and the 1st one is needed to reset the 2nd one. sql/sql_delete.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_insert.cc: binlog_row_based -> thd->current_stmt_binlog_row_based sql/sql_load.cc: binlog_row_based -> thd->current_stmt_binlog_row_based. sql/sql_parse.cc: when we are done with a statement, we reset the current_stmt_binlog_row_based to the value derived from THD::variables.binlog_format. sql/sql_partition.cc: compiler warning sql/sql_show.cc: compiler warning sql/sql_table.cc: binlog_row_based -> thd->current_stmt_binlog_row_based tests/mysql_client_test.c: compiler warning mysql-test/r/ndb_binlog_basic2.result: new result mysql-test/r/rpl_switch_stm_row_mixed.result: new result mysql-test/t/ndb_binlog_basic2.test: new test to verify that if cluster is enabled, can't change binlog format on the fly. mysql-test/t/rpl_switch_stm_row_mixed.test: test to see if one can switch between SBR, RBR, and "mixed" mode, and when one cannot, and test to see if the switching, and the mixed mode, work properly (using UUID() to test, as using UDFs is not possible in the testsuite for portability reasons).
2006-02-25 22:21:03 +01:00
# Let's compare. Note: If they match test will pass, if they do not match
# the test will show that the diff statement failed and not reject file
# will be created. You will need to go to the mysql-test dir and diff
# the files your self to see what is not matching
Fixes to the replication mixed mode (patch approved by Monty): - detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID(). - more tests of this mixed mode. mysql-test/r/rpl_switch_stm_row_mixed.result: result update mysql-test/t/rpl_switch_stm_row_mixed.test: testing more scenarios for the mixed replication mode. Added support for manual testing of UDFs vs the mixed mode (behind a variable in the test). Changing old file names to better ones. sql/item_create.cc: at parse time, when we see a UUID(), put up a flag in LEX to say this binlogs properly only with row-based binlogging. sql/item_func.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage. sql/item_strfunc.cc: it's not perfect to put up the flag at this execution stage, better do it at parse stage sql/set_var.cc: this assertion is wrong, this piece of code can happen in RBR mode too. sql/sql_lex.cc: when we reinitialize the LEX members before every query, we have to reinitialize the new flag sql/sql_lex.h: A new flag, set at parsing stage, which tells if some items seen during parsing stage require row-based replication to binlog/replicate correctly when this statement is later executed. It has to be in LEX and not directly in THD, for this to work in prepared statements. sql/sql_parse.cc: Parsing stage happened at some time in the past and set up the flag in LEX, now that we execute the statement we actually turn on row-based binlogging if the thread's binlog format is "mixed". We then turn it off when leaving mysql_execute_command(). Some cleanup code was not executed if leaving mysql_execute_command() at the "error" label, fixing this. A better fix than the "goto end" would be to modify each "goto error" to "res=1; goto end" but it required changing many lines which I don't want to do now ("make smallest possible patch"). sql/sql_yacc.yy: When at parsing stage we see a UDF we put up a flag to say that row-based binlogging is preferred.
2006-03-13 15:34:30 +01:00
--exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
connection master;
--replace_column 2 # 5 #
fixes after merge. Updates to test's results. We now reset the THD members related to auto_increment+binlog in MYSQL_LOG::write(). This is better than in THD::cleanup_after_query(), which was not able to distinguish between SELECT myfunc1(),myfunc2() and INSERT INTO t SELECT myfunc1(),myfunc2() from a binlogging point of view. Rows_log_event::exec_event() now calls lex_start() instead of mysql_init_query() because the latter now does too much (it resets the binlog format). mysql-test/extra/rpl_tests/rpl_insert_id.test: fix after merge mysql-test/mysql-test-run.pl: -v does not bring useful information when running valgrind; I remove it; if you think it's useful add it back. mysql-test/r/binlog_stm_mix_innodb_myisam.result: Position columns of SHOW BINLOG EVENTS are replaced by # (more robust if the size of an event changes). mysql-test/r/rpl_insert_id.result: fix after merge mysql-test/r/rpl_loaddata.result: The binlog positions change, because one event disappeared; indeed there was this in the binlog (in the current 5.1!): SET INSERT_ID=2; SET INSERT_ID=1; SET TIMESTAMP=1152540671; load data LOCAL INFILE '/tmp/SQL_LOAD_MB-1-2' INTO table t1; Two INSERT_ID events, useless and a bug. Goes away afer cleaning up auto_increment handling. mysql-test/r/rpl_switch_stm_row_mixed.result: INSERT_ID=5 appears, it's a consequence of having merged the fix for BUG#20341 "stored function inserting into one auto_increment puts bad data in slave". In mixed mode, if one substatement of a stored procedure requires row-based, the entire procedure uses row-based (was already true for stored functions); this is a consequence of not doing the resetting of binlog format inside lock_tables() (which didn't work with how the slave thread executes row-based binlog events). mysql-test/t/rpl_switch_stm_row_mixed.test: removing the multi-row delayed insert because in RBR the number of events which it generates, is not repeatable (probably depends on how the delayed thread groups rows, i.e. dependent on timing). sql/ha_partition.cc: update to new prototype sql/ha_partition.h: update to new prototype of the handler:: method. sql/handler.cc: after-merge fixes (manually merging part which was hard to merge in fmtool) sql/log.cc: When we write to the binary log, THD's parameters which influenced this write are reset: stmt_depends_on_first_successful_insert_id_in_prev_stmt and auto_inc_intervals_in_cur_stmt_for_binlog. This is so that future writes are not influenced by those and can write their own values. As a consequence, when we don't write to the binlog we do not reset. This is to abide by the rule that in a complex statement (using triggers etc), the first top- or substatement to generate auto_increment ids wins their writing to the binlog (that writing may be done by the statement itself or by the caller); so for example for INSERT INTO t SELECT myfunc() where myfunc() inserts into auto_increment and INSERT INTO t does not, myfunc() will fill auto_inc_intervals_in_cur_stmt_for_binlog, which will not be reset when myfunc() ends, then INSERT INTO t will write to the binlog and thus write the preserved auto_inc_intervals_in_cur_stmt_for_binlog. sql/log_event.cc: mysql_init_query() does too much now to be called in Rows_log_event::exec_event (it call mysql_reset_thd_for_next_command() which may switch the binlog format now). It's ok to call it in Table_map_log_event::exec_event() but its call must be before setting the binlog format to "row". sql/sql_base.cc: Resetting the binlog format in lock_tables() was a bad idea of mine; it causes problems in execution of row-based binlog events, where the thread sets the binlog format by itself and does not want a next lock_tables() to reset the binlog format. It is also misleading, for a function named lock_tables(), to reset the binlog format. As a consequence of this change, in mixed binlogging mode, a routine is logged either entirely statement-based or entirely row-based, we don't switch in the middle (this was already true for prelocked routines, now it's also true for stored procedures). sql/sql_class.cc: resetting of auto_increment variables used for binlogging is now done when writing to the binary log, no need to do the resetting at the end of the statement. It is also more correct this way; consider SELECT myfunc1(),myfunc2(); where both functions insert into the same auto_increment column. Binlogging is done in 2 events: "SELECT myfunc1()" and "SELECT myfunc2()". So each of those needs to have, in binlog, the INSERT_ID which it inserted. But as the 2 function calls are executed under prelocked mode, the old code didn't reset auto_inc_intervals_in_cur_stmt_for_binlog after the first SELECT was binlogged, and so the INSERT_ID of the first SELECT was binlogged for the first SELECT and (wrong) also for the 2nd SELECT event. stmt_depends_on_first_... has the same logic. sql/sql_class.h: clearer comment sql/sql_delete.cc: unneeded #ifdef. As we temporarily change the binlog format to "statement" before calling mysql_delete(), we must restore it afterwards. sql/sql_insert.cc: after-merge fixes. No need to reset auto_inc_intervals_in_cur_stmt_for_binlog for every row in the delayed insert system thread, because we already reset it when writing to the binlog. sql/sql_parse.cc: unneeded #ifdef
2006-07-10 18:41:03 +02:00
--replace_regex /table_id: [0-9]+/table_id: #/
* Mixed replication mode * : 1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": a stored function inserting into two such tables may fail to replicate (inserting wrong data in the slave's copy of the second table) if the slave's second table had an internal auto_increment counter different from master's. Because the auto_increment value autogenerated by master for the 2nd table does not go into binlog, only the first does, so the slave lacks information. To fix this, if running in mixed binlogging mode, if the stored function or trigger plans to update two different tables both having auto_increment columns, we switch to row-based for the whole function. We don't have a simple solution for statement-based binlogging mode, there the bug remains and will be documented as a known problem. Re-enabling rpl_switch_stm_row_mixed. 2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored functions, triggers, views", which was a documented limitation (in mixed mode, we didn't detect that a stored function's execution needed row-based binlogging (due to some UUID() call for example); same for triggers, same for views (a view created from a SELECT UUID(), and doing INSERT INTO sometable SELECT theview; would not replicate row-based). This is implemented by, after parsing a routine's body, remembering in sp_head that this routine needs row-based binlogging. Then when this routine is used, the caller is marked to require row-based binlogging too. Same for views: when we parse a view and detect that its SELECT needs row-based binary logging, we mark the calling LEX as such. 3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog": a temporary table containing e.g. UUID has its changes not binlogged, so any query updating a permanent table with data from the temporary table will run wrongly on slave. Solution: in mixed mode we don't switch back from row-based to statement-based when there exists temporary tables. 4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog; impossible due to BUG#11312 and BUG#20329, but test is in place for when they are fixed. mysql-test/r/rpl_switch_stm_row_mixed.result: testing BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog", testing BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views. testing BUG#20499 "mixed mode with temporary table breaks binlog". I have carefully checked this big result file, it is correct. mysql-test/t/disabled.def: re-enabling test mysql-test/t/rpl_switch_stm_row_mixed.test: Test for BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": we test that it goes row-based, but only when needed; without the bugfix, master and slave's data differed. Test for BUG#20499 "mixed mode with temporary table breaks binlog": without the bugfix, slave had 2 rows, not 3. Test for BUG#20930 "Mixed binlogging mode does not work with stored functions, triggers, views". Making strings used more different, for easier tracking of "by which routine was this binlog line generated". Towards the end, an attempt to test mysqlbinlog on a binlog generated by the mixed mode; attempt failed because of BUG#11312 and BUG#20929. sql/item_create.cc: fix for build without row-based replication sql/set_var.cc: cosmetic: in_sub_stmt is exactly meant to say if we are in stored function/trigger, so better use it. sql/sp.cc: When a routine adds its tables to the top statement's tables, if this routine needs row-based binlogging, mark the entire top statement as well. Same for triggers. Needed for making the mixed replication mode work with stored functions and triggers. sql/sp_head.cc: new enum value for sp_head::m_flags, remembers if, when parsing the routine, we found at least one element (UUID(), UDF) requiring row-based binlogging. sql/sp_head.h: new enum value for sp_head::m_flags (see sp_head.cc). An utility method, intended for attributes of a routine which need to propagate upwards to the caller; so far only used for binlogging information, but open to any other attribute. sql/sql_base.cc: For BUG#19630 "stored function inserting into two auto_increment breaks statement-based binlog": When we come to locking tables, we have collected all tables used by functions, views and triggers, we detect if we're going to update two tables having auto_increment columns. If yes, statement-based binlogging won't work (Intvar_log_event records only one insert_id) so, if in mixed binlogging mode, switch to row-based. For making mixed mode work with stored functions using UUID/UDF: when we come to locking tables, we have parsed the whole body so know if some elements need row-based. Generation of row-based binlog events depends on locked tables, so this is the good place to decide of the binlog format. sql/sql_class.h: Fix for BUG#20499 "mixed mode with temporary table breaks binlog". Making mixed mode work with stored functions/triggers: don't reset back to statement-based if in executing a stored function/trigger. sql/sql_lex.cc: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA and thus implicitely parses a view or routine's body: this body may contain needing-row-based components like UUID() but the SELECT on INFORMATION_SCHEMA should not be affected by that and should not use row-based; as Query_tables_list is backed-up/reset/restored when parsing the view/routine's body, so does binlog_row_based_if_mixed and the top SELECT is not affected. sql/sql_lex.h: fix for build without row-based replication. binlog_row_based_if_mixed moves from st_lex to Query_tables_list (see sql_lex.cc) sql/sql_parse.cc: For the mixed mode to work with stored functions using UUID and UDF, we need to move the switch-back-from-row-to-statement out of mysql_execute_command() (which is executed for each statement, causing the binlogging mode to change in the middle of the function, which would not work) The switch to row-based is now done in lock_tables(), no need to keep it in mysql_execute_command(); in lock_tables() we also switch back from row-based to statement-based (so in a stored procedure, all statements have their binlogging mode). We must however keep a resetting in mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call lock_tables(). sql/sql_view.cc: When a view's body needs row-based binlogging (e.g. the view is created from SELECT UUID()), propagate this fact to the top st_lex. sql/sql_yacc.yy: use TRUE instead of 1, for binlog_row_based_if_mixed.
2006-07-09 17:00:47 +02:00
show binlog events from 102;
# Now test that mysqlbinlog works fine on a binlog generated by the
# mixed mode
# BUG#11312 "DELIMITER is not written to the binary log that causes
# syntax error" makes that mysqlbinlog will fail if we pass it the
# text of queries; this forces us to use --base64-output here.
# BUG#20929 "BINLOG command causes invalid free plus assertion
# failure" makes mysqld segfault when receiving --base64-output
# So I can't enable this piece of test
# SIGH
if ($enable_when_11312_or_20929_fixed)
{
--exec $MYSQL_BINLOG --base64-output $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
drop database mysqltest1;
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
# the old mysqldump output on slave is the same as what it was on
# master before restoring on master.
--exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
}
drop database mysqltest1;
sync_slave_with_master;