From 2019f17276a3a3bb37f81824aa34b0428f5d8753 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Mon, 20 Oct 2008 20:50:08 +0200 Subject: [PATCH] Bug #40004 Replication failure with no PK + no indexes In certain situations, a scan of the table will return the error code HA_ERR_RECORD_DELETED, and this error code is not correctly caught in the Rows_log_event::find_row() function, which causes an error to be returned for this case. This patch fixes the problem by adding code to either ignore the record and continuing with the next one, the the event of a table scan, or change the error code to HA_ERR_KEY_NOT_FOUND, in the event that a key lookup is attempted. --- mysql-test/extra/rpl_tests/rpl_row_basic.test | 91 +++++++++++++++++++ .../suite/rpl/r/rpl_row_basic_2myisam.result | 57 ++++++++++++ .../suite/rpl/r/rpl_row_basic_3innodb.result | 57 ++++++++++++ .../suite/rpl_ndb/r/rpl_row_basic_7ndb.result | 57 ++++++++++++ sql/log_event.cc | 38 ++++++-- sql/log_event_old.cc | 47 ++++++++-- 6 files changed, 332 insertions(+), 15 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_row_basic.test b/mysql-test/extra/rpl_tests/rpl_row_basic.test index 7cfbcdb4437..3491fb903a0 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test @@ -471,3 +471,94 @@ source include/diff_tables.inc; connection master; drop table t1; sync_slave_with_master; + +# +# BUG#40004: Replication failure with no PK + no indexes +# + +connection master; + +eval CREATE TABLE t1 (a int) ENGINE=$type; + +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 2 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 5 ); + +UPDATE t1 SET a = 5 WHERE a = 9; +DELETE FROM t1 WHERE a < 6; +UPDATE t1 SET a = 9 WHERE a < 3; +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a < 4; +UPDATE t1 SET a = 8 WHERE a < 5; + +sync_slave_with_master; + +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +connection master; +drop table t1; +sync_slave_with_master; + +# +# Bug #39752: Replication failure on RBR + MyISAM + no PK +# + +connection master; + +--disable_warnings +eval CREATE TABLE t1 (a bit) ENGINE=$type; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3; +INSERT INTO t1 ( a ) VALUES ( 5 ); +DELETE FROM t1 WHERE a < 2 LIMIT 4; +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 9 ); +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 8 ); +UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0; +INSERT INTO t1 ( a ) VALUES ( 4 ); +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6; +DELETE FROM t1 WHERE a = 4 LIMIT 7; +UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9; +UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2; +DELETE FROM t1 WHERE a < 0 LIMIT 5; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8; +DELETE FROM t1 WHERE a < 8 LIMIT 8; +INSERT INTO t1 ( a ) VALUES ( 6 ); +DELETE FROM t1 WHERE a < 6 LIMIT 7; +UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7; +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 7 ); +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 7 ); +INSERT INTO t1 ( a ) VALUES ( 6 ); +UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4; +DELETE FROM t1 WHERE a = 2 LIMIT 9; +DELETE FROM t1 WHERE a = 1 LIMIT 4; +UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7; +INSERT INTO t1 ( a ) VALUES ( 0 ); +DELETE FROM t1 WHERE a < 3 LIMIT 0; +UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2; +INSERT INTO t1 ( a ) VALUES ( 1 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3; +--enable_warnings + +sync_slave_with_master; + +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +connection master; +drop table t1; +sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result index d9d96cf7eda..76ff8e15fdb 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY' INSERT INTO t1 VALUES (4); Comparing tables master:test.t1 and slave:test.t1 drop table t1; +CREATE TABLE t1 (a int) ENGINE='MYISAM' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 2 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 5 WHERE a = 9; +DELETE FROM t1 WHERE a < 6; +UPDATE t1 SET a = 9 WHERE a < 3; +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a < 4; +UPDATE t1 SET a = 8 WHERE a < 5; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; +CREATE TABLE t1 (a bit) ENGINE='MYISAM' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3; +INSERT INTO t1 ( a ) VALUES ( 5 ); +DELETE FROM t1 WHERE a < 2 LIMIT 4; +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 9 ); +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 8 ); +UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0; +INSERT INTO t1 ( a ) VALUES ( 4 ); +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6; +DELETE FROM t1 WHERE a = 4 LIMIT 7; +UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9; +UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2; +DELETE FROM t1 WHERE a < 0 LIMIT 5; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8; +DELETE FROM t1 WHERE a < 8 LIMIT 8; +INSERT INTO t1 ( a ) VALUES ( 6 ); +DELETE FROM t1 WHERE a < 6 LIMIT 7; +UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7; +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 7 ); +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 7 ); +INSERT INTO t1 ( a ) VALUES ( 6 ); +UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4; +DELETE FROM t1 WHERE a = 2 LIMIT 9; +DELETE FROM t1 WHERE a = 1 LIMIT 4; +UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7; +INSERT INTO t1 ( a ) VALUES ( 0 ); +DELETE FROM t1 WHERE a < 3 LIMIT 0; +UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2; +INSERT INTO t1 ( a ) VALUES ( 1 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result index 72c94ceb525..15673768180 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY' INSERT INTO t1 VALUES (4); Comparing tables master:test.t1 and slave:test.t1 drop table t1; +CREATE TABLE t1 (a int) ENGINE='INNODB' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 2 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 5 WHERE a = 9; +DELETE FROM t1 WHERE a < 6; +UPDATE t1 SET a = 9 WHERE a < 3; +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a < 4; +UPDATE t1 SET a = 8 WHERE a < 5; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; +CREATE TABLE t1 (a bit) ENGINE='INNODB' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3; +INSERT INTO t1 ( a ) VALUES ( 5 ); +DELETE FROM t1 WHERE a < 2 LIMIT 4; +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 9 ); +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 8 ); +UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0; +INSERT INTO t1 ( a ) VALUES ( 4 ); +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6; +DELETE FROM t1 WHERE a = 4 LIMIT 7; +UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9; +UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2; +DELETE FROM t1 WHERE a < 0 LIMIT 5; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8; +DELETE FROM t1 WHERE a < 8 LIMIT 8; +INSERT INTO t1 ( a ) VALUES ( 6 ); +DELETE FROM t1 WHERE a < 6 LIMIT 7; +UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7; +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 7 ); +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 7 ); +INSERT INTO t1 ( a ) VALUES ( 6 ); +UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4; +DELETE FROM t1 WHERE a = 2 LIMIT 9; +DELETE FROM t1 WHERE a = 1 LIMIT 4; +UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7; +INSERT INTO t1 ( a ) VALUES ( 0 ); +DELETE FROM t1 WHERE a < 3 LIMIT 0; +UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2; +INSERT INTO t1 ( a ) VALUES ( 1 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; diff --git a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result index 2538358b4d3..ac8ca2b3bcd 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for key 'PRIMARY' INSERT INTO t1 VALUES (4); Comparing tables master:test.t1 and slave:test.t1 drop table t1; +CREATE TABLE t1 (a int) ENGINE='NDB' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 2 ); +INSERT INTO t1 ( a ) VALUES ( 9 ); +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 5 WHERE a = 9; +DELETE FROM t1 WHERE a < 6; +UPDATE t1 SET a = 9 WHERE a < 3; +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a < 4; +UPDATE t1 SET a = 8 WHERE a < 5; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; +CREATE TABLE t1 (a bit) ENGINE='NDB' ; +INSERT IGNORE INTO t1 VALUES (NULL); +INSERT INTO t1 ( a ) VALUES ( 0 ); +UPDATE t1 SET a = 0 WHERE a = 1 LIMIT 3; +INSERT INTO t1 ( a ) VALUES ( 5 ); +DELETE FROM t1 WHERE a < 2 LIMIT 4; +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 9 ); +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 8 ); +UPDATE t1 SET a = 0 WHERE a < 6 LIMIT 0; +INSERT INTO t1 ( a ) VALUES ( 4 ); +INSERT INTO t1 ( a ) VALUES ( 3 ); +UPDATE t1 SET a = 0 WHERE a = 7 LIMIT 6; +DELETE FROM t1 WHERE a = 4 LIMIT 7; +UPDATE t1 SET a = 9 WHERE a < 2 LIMIT 9; +UPDATE t1 SET a = 0 WHERE a < 9 LIMIT 2; +DELETE FROM t1 WHERE a < 0 LIMIT 5; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 4 WHERE a < 6 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 5 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 8; +DELETE FROM t1 WHERE a < 8 LIMIT 8; +INSERT INTO t1 ( a ) VALUES ( 6 ); +DELETE FROM t1 WHERE a < 6 LIMIT 7; +UPDATE t1 SET a = 7 WHERE a = 3 LIMIT 7; +UPDATE t1 SET a = 8 WHERE a = 0 LIMIT 6; +INSERT INTO t1 ( a ) VALUES ( 7 ); +DELETE FROM t1 WHERE a < 9 LIMIT 4; +INSERT INTO t1 ( a ) VALUES ( 7 ); +INSERT INTO t1 ( a ) VALUES ( 6 ); +UPDATE t1 SET a = 8 WHERE a = 3 LIMIT 4; +DELETE FROM t1 WHERE a = 2 LIMIT 9; +DELETE FROM t1 WHERE a = 1 LIMIT 4; +UPDATE t1 SET a = 4 WHERE a = 2 LIMIT 7; +INSERT INTO t1 ( a ) VALUES ( 0 ); +DELETE FROM t1 WHERE a < 3 LIMIT 0; +UPDATE t1 SET a = 8 WHERE a = 5 LIMIT 2; +INSERT INTO t1 ( a ) VALUES ( 1 ); +UPDATE t1 SET a = 9 WHERE a < 5 LIMIT 3; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; diff --git a/sql/log_event.cc b/sql/log_event.cc index f91ebf3823f..0d03593946d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7203,6 +7203,9 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) error= do_exec_row(rli); + DBUG_PRINT("info", ("error: %s", HA_ERR(error))); + DBUG_ASSERT(error != HA_ERR_RECORD_DELETED); + table->in_use = old_thd; switch (error) { @@ -7218,11 +7221,13 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) case HA_ERR_TABLE_DEF_CHANGED: case HA_ERR_CANNOT_ADD_FOREIGN: - + which are not included into to the list. + + Note that HA_ERR_RECORD_DELETED is not in the list since + do_exec_row() should not return that error code. */ case HA_ERR_RECORD_CHANGED: - case HA_ERR_RECORD_DELETED: case HA_ERR_KEY_NOT_FOUND: case HA_ERR_END_OF_FILE: case HA_ERR_FOUND_DUPP_KEY: @@ -7231,7 +7236,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) case HA_ERR_NO_REFERENCED_ROW: case HA_ERR_ROW_IS_REFERENCED: - DBUG_PRINT("info", ("error: %s", HA_ERR(error))); if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) { if (global_system_variables.log_warnings) @@ -7254,7 +7258,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) m_curr_row_end. */ - DBUG_PRINT("info", ("error: %d", error)); DBUG_PRINT("info", ("curr_row: 0x%lu; curr_row_end: 0x%lu; rows_end: 0x%lu", (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end)); @@ -8269,6 +8272,8 @@ Rows_log_event::write_row(const Relay_log_info *const rli, if (error) { DBUG_PRINT("info",("rnd_pos() returns error %d",error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -8301,7 +8306,9 @@ Rows_log_event::write_row(const Relay_log_info *const rli, HA_READ_KEY_EXACT); if (error) { - DBUG_PRINT("info",("index_read_idx() returns error %d",error)); + DBUG_PRINT("info",("index_read_idx() returns %s", HA_ERR(error))); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -8574,6 +8581,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli) if (error) { DBUG_PRINT("info",("rnd_pos returns error %d",error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); } DBUG_RETURN(error); @@ -8633,6 +8642,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli) HA_READ_KEY_EXACT))) { DBUG_PRINT("info",("no record matching the key found in the table")); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); table->file->ha_index_end(); goto err; @@ -8690,8 +8701,11 @@ int Rows_log_event::find_row(const Relay_log_info *rli) 256U - (1U << table->s->last_null_bit_pos); } - if ((error= table->file->index_next(table->record[0]))) + while ((error= table->file->index_next(table->record[0]))) { + /* We just skip records that has already been deleted */ + if (error == HA_ERR_RECORD_DELETED) + continue; DBUG_PRINT("info",("no record matching the given row found")); table->file->print_error(error, MYF(0)); table->file->ha_index_end(); @@ -8722,14 +8736,22 @@ int Rows_log_event::find_row(const Relay_log_info *rli) /* Continue until we find the right record or have made a full loop */ do { + restart_rnd_next: error= table->file->rnd_next(table->record[0]); + DBUG_PRINT("info", ("error: %s", HA_ERR(error))); switch (error) { case 0: - case HA_ERR_RECORD_DELETED: break; + /* + If the record was deleted, we pick the next one without doing + any comparisons. + */ + case HA_ERR_RECORD_DELETED: + goto restart_rnd_next; + case HA_ERR_END_OF_FILE: if (++restart_count < 2) table->file->ha_rnd_init(1); @@ -8759,7 +8781,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) DBUG_DUMP("record found", table->record[0], table->s->reclength); table->file->ha_rnd_end(); - DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == HA_ERR_RECORD_DELETED || error == 0); + DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0); goto err; } ok: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index c6b99b1bd69..75aa8722aa9 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -556,6 +556,9 @@ replace_record(THD *thd, TABLE *table, error= table->file->rnd_pos(table->record[1], table->file->dup_ref); if (error) { + DBUG_PRINT("info",("rnd_pos() returns error %d",error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -582,6 +585,9 @@ replace_record(THD *thd, TABLE *table, HA_READ_KEY_EXACT); if (error) { + DBUG_PRINT("info", ("index_read_idx() returns error %d", error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -787,11 +793,14 @@ static int find_and_fetch_row(TABLE *table, uchar *key) 256U - (1U << table->s->last_null_bit_pos); } - if ((error= table->file->index_next(table->record[1]))) + while ((error= table->file->index_next(table->record[1]))) { - table->file->print_error(error, MYF(0)); + /* We just skip records that has already been deleted */ + if (error == HA_ERR_RECORD_DELETED) + continue; + table->file->print_error(error, MYF(0)); table->file->ha_index_end(); - DBUG_RETURN(error); + DBUG_RETURN(error); } } @@ -812,6 +821,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key) /* Continue until we find the right record or have made a full loop */ do { + restart_rnd_next: error= table->file->rnd_next(table->record[1]); DBUG_DUMP("record[0]", table->record[0], table->s->reclength); @@ -819,8 +829,14 @@ static int find_and_fetch_row(TABLE *table, uchar *key) switch (error) { case 0: + break; + + /* + If the record was deleted, we pick the next one without doing + any comparisons. + */ case HA_ERR_RECORD_DELETED: - break; + goto restart_rnd_next; case HA_ERR_END_OF_FILE: if (++restart_count < 2) @@ -1680,6 +1696,9 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) error= do_exec_row(rli); + DBUG_PRINT("info", ("error: %d", error)); + DBUG_ASSERT(error != HA_ERR_RECORD_DELETED); + table->in_use = old_thd; switch (error) { @@ -2100,6 +2119,8 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli, if (error) { DBUG_PRINT("info",("rnd_pos() returns error %d",error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -2132,7 +2153,9 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli, HA_READ_KEY_EXACT); if (error) { - DBUG_PRINT("info",("index_read_idx() returns error %d",error)); + DBUG_PRINT("info",("index_read_idx() returns error %d", error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); DBUG_RETURN(error); } @@ -2288,6 +2311,8 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) if (error) { DBUG_PRINT("info",("rnd_pos returns error %d",error)); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); } DBUG_RETURN(error); @@ -2347,6 +2372,8 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) HA_READ_KEY_EXACT))) { DBUG_PRINT("info",("no record matching the key found in the table")); + if (error == HA_ERR_RECORD_DELETED) + error= HA_ERR_KEY_NOT_FOUND; table->file->print_error(error, MYF(0)); table->file->ha_index_end(); DBUG_RETURN(error); @@ -2404,8 +2431,11 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) 256U - (1U << table->s->last_null_bit_pos); } - if ((error= table->file->index_next(table->record[0]))) + while ((error= table->file->index_next(table->record[0]))) { + /* We just skip records that has already been deleted */ + if (error == HA_ERR_RECORD_DELETED) + continue; DBUG_PRINT("info",("no record matching the given row found")); table->file->print_error(error, MYF(0)); table->file->ha_index_end(); @@ -2436,14 +2466,17 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) /* Continue until we find the right record or have made a full loop */ do { + restart_rnd_next: error= table->file->rnd_next(table->record[0]); switch (error) { case 0: - case HA_ERR_RECORD_DELETED: break; + case HA_ERR_RECORD_DELETED: + goto restart_rnd_next; + case HA_ERR_END_OF_FILE: if (++restart_count < 2) table->file->ha_rnd_init(1);