mysql ha_err_key_not_found_[MySQL Patch]自动处理备库错误解决方案

备库因为某些错误停止时有发生,最常见的错误就是”HA_ERR_KEY_NOT_FOUND”和 “HA_ERR_FOUND_DUPP_KEY”.这既有可能是主备切换导致的,也可能是MySQL Bug导致的

通常有两种办法来处理备库错误:

1). 设置 “sql_slave_skip_counter”来忽略错误.

2).set slave_exec_mode = “idempotent”来处理 “HA_ERR_FOUND_DUPP_KEY” (overwritten the record) 和”HA_ERR_KEY_NOT_FOUND”(简单的忽略掉错误).

这两种方法都可能导致主备不一致

如果你使用的是innodb存储引擎,并且使用的是ROW模式复制,那我们就可以fix这个Bug。

很久之前我写了一个工具(http://code.google.com/p/relay-fetch/,下面的slave_error_handler文件夹)可以用来处理这个问题。

以下的patch则通过修改代码,为slave_exec_mode增加新的选项SMART,来自动处理。

思想很简单

1) HA_ERR_KEY_NOT_FOUND

UPDATE_ROWS_EVENT: 先写记录的’Before Image’ ,然后再update

DELETE_ROWS_EVENT: 先写后删 , 或者直接忽略错误

2)HA_ERR_FOUND_DUPP_KEY

WRITE_ROWS_EVENT: overwrite the record

对UPDATE_ROWS_EVENT导致的重复键错误暂不做处理。

以下patch基于Percona Server 5.5.18:

Index: /PS5518/branches/PS-r1086-slave-auto-fix/sql/log_event.cc

— /PS5518/branches/PS-r1086-slave-auto-fix/sql/log_event.cc (revision 1136)

+++ /PS5518/branches/PS-r1086-slave-auto-fix/sql/log_event.cc (revision 1180)

@@ -8750,6 +8750,7 @@

applying the event in the replace (idempotent) fashion.

*/

if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) ||

+ (slave_exec_mode == SLAVE_EXEC_MODE_SMART) ||

(m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER))

{

/*

@@ -8829,6 +8830,7 @@

m_table->next_number_field=0;

m_table->auto_increment_field_not_null= FALSE;

if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) ||

+ (slave_exec_mode == SLAVE_EXEC_MODE_SMART) ||

m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)

{

m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);

@@ -9124,7 +9126,9 @@

Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)

{

DBUG_ASSERT(m_table != NULL);

- int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);

+

+ int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT ||

+ slave_exec_mode == SLAVE_EXEC_MODE_SMART);

if (error && !thd->is_error())

{

@@ -9662,7 +9666,19 @@

Delete the record found, located in record[0]

*/

error= m_table->file->ha_delete_row(m_table->record[0]);

+ } else if ( (slave_exec_mode == SLAVE_EXEC_MODE_SMART) &&

+ (error == HA_ERR_KEY_NOT_FOUND)) {

+ tmp_disable_binlog(rli->sql_thd);

+ error = m_table->file->ha_write_row(m_table->record[0]) ||

+ m_table->file->rnd_pos_by_record(m_table->record[0]);

+

+ reenable_binlog(rli->sql_thd);

+ if (!error)

+ error = m_table->file->ha_delete_row(m_table->record[0]);

+ else

+ error = HA_ERR_KEY_NOT_FOUND;

}

+

return error;

}

@@ -9782,6 +9798,17 @@

int error= find_row(rli);

if (error)

{

+ if ((slave_exec_mode == SLAVE_EXEC_MODE_SMART) &&

+ (error == HA_ERR_KEY_NOT_FOUND)) {

+ tmp_disable_binlog(rli->sql_thd);

+ error = m_table->file->ha_write_row(m_table->record[0]) ||

+ m_table->file->rnd_pos_by_record(m_table->record[0]);

+ reenable_binlog(rli->sql_thd);

+ if (error)

+ error = HA_ERR_KEY_NOT_FOUND;

+ }

+

+ if (error) {

/*

We need to read the second image in the event of error to be

able to skip to the next pair of updates

@@ -9789,6 +9816,7 @@

m_curr_row= m_curr_row_end;

unpack_current_row(rli);

return error;

+ }

}

/*

Index: /PS5518/branches/PS-r1086-slave-auto-fix/sql/sql_class.h

— /PS5518/branches/PS-r1086-slave-auto-fix/sql/sql_class.h (revision 1136)

+++ /PS5518/branches/PS-r1086-slave-auto-fix/sql/sql_class.h (revision 1180)

@@ -90,6 +90,7 @@

enum enum_log_warnings_suppress { log_warnings_suppress_1592 };

enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,

SLAVE_EXEC_MODE_IDEMPOTENT,

+ SLAVE_EXEC_MODE_SMART,

SLAVE_EXEC_MODE_LAST_BIT};

enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY,

SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY};

Index: /PS5518/branches/PS-r1086-slave-auto-fix/sql/sys_vars.cc

— /PS5518/branches/PS-r1086-slave-auto-fix/sql/sys_vars.cc (revision 1136)

+++ /PS5518/branches/PS-r1086-slave-auto-fix/sql/sys_vars.cc (revision 1180)

@@ -1962,7 +1962,7 @@

DEFAULT(FALSE));

#ifdef HAVE_REPLICATION

-static const char *slave_exec_mode_names[]= {“STRICT”, “IDEMPOTENT”, 0};

+static const char *slave_exec_mode_names[]= {“STRICT”, “IDEMPOTENT”, “SMART”,0};

static Sys_var_enum Slave_exec_mode(

“slave_exec_mode”,

“Modes for how replication events should be executed. Legal values ”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值