0%

自动处理备库错误 [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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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 "

原创文章,转载请注明: 转载自Simple Life

本文链接地址: [MySQL Patch]自动处理备库错误