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#14615095 | Martin Skold | 6 Nov |