mariadb/mysql-test/r/rpl_switch_stm_row_mixed.result

1006 lines
48 KiB
Text
Raw Normal View History

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
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
drop database if exists mysqltest1;
create database mysqltest1;
use mysqltest1;
set session binlog_format=row;
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%";
Variable_name Value
binlog_format ROW
show session variables like "binlog_format%";
Variable_name Value
binlog_format ROW
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
ROW ROW
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_";
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
set binlog_format=statement;
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
insert into t1 select * from tmp;
drop temporary table tmp;
set binlog_format=statement;
show global variables like "binlog_format%";
Variable_name Value
binlog_format ROW
show session variables like "binlog_format%";
Variable_name Value
binlog_format STATEMENT
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
ROW STATEMENT
set global binlog_format=statement;
show global variables like "binlog_format%";
Variable_name Value
binlog_format STATEMENT
show session variables like "binlog_format%";
Variable_name Value
binlog_format STATEMENT
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
STATEMENT STATEMENT
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
set binlog_format=default;
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
STATEMENT STATEMENT
set global binlog_format=default;
ERROR 42000: Variable 'binlog_format' doesn't have a default value
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
STATEMENT STATEMENT
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
set binlog_format=mixed;
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
STATEMENT MIXED
set global binlog_format=mixed;
select @@global.binlog_format, @@session.binlog_format;
@@global.binlog_format @@session.binlog_format
MIXED MIXED
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_";
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);
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
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
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
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
select foo3();
ERROR HY000: Cannot change the binary logging format inside a stored function or trigger
select * from t1 where a="alarm";
a
* 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
drop function foo3;
create function foo3() returns bigint unsigned
begin
insert into t1 values("foo3_32_");
call foo();
return 100;
end|
insert into t2 select foo3();
prepare stmt1 from 'insert into t2 select foo3()';
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
create function foo4() returns bigint unsigned
begin
insert into t2 select foo3();
return 100;
end|
select foo4();
foo4()
100
prepare stmt1 from 'select foo4()';
execute stmt1;
foo4()
100
execute stmt1;
foo4()
100
deallocate prepare stmt1;
create function foo5() returns bigint unsigned
begin
insert into t2 select UUID();
return 100;
end|
select foo5();
foo5()
100
prepare stmt1 from 'select foo5()';
execute stmt1;
foo5()
100
execute stmt1;
foo5()
100
deallocate prepare stmt1;
create function foo6(x varchar(100)) returns bigint unsigned
begin
insert into t2 select x;
return 100;
end|
select foo6("foo6_1_");
foo6("foo6_1_")
100
select foo6(concat("foo6_2_",UUID()));
foo6(concat("foo6_2_",UUID()))
100
prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))';
execute stmt1;
foo6(concat("foo6_3_",UUID()))
100
execute stmt1;
foo6(concat("foo6_3_",UUID()))
100
deallocate prepare stmt1;
create view v1 as select uuid();
create table t11 (data varchar(255));
insert into t11 select * from v1;
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;
create trigger t11_bi before insert on t11 for each row
begin
set NEW.data = concat(NEW.data,UUID());
end|
insert into t11 values("try_560_");
insert delayed into t2 values("delay_1_");
insert delayed into t2 values(concat("delay_2_",UUID()));
insert delayed into t2 values("delay_6_");
insert delayed into t2 values(rand());
set @a=2.345;
insert delayed into t2 values(@a);
* 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;
create table t21 select * from t2;
create table t22 select * from t3;
drop table t1,t2,t3;
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));
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|
select f("try_41_");
f("try_41_")
1
use mysqltest1;
insert into t2 values(2,null),(3,null),(4,null);
delete from t2 where a>=2;
select f("try_42_");
f("try_42_")
1
insert into t2 values(3,null),(4,null);
delete from t2 where a>=3;
prepare stmt1 from 'select f(?)';
set @string="try_43_";
insert into t1 values(null,"try_44_");
execute stmt1 using @string;
f(?)
1
deallocate prepare stmt1;
create table t12 select * from t1;
drop table t1;
create table t1 (a int, b varchar(100), key(a));
select f("try_45_");
f("try_45_")
1
create table t13 select * from t1;
drop table t1;
create table t1 (a int primary key auto_increment, b varchar(100));
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
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;
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|
select f1("try_46_"),f2("try_47_");
f1("try_46_") f2("try_47_")
1 1
insert into t2 values(2,null),(3,null),(4,null);
delete from t2 where a>=2;
select f1("try_48_"),f2("try_49_");
f1("try_48_") f2("try_49_")
1 1
insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_")));
drop function f2;
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|
select f1("try_53_"),f2("try_54_");
f1("try_53_") f2("try_54_")
1 3
drop function f2;
create trigger t1_bi before insert on t1 for each row
begin
insert into t2 values(null,"try_55_");
end|
insert into t1 values(null,"try_56_");
alter table t1 modify a int, drop primary key;
insert into t1 values(null,"try_57_");
CREATE TEMPORARY TABLE t15 SELECT UUID();
create table t16 like t15;
INSERT INTO t16 SELECT * FROM t15;
insert into t16 values("try_65_");
drop table t15;
insert into t16 values("try_66_");
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
select count(*) from t1;
count(*)
* 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
7
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
select count(*) from t2;
count(*)
5
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
select count(*) from t3;
count(*)
* 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
1
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
select count(*) from t4;
count(*)
29
select count(*) from t5;
count(*)
58
* 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;
count(*)
8
select count(*) from t20;
count(*)
66
select count(*) from t21;
count(*)
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
19
* 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 t22;
count(*)
2
select count(*) from t12;
count(*)
4
select count(*) from t13;
count(*)
1
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;
count(*)
4
* 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;
count(*)
3
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;
SELECT * FROM t11;
song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict
song Careful With That Axe, Eugene
USE mysqltest1;
SELECT * FROM t11;
song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict
song Careful With That Axe, Eugene
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;
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;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # drop database if exists mysqltest1
master-bin.000001 # Query 1 # create database mysqltest1
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_8_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_9_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_10_")
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_11_"
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_13_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_14_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_15_")
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_16_"
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_18_")
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_21_"
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_24_"
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
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `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
`rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''
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
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t3` (
Manual merge 5.0->5.1. Post-merge fixes. client/mysqldump.c: A post-merge fix - 'sock' was renamed to 'mysql' mysql-test/r/events_bugs.result: A post merge fix: now we strip rear comments from the query before it gets into the log. mysql-test/r/func_group.result: A post merge fix: default clause is now printed uppercase. mysql-test/r/im_life_cycle.result: Fix my mistake in manual resolve. mysql-test/r/mysqlcheck.result: use test; - after we drop client_test_db there is no current database. This cleanup is present in 5.1 only, but the test that was added in 5.0 assumes there is a current database, test. mysql-test/r/mysqldump.result: Ignore results of execution of mysqldump: we can't rely on MASTER_LOG_POS in test results, it's different for statement and row level logging. mysql-test/r/mysqlshow.result: A post-merge fix: information schema contains a few more tables in 5.1 mysql-test/r/mysqltest.result: A post merge fix: add 5.1 test end separator. mysql-test/r/ndb_basic.result: A post-merge fix: add test end separators. mysql-test/r/rpl_switch_stm_row_mixed.result: A post merge fix: length of varbinary column is now 3 times less. Assuming a side effect of some other change. Length of any field is not relevant in this test. mysql-test/r/rpl_view.result: Add an end of test marker. mysql-test/r/show_check.result: Remove duplicate results. Add results from a merged test case. mysql-test/r/sp-error.result: Add test end separators. mysql-test/r/sp-security.result: Post-merge fix: use test after the current database is dropped. mysql-test/r/sp.result: Remove a duplicate result (bad merge that left a copy of the test case for Bug#19862 in the test suite). mysql-test/r/strict.result: An after-merge fix for a new test case: in 5.1 we issue a more accurate error message: "Incorrect value" instead of "Truncated value". I reason it so that in case of an error nothing is truncated, really. Also found similar changes in other test cases. mysql-test/r/type_datetime.result: Fix the text of an error. mysql-test/r/union.result: A post-merge fix: CHARACTER SET is now uppercase. mysql-test/t/mysqlcheck.test: A post-merge fix: use test, after current database is dropped, there is no current database. mysql-test/t/mysqldump.test: Disable result log: it's dependent on binlog position. mysql-test/t/sp-security.test: use test sql/item_sum.cc: Adjust the call to the constructor after the merge. sql/sp_head.cc: Add a missing DBUG_VOID_RETURN, move security checks out of execute_trigger to Table_triggers_list: in 5.1 we check for TRIGGER privilege, not SUPER privilege to execute triggers, so these checks lack table context inside execute_trigger and have to be performed when we have table object on hand. sql/sql_db.cc: A post-merge fix: adjust load_db_opt_by_name and check_db_dir_existence (new functions added in 5.0) to be tablename-to-filename encoding friendly. sql/sql_lex.cc: A post-merge fix: make skip_rear_comments operate on const uchar *s. sql/sql_lex.h: A post-merge fix. sql/sql_show.cc: A post-merge fix: fix a bad merge, rename orig_sql_command -> sql_command. sql/sql_trigger.cc: A post-merge fix: move security checks to process_triggers from execute_trigger. sql/sql_view.cc: Adjust to the new signature of skip_rear_comments. sql/sql_yacc.yy: Adjust to the new signature of init_strings.
2006-08-14 11:27:11 +02:00
`1` varbinary(36) NOT NULL DEFAULT ''
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
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t4` (
`a` varchar(100) DEFAULT NULL
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t4)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t5)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
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
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
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
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
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
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
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
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
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4(x varchar(100))
begin
insert into t1 values(concat("work_250_",x));
insert into t1 select "yesterday_270_";
end
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'hello')))
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'world')))
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
master-bin.000001 # Query 1 # use `mysqltest1`; drop function foo3
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
begin
insert into t1 values("foo3_32_");
call foo();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
* 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
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
* 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
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo4() returns bigint unsigned
begin
insert into t2 select foo3();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo5() returns bigint unsigned
begin
insert into t2 select UUID();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo6(x varchar(100)) returns bigint unsigned
begin
insert into t2 select x;
return 100;
end
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `foo6`(_latin1'foo6_1_')
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select uuid()
master-bin.000001 # Query 1 # use `mysqltest1`; create table t11 (data varchar(255))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t11_bi before insert on t11 for each row
begin
set NEW.data = concat(NEW.data,UUID());
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; create table t20 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t21 select * from t2
master-bin.000001 # Query 1 # use `mysqltest1`; create table t22 select * from t3
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1,t2,t3
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; create table t3 (b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
insert into t2 values(null,x);
return 1;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Intvar 1 # INSERT_ID=3
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_44_")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; create table t12 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int, b varchar(100), key(a))
master-bin.000001 # Intvar 1 # INSERT_ID=4
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f`(_latin1'try_45_')
master-bin.000001 # Query 1 # use `mysqltest1`; create table t13 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; 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
master-bin.000001 # Query 1 # use `mysqltest1`; 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
master-bin.000001 # Query 1 # use `mysqltest1`; truncate table t2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f1 (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
return 1;
end
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic
begin
insert into t2 values(null,x);
return 1;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` 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
master-bin.000001 # Intvar 1 # INSERT_ID=4
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f1`(_latin1'try_53_')
master-bin.000001 # Intvar 1 # INSERT_ID=5
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f2`(_latin1'try_54_')
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1 for each row
begin
insert into t2 values(null,"try_55_");
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t1 modify a int, drop primary key
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
master-bin.000001 # Intvar 1 # INSERT_ID=5
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_57_")
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t16` (
`UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_")
master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t11
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene')
master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t12
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
show binlog events from 102;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # drop database if exists mysqltest1
master-bin.000001 # Query 1 # create database mysqltest1
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_8_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_9_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_10_")
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_11_"
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_13_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_14_")
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_15_")
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_16_"
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_18_")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_21_"
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_24_"
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t2` (
`rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t3` (
`1` varbinary(36) NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t4` (
`a` varchar(100) DEFAULT NULL
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t4)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t5)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
begin
insert into t1 values("work_25_");
insert into t1 values(concat("for_26_",UUID()));
insert into t1 select "yesterday_27_";
end
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
begin
insert into t1 values(concat("emergency_28_",UUID()));
insert into t1 values("work_29_");
insert into t1 values(concat("for_30_",UUID()));
set session binlog_format=row; # accepted for stored procs
insert into t1 values("more work_31_");
set session binlog_format=mixed;
end
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
begin
set session binlog_format=row; # rejected for stored funcs
insert into t1 values("alarm");
return 100;
end
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4(x varchar(100))
begin
insert into t1 values(concat("work_250_",x));
insert into t1 select "yesterday_270_";
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'hello')))
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'world')))
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
master-bin.000001 # Query 1 # use `mysqltest1`; drop function foo3
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
begin
insert into t1 values("foo3_32_");
call foo();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
* 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
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
* 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
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo4() returns bigint unsigned
begin
insert into t2 select foo3();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo5() returns bigint unsigned
begin
insert into t2 select UUID();
return 100;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo6(x varchar(100)) returns bigint unsigned
begin
insert into t2 select x;
return 100;
end
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `foo6`(_latin1'foo6_1_')
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select uuid()
master-bin.000001 # Query 1 # use `mysqltest1`; create table t11 (data varchar(255))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t11_bi before insert on t11 for each row
begin
set NEW.data = concat(NEW.data,UUID());
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; create table t20 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t21 select * from t2
master-bin.000001 # Query 1 # use `mysqltest1`; create table t22 select * from t3
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1,t2,t3
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; create table t3 (b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
insert into t2 values(null,x);
return 1;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Intvar 1 # INSERT_ID=3
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_44_")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; create table t12 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int, b varchar(100), key(a))
master-bin.000001 # Intvar 1 # INSERT_ID=4
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f`(_latin1'try_45_')
master-bin.000001 # Query 1 # use `mysqltest1`; create table t13 select * from t1
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest1`; 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
master-bin.000001 # Query 1 # use `mysqltest1`; 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
master-bin.000001 # Query 1 # use `mysqltest1`; truncate table t2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f1 (x varchar(100)) returns int deterministic
begin
insert into t1 values(null,x);
return 1;
end
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic
begin
insert into t2 values(null,x);
return 1;
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` 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
master-bin.000001 # Intvar 1 # INSERT_ID=4
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f1`(_latin1'try_53_')
master-bin.000001 # Intvar 1 # INSERT_ID=5
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f2`(_latin1'try_54_')
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1 for each row
begin
insert into t2 values(null,"try_55_");
end
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t1 modify a int, drop primary key
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
master-bin.000001 # Intvar 1 # INSERT_ID=5
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_57_")
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t16` (
`UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
* 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
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_")
master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t11
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255))
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene')
master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t12
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
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
drop database mysqltest1;