List:Internals« Previous MessageNext Message »
From:guilhem Date:September 13 2005 5:18pm
Subject:bk commit into 5.0 tree (guilhem:1.1967) BUG#13090
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of guilhem. When guilhem does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1967 05/09/13 19:18:51 guilhem@stripped +8 -0
  WL#1012: Fix for BUG#13090 "rbr slave crashes at end of rpl_insert_id, rpl_insert_ignore":
  slave was not calling ha_autocommit_or_rollback() which is needed if working in autocommit mode
  (only this statement, and not ha_commit(), will cause binlog cache to be flushed, the assertion
  was because binlog cache was not flushed).
  Fix to rpl_row_func003.test (properly dropping table at start).
  Some tests known to fail still do: rpl_multi_delete, rpl_row_view, rpl_row_basic_2myisam

  wl1012-review-pending-comments.txt
    1.4 05/09/13 19:18:47 guilhem@stripped +5 -10
    making TODO up-to-date

  sql/sql_class.cc
    1.208 05/09/13 19:18:47 guilhem@stripped +8 -10
    In THD::end_statement(), always call binlog_flush_pending_rows_event() (see comments).

  sql/log_event.cc
    1.201 05/09/13 19:18:47 guilhem@stripped +60 -22
    In Rows_log_event::exec_event(), ha_commit() is not enough because we may be working in autocommit mode;
    adding ha_autocommit_or_rollback(), and ha_commit() becomes unnecessary (as Xid_log_event::exec_event()
    will follow if needed).

  mysql-test/t/rpl_row_func003.test
    1.6 05/09/13 19:18:47 guilhem@stripped +1 -2
    Imagine that when test starts, function exists on master but not on slave, then test will fail. Use IF EXISTS to avoid that.

  mysql-test/t/ps_grant.test
    1.9 05/09/13 19:18:47 guilhem@stripped +0 -11
    these lines are removed in the main tree so let's remove them here too (a merge must have failed one day).

  mysql-test/r/rpl_row_max_relay_size.result
    1.3 05/09/13 19:18:47 guilhem@stripped +5 -5
    it's a row-based test, 800 INSERT statements generate 55k binlog, more realistic than 4k.

  mysql-test/r/rpl_row_func003.result
    1.2 05/09/13 19:18:47 guilhem@stripped +1 -1
    result update

  mysql-test/r/ps_grant.result
    1.11 05/09/13 19:18:47 guilhem@stripped +0 -5
    result update

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	guilhem
# Host:	gbichot3.local
# Root:	/home/mysql_src/mysql-5.0-wl1012

--- 1.200/sql/log_event.cc	2005-09-12 01:11:56 +02:00
+++ 1.201/sql/log_event.cc	2005-09-13 19:18:47 +02:00
@@ -5163,6 +5163,19 @@
 		      get_type_str(), table->s->db, table->s->table_name);
  
     rli->m_table_map.clear_tables();
+    /*
+      We do the two next calls to be sure to rollback whether it was
+      autocommit or in a transaction.
+      If one day we honour --skip-slave-errors in row-based replication, and
+      the error should be skipped, then we would clear mappings, rollback,
+      close tables, but the slave SQL thread would not stop and then may
+      assume the mapping is still available, the tables are still open...
+      To fix this we should detect skippability of error in the "if (error)"
+      above, and not later. So that we don't delete needed information.
+      For now we code, knowing that error is not skippable and so slave SQL
+      thread is certainly going to stop.
+    */
+    ha_autocommit_or_rollback(thd, error);
     ha_rollback(thd);
     close_thread_tables(thd);
     thd->query_error= 1;
@@ -5187,8 +5200,28 @@
     */
     rli->m_table_map.clear_tables();
 
-    error= ha_commit(thd);
-    close_thread_tables(thd);
+    /*
+      If this event is not in a transaction, the call below will, if some
+      transactional storage engines are involved, commit the statement into
+      them and flush the pending event to binlog.
+      If this event is in a transaction, the call will do nothing, but a
+      Xid_log_event will come next which will, if some transactional engines
+      are involved, commit the transaction and flush the pending event to the
+      binlog.
+    */
+    error= ha_autocommit_or_rollback(thd, 0);
+    /*
+      Now what if this is not a transactional engine? we still need to flush
+      the pending event to the binlog (that's what THD::end_statement() is
+      for when it executes a query); we do it below. Note that we imitate what
+      is done for real queries: a call to ha_autocommit_or_rollback()
+      (sometimes only if involves a transactional engine), and a call to be
+      sure to have the pending event flushed (like THD::end_statement at end
+      of mysql_parse()).
+    */
+    thd->binlog_flush_pending_rows_event(true);
+    
+    close_thread_tables(thd); // unlocks and closes tables
     rli->transaction_end(thd);
 
     if (error == 0)
@@ -5201,31 +5234,36 @@
     {
       slave_print_error(rli, error, 
 			"Error in %s event: commit of row events failed, "
-			"table %s.%s",
+			"table `%s`.`%s`",
 			get_type_str(), table->s->db, table->s->table_name);
     }
     DBUG_RETURN(error);
   }
 
-  if (thd->lock)
-  {
-    /* if transactional... */
-    error= ha_autocommit_or_rollback(thd,error);
-    mysql_unlock_tables(thd, thd->lock);
-    thd->lock=0;
-    if (unlikely(error))
-    {
-      slave_print_error(rli, error, 
-			"Error in %s event: autocommit or rollback of "
-			"row events failed for table %s.%s",
-			get_type_str(), table->s->db, table->s->table_name);
-      thd->query_error= 1;
-      rli->m_table_map.clear_tables();
-      close_thread_tables(thd);
-      DBUG_RETURN(error);
-    }
-  }
-    
+  /*
+    We did a lock_tables(), without any prior LOCK TABLES and are not in
+    prelocked mode, so this assertion should be true.
+  */
+  DBUG_ASSERT(thd->lock);
+  /*
+    If we are here, there are more events to come which may use our mappings
+    and our table. So don't clear mappings or close tables, just unlock
+    tables.
+    Why don't we lock the table once for all in
+    Table_map_log_event::exec_event() ? Because we could have in binlog:
+    BEGIN;
+    Table_map t1 -> 1
+    Write_rows to id 1
+    Table_map t2 -> 2
+    Write_rows to id 2
+    Xid_log_event
+    So we cannot lock t1 when executing the first Table_map, because at that
+    moment we don't know we'll also have to lock t2, and all tables must be
+    locked at once in MySQL.
+  */
+  mysql_unlock_tables(thd, thd->lock);
+  thd->lock= 0;
+
   DBUG_ASSERT(error == 0);
   rli->inc_event_relay_log_pos();
 

--- 1.207/sql/sql_class.cc	2005-09-10 13:42:31 +02:00
+++ 1.208/sql/sql_class.cc	2005-09-13 19:18:47 +02:00
@@ -1594,18 +1594,16 @@
   lex->result= 0;
   /* Note that free_list is freed in cleanup_after_query() */
 
+#if !defined(MYSQL_CLIENT) && defined(HAVE_ROW_BASED_REPLICATION)
   /*
-    Flush the pending binlog rows event to the binlog if we are *not* in a
-    transaction (otherwise, the pending event will already have been
-    flushed before).
+    Flush the pending binlog rows event to the binlog.
+    If the command was a COMMIT (or a DDL having an implicit commit), this is
+    going to do nothing (because then the pending event has already been
+    flushed by COMMIT) but here there is no easy way to know if it was a
+    COMMIT or a DDL with implicit commit (e.g. OPTION_BEGIN is gone at this
+    moment)... So we call it anyway.
   */
-#if !defined(MYSQL_CLIENT)
-  if (!(options & OPTION_BEGIN)) // TODO not a good test
-  {
-#ifdef HAVE_ROW_BASED_REPLICATION
-    binlog_flush_pending_rows_event(true);
-#endif
-  }
+  binlog_flush_pending_rows_event(true);
 #endif
 
   /*

--- 1.3/wl1012-review-pending-comments.txt	2005-09-09 00:13:57 +02:00
+++ 1.4/wl1012-review-pending-comments.txt	2005-09-13 19:18:47 +02:00
@@ -1432,7 +1432,7 @@
 [M] We cannot lock tables when we see the table map event, since these
 [M] are generated on a need-to-have basis.
 
-[G2TODO] I have to think about it
+[G2DONE] Made modifications, see the posts in BUG#13090.
 
 > +    /* if transactional... */
 > +    error= ha_autocommit_or_rollback(thd,error);
@@ -3647,7 +3647,7 @@
 [G] There can be a transaction without OPTION_BEGIN: with
 [G] OPTION_NO_AUTOCOMMIT. 
 
-[G2TODO]
+[G2DONE] removed if(), added comments, in a fix for BUG#13090.
 
 > @@ -1775,3 +1794,490 @@
 >  {
@@ -9790,11 +9790,6 @@
 [G2TODO] fix BUG#12352, BUG#12326, BUG#12134, etc etc (all those
 [G2TODO] assigned to Lars)
 
-[G2TODO] review all testcase changes
-
--- 
-   __  ___     ___ ____  __
-  /  |/  /_ __/ __/ __ \/ /    Mr. Guilhem Bichot <guilhem@stripped>
- / /|_/ / // /\ \/ /_/ / /__   MySQL AB, Full-Time Software Developer
-/_/  /_/\_, /___/\___\_\___/   Bordeaux, France
-       <___/   www.mysql.com   
+[G2TODO] review all testcase changes, make sure no existing rpl* test
+[G2TODO] has been suppressed before the final push (currently this is
+[G2TODO] unfortunately the case in mysql-5.0-wl1012.

--- 1.10/mysql-test/r/ps_grant.result	2005-08-11 10:09:55 +02:00
+++ 1.11/mysql-test/r/ps_grant.result	2005-09-13 19:18:47 +02:00
@@ -88,8 +88,3 @@
 prepare stmt3 from ' drop user drop_user@localhost ';
 ERROR HY000: This command is not supported in the prepared statement protocol yet
 drop user drop_user@localhost;
-prepare stmt4 from ' show full processlist ';
-execute stmt4;
-Id	User	Host	db	Command	Time	State	Info
-number	root	localhost	test	Execute	time	NULL	show full processlist
-deallocate prepare stmt4;

--- 1.8/mysql-test/t/ps_grant.test	2005-09-11 00:37:55 +02:00
+++ 1.9/mysql-test/t/ps_grant.test	2005-09-13 19:18:47 +02:00
@@ -129,14 +129,3 @@
 --error 1295
 prepare stmt3 from ' drop user drop_user@localhost ';
 drop user drop_user@localhost;
-
-# This test must be the last one, otherwise it may produce extra
-# rows in the processlist under high load.
-# Tested here simply so it is not tested with embedded server
---disable_query_log
-sleep 4;
---enable_query_log
-prepare stmt4 from ' show full processlist ';
---replace_column 1 number 6 time 3 localhost
-execute stmt4;
-deallocate prepare stmt4;

--- 1.1/mysql-test/r/rpl_row_func003.result	2005-08-25 12:47:52 +02:00
+++ 1.2/mysql-test/r/rpl_row_func003.result	2005-09-13 19:18:47 +02:00
@@ -4,7 +4,7 @@
 reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 start slave;
-DROP FUNCTION test.f1;
+DROP FUNCTION IF EXISTS test.f1;
 DROP TABLE IF EXISTS test.t1;
 CREATE TABLE test.t1 (a INT NOT NULL AUTO_INCREMENT, c CHAR(16),PRIMARY KEY(a))ENGINE=INNODB;
 create function test.f1() RETURNS CHAR(16) 

--- 1.5/mysql-test/t/rpl_row_func003.test	2005-08-31 05:23:53 +02:00
+++ 1.6/mysql-test/t/rpl_row_func003.test	2005-09-13 19:18:47 +02:00
@@ -26,8 +26,7 @@
 # Begin clean up test section
 connection master;
 --disable_warnings
---error 0,1305
-DROP FUNCTION test.f1;
+DROP FUNCTION IF EXISTS test.f1;
 DROP TABLE IF EXISTS test.t1;
 
 --enable_warnings

--- 1.2/mysql-test/r/rpl_row_max_relay_size.result	2005-08-13 14:02:27 +02:00
+++ 1.3/mysql-test/r/rpl_row_max_relay_size.result	2005-09-13 19:18:47 +02:00
@@ -16,7 +16,7 @@
 start slave;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	4520	#	#	master-bin.000001	Yes	Yes				#			0		0	4520	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	55464	#	#	master-bin.000001	Yes	Yes				#			0		0	55464	#	None		0	No						#
 stop slave;
 reset slave;
 set global max_relay_log_size=(5*4096);
@@ -26,7 +26,7 @@
 start slave;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	4520	#	#	master-bin.000001	Yes	Yes				#			0		0	4520	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	55464	#	#	master-bin.000001	Yes	Yes				#			0		0	55464	#	None		0	No						#
 stop slave;
 reset slave;
 set global max_relay_log_size=0;
@@ -36,7 +36,7 @@
 start slave;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	4520	#	#	master-bin.000001	Yes	Yes				#			0		0	4520	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	55464	#	#	master-bin.000001	Yes	Yes				#			0		0	55464	#	None		0	No						#
 stop slave;
 reset slave;
 flush logs;
@@ -49,12 +49,12 @@
 create table t1 (a int);
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	4606	#	#	master-bin.000001	Yes	Yes				#			0		0	4606	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	55550	#	#	master-bin.000001	Yes	Yes				#			0		0	55550	#	None		0	No						#
 flush logs;
 drop table t1;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	4682	#	#	master-bin.000001	Yes	Yes				#			0		0	4682	#	None		0	No						#
+#	127.0.0.1	root	MASTER_PORT	1	master-bin.000001	55626	#	#	master-bin.000001	Yes	Yes				#			0		0	55626	#	None		0	No						#
 flush logs;
 show master status;
 File	Position	Binlog_Do_DB	Binlog_Ignore_DB
Thread
bk commit into 5.0 tree (guilhem:1.1967) BUG#13090guilhem13 Sep