From: Date: October 20 2008 9:03pm Subject: bzr commit into mysql-5.1 branch (mats:2771) Bug#40004 List-Archive: http://lists.mysql.com/commits/56616 X-Bug: 40004 Message-Id: <20081020190312.BF35F469F5C@romeo> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/bzr/bugs/b40004-5.1-5.1.29-rc/ 2771 Mats Kindahl 2008-10-20 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. modified: mysql-test/extra/rpl_tests/rpl_row_basic.test mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result sql/log_event.cc sql/log_event_old.cc === modified file 'mysql-test/extra/rpl_tests/rpl_row_basic.test' --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-09-03 20:04:07 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-10-20 18:50:08 +0000 @@ -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; === modified file 'mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result' --- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-09-03 20:04:07 +0000 +++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-10-20 18:50:08 +0000 @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for ke 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; === modified file 'mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result' --- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-09-03 20:04:07 +0000 +++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-10-20 18:50:08 +0000 @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for ke 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; === modified file 'mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result' --- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2008-09-03 20:52:54 +0000 +++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2008-10-20 18:50:08 +0000 @@ -527,3 +527,60 @@ ERROR 23000: Duplicate entry '10' for ke 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; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2008-10-07 13:21:17 +0000 +++ b/sql/log_event.cc 2008-10-20 18:50:08 +0000 @@ -7203,6 +7203,9 @@ int Rows_log_event::do_apply_event(Relay 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 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 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 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_lo 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_lo 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 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 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 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 /* 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 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: === modified file 'sql/log_event_old.cc' --- a/sql/log_event_old.cc 2008-05-12 17:50:53 +0000 +++ b/sql/log_event_old.cc 2008-10-20 18:50:08 +0000 @@ -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 *tab 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 *tab /* 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 *tab 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(R 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 Rela 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 Rela 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 R 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 R 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 R 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 R /* 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);