summaryrefslogtreecommitdiff
path: root/sql/log_event.cc
diff options
context:
space:
mode:
authorMats Kindahl <mats@sun.com>2008-10-20 20:50:08 +0200
committerMats Kindahl <mats@sun.com>2008-10-20 20:50:08 +0200
commit2019f17276a3a3bb37f81824aa34b0428f5d8753 (patch)
tree5b729a02dec3bf0259864c4d2d110a365a74a42c /sql/log_event.cc
parent0c20c0f12ff15601e23bd45bcda70317a59d9380 (diff)
downloadmariadb-git-2019f17276a3a3bb37f81824aa34b0428f5d8753.tar.gz
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.
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r--sql/log_event.cc38
1 files changed, 30 insertions, 8 deletions
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: