List:Commits« Previous MessageNext Message »
From:Martin Skold Date:November 1 2012 3:38pm
Subject:bzr push into mysql-5.1-telco-7.1 branch (Martin.Skold:4637 to 4640)
Bug#14615095
View as plain text  
 4640 Martin Skold	2012-11-01
      Bug#14615095  ERROR 839 'ILLEGAL NULL ATTRIBUTE' WHEN REPLAYING BINLOG: Added IgnoreError option when committing transactions during application of binlog statements to achieve same behavior as in the slave applier thread, added test cases

    modified:
      mysql-test/suite/ndb_binlog/r/ndb_binlog_variants.result
      mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.test
 4639 Martin Skold	2012-11-01
      Added option to specify specific binlog_file to wait for

    modified:
      mysql-test/include/wait_for_binlog_event.inc
 4638 Martin Skold	2012-11-01
      Bug#14615095  ERROR 839 'ILLEGAL NULL ATTRIBUTE' WHEN REPLAYING BINLOG: Added IgnoreError option when committing transactions during application of binlog statements to achieve same behavior as in the slave applier thread

    modified:
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster.h
 4637 Maitrayi Sabaratnam	2012-11-01 [merge]
      Merge 7.0->7.1

    modified:
      storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
=== modified file 'mysql-test/include/wait_for_binlog_event.inc'
--- a/mysql-test/include/wait_for_binlog_event.inc	2010-05-24 13:54:08 +0000
+++ b/mysql-test/include/wait_for_binlog_event.inc	2012-11-01 14:54:48 +0000
@@ -7,6 +7,7 @@
 # USAGE
 #
 #    let $wait_binlog_event= DROP;
+#    [let $binlog_file= master-bin.000001;]
 #    --source include/wait_for_binlog_event.inc
 
 let $_loop_count= 300;
@@ -22,12 +23,26 @@ while (`SELECT INSTR("$_last_event","$wa
     --die ERROR: failed while waiting for $wait_binlog_event in binlog 
   }
   real_sleep 0.1;
-  let $_event= query_get_value(SHOW BINLOG EVENTS, Info, $_event_pos);
+  if (!$binlog_file)
+  {
+    let $_event= query_get_value(SHOW BINLOG EVENTS, Info, $_event_pos);
+  }
+  if ($binlog_file)
+  {
+    let $_event= query_get_value(SHOW BINLOG EVENTS IN '$binlog_file', Info, $_event_pos);
+  }
   let $_last_event= $_event;
   while (`SELECT "$_event" != "No such row"`)
   {
     inc $_event_pos;
     let $_last_event= $_event;
-    let $_event= query_get_value(SHOW BINLOG EVENTS, Info, $_event_pos);
+    if (!$binlog_file)
+    {
+      let $_event= query_get_value(SHOW BINLOG EVENTS, Info, $_event_pos);
+    }
+    if ($binlog_file)
+    {
+      let $_event= query_get_value(SHOW BINLOG EVENTS IN '$binlog_file', Info, $_event_pos);
+    }
   }
 }

=== modified file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_variants.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_variants.result	2009-10-07 17:16:52 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_variants.result	2012-11-01 14:55:35 +0000
@@ -101,3 +101,82 @@ select * from bah order by tst;
 tst	cvy	sqs
 1	2	1
 drop table bah;
+reset master;
+show variables like '%log_update%';
+Variable_name	Value
+ndb_log_update_as_write	ON
+ndb_log_updated_only	ON
+sql_log_update	ON
+CREATE TABLE `t1` (
+`charId` varchar(60) NOT NULL,
+`enumId` enum('A','B','C') NOT NULL,
+`val` bigint(20) NOT NULL,
+`version` int(11) NOT NULL,
+PRIMARY KEY (`charId`,`enumId`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES ('', 'A', 0, 1);
+FLUSH LOGS;
+UPDATE t1 SET val = val + 1 WHERE charId = '';
+FLUSH LOGS;
+DELETE FROM t1 WHERE charId = '';
+FLUSH LOGS;
+Manually applying captured binlog
+select * from t1;
+charId	enumId	val	version
+drop table t1;
+reset master;
+show variables like '%log_update%';
+Variable_name	Value
+ndb_log_update_as_write	ON
+ndb_log_updated_only	ON
+sql_log_update	ON
+create table t1 (pk int not null primary key, name varchar(256)) engine = ndb;
+FLUSH LOGS;
+insert into t1 values (0, "zero"),(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five"),(6,"six"),(7,"seven"),(8,"eight"),(9,"nine");
+select * from t1 order by pk;
+pk	name
+0	zero
+1	one
+2	two
+3	three
+4	four
+5	five
+6	six
+7	seven
+8	eight
+9	nine
+update t1 set name = "even" where pk in (0,2,4,6,8);
+update t1 set name = "odd" where pk in (1,3,5,7,9);
+delete from t1 where name = "odd";
+select * from t1 order by pk;
+pk	name
+0	even
+2	even
+4	even
+6	even
+8	even
+FLUSH LOGS;
+truncate t1;
+insert into t1 values (0, "zero"),(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five"),(6,"six"),(7,"seven"),(8,"eight"),(9,"nine");
+select * from t1 order by pk;
+pk	name
+0	zero
+1	one
+2	two
+3	three
+4	four
+5	five
+6	six
+7	seven
+8	eight
+9	nine
+FLUSH LOGS;
+Manually applying captured binlog
+select * from t1 order by pk;
+pk	name
+0	even
+2	even
+4	even
+6	even
+8	even
+drop table t1;

=== modified file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.test'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.test	2011-05-13 07:40:50 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_variants.test	2012-11-01 14:55:35 +0000
@@ -214,3 +214,152 @@ let $MYSQLD_DATADIR= `select @@datadir;`
 select * from bah order by tst;
 
 drop table bah;
+
+# Bug #14615095   ERROR 839 'ILLEGAL NULL ATTRIBUTE' WHEN REPLAYING BINLOG
+# When applying WRITE_ROW events to tables where the rows are missing
+# any errors should be ignored
+
+connection mysqld1;
+reset master;
+show variables like '%log_update%';
+
+CREATE TABLE `t1` (
+   `charId` varchar(60) NOT NULL,
+   `enumId` enum('A','B','C') NOT NULL,
+   `val` bigint(20) NOT NULL,
+   `version` int(11) NOT NULL,
+   PRIMARY KEY (`charId`,`enumId`)
+  ) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+
+INSERT INTO t1 VALUES ('', 'A', 0, 1);
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until the INSERT statement is confirmed to have made it into the current binary log
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+UPDATE t1 SET val = val + 1 WHERE charId = '';
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until the UPDATE statement is confirmed to have made it into the current binary log
+--sleep 5
+--let $binlog_file=mysqld-bin.000002
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+DELETE FROM t1 WHERE charId = '';
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until the DELETE statement is confirmed to have made it into the current binary log
+--sleep 5
+--let $binlog_file=mysqld-bin.000003
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+# Now let's re-apply the binlog from the UPDATE
+# Without fix, this fails with 'Illegal null attribute'
+--echo Manually applying captured binlog
+--disable_query_log
+let $MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/mysqld-bin.000002 > $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
+--exec $MYSQL -uroot < $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
+
+--enable_query_log
+# Check that the table is still empty
+select * from t1;
+
+drop table t1;
+
+# Bug #14678088   CAN'T FIND RECORD IN
+# We need to be idempotent when applying binlog
+# test insert of existing row, update and delete
+# of non-existing row
+
+connection mysqld1;
+reset master;
+show variables like '%log_update%';
+
+create table t1 (pk int not null primary key, name varchar(256)) engine = ndb;
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until all statements are confirmed to have made it into the current binary log
+--let $binlog_file=mysqld-bin.000001
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+insert into t1 values (0, "zero"),(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five"),(6,"six"),(7,"seven"),(8,"eight"),(9,"nine");
+select * from t1 order by pk;
+
+update t1 set name = "even" where pk in (0,2,4,6,8);
+update t1 set name = "odd" where pk in (1,3,5,7,9);
+
+delete from t1 where name = "odd";
+
+select * from t1 order by pk;
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until all statements are confirmed to have made it into the current binary log
+--let $binlog_file=mysqld-bin.000002
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+truncate t1;
+insert into t1 values (0, "zero"),(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five"),(6,"six"),(7,"seven"),(8,"eight"),(9,"nine");
+select * from t1 order by pk;
+
+--disable_query_log
+# Add an event-stream marker
+create table stream_marker(a int) engine=ndb;
+drop table stream_marker;
+--let $wait_binlog_event=stream_marker
+--enable_query_log
+
+# Wait until all statements are confirmed to have made it into the current binary log
+--let $binlog_file=mysqld-bin.000003
+--source include/wait_for_binlog_event.inc
+FLUSH LOGS;
+
+# Now let's re-apply the binlog INSERT,UPDATE,DELETE
+# Without fix, this fails with 'Illegal null attribute'
+--echo Manually applying captured binlog
+--disable_query_log
+let $MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/mysqld-bin.000002 > $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
+--exec $MYSQL -uroot < $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
+
+--enable_query_log
+select * from t1 order by pk;
+
+drop table t1;
+
+

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2012-06-14 11:48:36 +0000
+++ b/sql/ha_ndbcluster.cc	2012-11-01 14:52:55 +0000
@@ -4082,27 +4082,6 @@ ha_ndbcluster::eventSetAnyValue(THD *thd
 #endif
 }
 
-bool ha_ndbcluster::isManualBinlogExec(THD *thd)
-{
-  /* Are we executing handler methods as part of 
-   * a mysql client BINLOG statement?
-   */
-#ifndef EMBEDDED_LIBRARY
-  return thd ? 
-    ( thd->rli_fake? 
-      ndb_mi_get_in_relay_log_statement(thd->rli_fake) : false)
-    : false;
-#else
-  /* For Embedded library, we can't determine if we're
-   * executing Binlog manually
-   * TODO : Find better way to determine whether to use
-   *        SQL REPLACE or Write_row semantics
-   */
-  return false;
-#endif
-
-}
-
 static inline bool
 thd_allow_batch(const THD* thd)
 {
@@ -4703,15 +4682,7 @@ int ha_ndbcluster::ndb_write_row(uchar *
      * to avoid trampling unchanged columns when an update is
      * logged as a WRITE
      */
-    bool useWriteSet= isManualBinlogExec(thd);
-
-#ifdef HAVE_NDB_BINLOG
-    /* Slave always uses writeset
-     * TODO : What about SBR replicating a
-     * REPLACE command?
-     */
-    useWriteSet |= thd->slave_thread;
-#endif
+    bool useWriteSet= applying_binlog(thd);
     uchar* mask;
 
     if (useWriteSet)
@@ -5153,7 +5124,7 @@ int ha_ndbcluster::exec_bulk_update(uint
       DBUG_RETURN(ndb_err(trans));
     }
     THD *thd= table->in_use;
-    if (!thd->slave_thread)
+    if (!applying_binlog(thd))
     {
       DBUG_PRINT("info", ("ignore_count: %u", ignore_count));
       assert(m_rows_changed >= ignore_count);
@@ -5197,7 +5168,7 @@ int ha_ndbcluster::exec_bulk_update(uint
     no_uncommitted_rows_execute_failure();
     DBUG_RETURN(ndb_err(trans));
   }
-  if (!thd->slave_thread)
+  if (!applying_binlog(thd))
   {
     assert(m_rows_changed >= ignore_count);
     assert(m_rows_updated >= ignore_count);
@@ -5522,7 +5493,7 @@ int ha_ndbcluster::ndb_update_row(const 
   m_rows_changed++;
   m_rows_updated++;
 
-  if (!thd->slave_thread)
+  if (!applying_binlog(thd))
   {
     assert(m_rows_changed >= ignore_count);
     assert(m_rows_updated >= ignore_count);
@@ -5583,7 +5554,7 @@ int ha_ndbcluster::end_bulk_delete()
       DBUG_RETURN(ndb_err(trans));
     }
     THD *thd= table->in_use;
-    if (!thd->slave_thread)
+    if (!applying_binlog(thd))
     {
       DBUG_PRINT("info", ("ignore_count: %u", ignore_count));
       assert(m_rows_deleted >= ignore_count);
@@ -5625,7 +5596,7 @@ int ha_ndbcluster::end_bulk_delete()
     DBUG_RETURN(ndb_err(trans));
   }
 
-  if (!thd->slave_thread)
+  if (!applying_binlog(thd))
   {
     assert(m_rows_deleted >= ignore_count);
     m_rows_deleted-= ignore_count;
@@ -5835,7 +5806,7 @@ int ha_ndbcluster::ndb_delete_row(const 
   }
   if (!primary_key_update)
   {
-    if (!thd->slave_thread)
+    if (!applying_binlog(thd))
     {
       assert(m_rows_deleted >= ignore_count);
       m_rows_deleted-= ignore_count;
@@ -6801,8 +6772,11 @@ int ha_ndbcluster::extra(enum ha_extra_f
   case HA_EXTRA_WRITE_CAN_REPLACE:
     DBUG_PRINT("info", ("HA_EXTRA_WRITE_CAN_REPLACE"));
     if (!m_has_unique_index ||
-        current_thd->slave_thread || /* always set if slave, quick fix for bug 27378 */
-        isManualBinlogExec(current_thd)) /* or if manual binlog application, for bug 46662 */
+        /* 
+           Always set if slave, quick fix for bug 27378
+           or if manual binlog application, for bug 46662
+        */
+        applying_binlog(current_thd))
     {
       DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
       m_use_write= TRUE;
@@ -7200,6 +7174,13 @@ static void transaction_checks(THD *thd,
     THDVAR(thd, optimized_node_selection)=
       THDVAR(NULL, optimized_node_selection) & 1; /* using global value */
   }
+#ifndef EMBEDDED_LIBRARY
+  bool applying_binlog=
+    thd->rli_fake? 
+    ndb_mi_get_in_relay_log_statement(thd->rli_fake) : false;
+  if (applying_binlog)
+    thd_ndb->trans_options|= TNTO_APPLYING_BINLOG;
+#endif
 }
 
 int ha_ndbcluster::start_statement(THD *thd,
@@ -7660,7 +7641,6 @@ ha_ndbcluster::start_transaction_part_id
   DBUG_RETURN(NULL);
 }
    
-
 /**
   Commit a transaction started in NDB.
 */
@@ -7753,7 +7733,10 @@ int ndbcluster_commit(handlerton *hton, 
       }
     }
     else
-      res= execute_commit(thd, thd_ndb, trans, THDVAR(thd, force_send), FALSE);
+    {
+      bool applying_binlog= (thd_ndb->trans_options & TNTO_APPLYING_BINLOG);
+      res= execute_commit(thd, thd_ndb, trans, THDVAR(thd, force_send), applying_binlog);
+    }
   }
 
   if (res != 0)

=== modified file 'sql/ha_ndbcluster.h'
--- a/sql/ha_ndbcluster.h	2012-06-14 11:48:36 +0000
+++ b/sql/ha_ndbcluster.h	2012-11-01 14:52:55 +0000
@@ -274,6 +274,7 @@ enum THD_NDB_TRANS_OPTIONS
   TNTO_INJECTED_APPLY_STATUS= 1 << 0
   ,TNTO_NO_LOGGING=           1 << 1
   ,TNTO_TRANSACTIONS_OFF=     1 << 2
+  ,TNTO_APPLYING_BINLOG=      1 << 3
 };
 
 struct Ndb_local_table_statistics {
@@ -721,8 +722,6 @@ private:
                                   ulonglong *nb_reserved_values);
   bool uses_blob_value(const MY_BITMAP *bitmap) const;
 
-  static inline bool isManualBinlogExec(THD *thd);
-
   char *update_table_comment(const char * comment);
 
   int write_ndb_file(const char *name);
@@ -882,6 +881,21 @@ private:
   int update_stats(THD *thd, bool do_read_stat, bool have_lock= FALSE,
                    uint part_id= ~(uint)0);
   int add_handler_to_open_tables(THD*, Thd_ndb*, ha_ndbcluster* handler);
+
+  /*
+    Check if we are applying a binlog, either as a slave or
+    by applying BINLOG statements (from mysqlbinlog command line tool)
+  */
+  bool applying_binlog(THD* thd)
+  { 
+    return 
+#ifdef HAVE_NDB_BINLOG
+      thd->slave_thread ||
+#endif
+      m_thd_ndb->trans_options & TNTO_APPLYING_BINLOG;
+  };
+
+
 };
 
 int ndbcluster_discover(THD* thd, const char* dbname, const char* name,

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.1 branch (Martin.Skold:4637 to 4640)Bug#14615095Martin Skold6 Nov