常见的MySQL Replication Error
现在不少公司都在用MySQL(master)-->MySQL(slave)的框架,当然也有一主多从的架构,这也是MySQL主从的一个延伸架构;当然也有的公司MySQL主主的架构,MySQL主主架构要是处理得不适当,会面临各种各样的问题,当然啦,每种数据库构架都有自己的优缺点,合适自己公司业务需求的且方便自己维护的架构都可以认为是理想的构架,当出现同步断开了,我们是不是一味的使用--slave-skip-errors=[error_code]来跳过错误代码呢?其实不是的,这样做可能会造成数据不一致的可能,下面我只针对MySQL Replication常见的错误进行说明及处理。
一、在master上更新一条记录时出现的故障(master与slave处理同步的情况下,binlog为row格式)
在slave库上,模拟slave少了一条数据,所以把id=6的记录在slave上先delete掉:
root@mysql-slave> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 6 | aa | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
4 rows in set (0.00 sec) root@mysql-slave> delete from test where id=6;
Query OK, 1 row affected (0.00 sec)
然后在master上更新id为6的记录:
root@mysql-master> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec) root@mysql-master> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 6 | aa | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
4 rows in set (0.00 sec) root@mysql-master> update test set name='AA' where id=6;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
root@mysql-master>
回slave库看下同步状态是否正常:
Replicate_Wild_Ignore_Table:
Last_Errno: 1032
Last_Error: Could not execute Update_rows event on table xuanzhi.test; Can't find record in 'test', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000004, end_log_pos 3704
Skip_Counter: 0
Exec_Master_Log_Pos: 3529
Relay_Log_Space: 4183
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Update_rows event on table xuanzhi.test; Can't find record in 'test', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000004, end_log_pos 3704
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec) root@mysql-slave>
可以看到,同步已经断开,根据slave的报错信息去查看master的binlog到底做了什么,从上面看现在master做的操作写的binlog是mysql-bin.000004,end_log_pos=3704
[root@localhost ~]# /usr/local/services/mysql/bin/mysqlbinlog -v --base64-output=DECODE-ROWS /data/mysql/data/mysql-bin. | grep -A ''
# :: server id end_log_pos Update_rows: table id flags: STMT_END_F
### UPDATE xuanzhi.test
### WHERE
### @=
### @='aa'
### @=
### SET
### @=
### @='AA'
### @=
# at
# :: server id end_log_pos Xid =
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
[root@localhost ~]#
可以看到做了更新的操作UPDATE xuanzhi.test where id=6的操作,我们在slave库上查看id为6的记录:
root@mysql-slave> select * from xuanzhi.test where id=6;
Empty set (0.00 sec) root@mysql-slave>
可以看到slave库上并没存在这样的记录。我们回到master查看下id=6的记录:
root@mysql-master> select * from xuanzhi.test where id=6;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 6 | AA | 10002011 |
+----+------+----------+
1 row in set (0.00 sec) root@mysql-master>
下面我们要解决同步问题呢?操作如下:把丢失的数据补到slave上:
root@mysql-slave> stop slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> insert into test (id,name,code) values (6,'AA',10002011);
Query OK, 1 row affected (0.00 sec) root@mysql-slave> start slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.132
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 3731
Relay_Log_File: localhost-relay-bin.000004
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
正常同步了。如果有N多数据缺失,得用pt-table-checksum校验数据一致性,很多同学会好奇为什么slave库上会少数据呢?我总结了以下几种情况,当然还有别的:
1、当人为设置set session sql_log_bin=0时,当前session操作是不记录到Binlog的。
2、就是slave没设置为read only,在slave库上有删除操作
3、slave读取master的binlog日志后,需要落地3个文件:relay log、relay log info、master info,这三个文件如果不及时落地,则主机crash后会导致数据的不一致
二、估计比较常见的一种错误,就是错误代码为1062的错误,主键冲突
在slave上添加一条记录,模拟slave上还存在旧的数据记录,此时master是没有的这条记录的(这里的id自增主键)
root@mysql-slave> insert into test value (5,'zz',10002010);
Query OK, 1 row affected (0.00 sec) root@mysql-slave> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 5 | zz | 10002010 |
| 6 | AA | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
5 rows in set (0.00 sec) root@mysql-slave>
在master上操作,添加一条id为5的记录:
root@mysql-master> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 6 | AA | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
5 rows in set (0.00 sec) root@mysql-master> insert into test value (5,'ZZ',10002010);
Query OK, 1 row affected (0.00 sec)
回到slave库查看同步状态:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table xuanzhi.test; Duplicate entry '' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 3893
Skip_Counter: 0
Exec_Master_Log_Pos: 3731
Relay_Log_Space: 2322
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1062
Last_SQL_Error: Could not execute Write_rows event on table xuanzhi.test; Duplicate entry '5' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 3893
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec) root@mysql-slave>
可以看到提示1062主键冲突错误,在表xuanzhi.test上,那么,此时我们应该考虑以谁的数据为准?我们当然要以master库的数据为准啦,所以我们需要把slave上主键为5的记录给删除掉,删除前要先desc查看表结构确定自增主键在什么列:
root@mysql-slave> stop slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> desc xuanzhi.test;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | char(10) | YES | | NULL | |
| code | int(20) | YES | | NULL | |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec) root@mysql-slave> delete from xuanzhi.test where id=5;
Query OK, 1 row affected (0.00 sec) root@mysql-slave> start slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.132
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 3920
Relay_Log_File: localhost-relay-bin.000005
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
嘻嘻,有人会想,如果有N多主键冲突,这样手动清除冲突的记录有点不科学,是的,所以我写了写脚本去清除,可以参考我写的主从复制1062错误的解决方法。有人会好其,这样删除后,启动同步线程,记录还会不会同步过来呢,答案是会的
root@mysql-slave> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 5 | ZZ | 10002010 |
| 6 | AA | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
5 rows in set (0.00 sec) root@mysql-slave>
可以看到主键值为5的记录被同步过来了。当备库在一次非计划的关闭后重启时,会去读master.info文件以找到上次停止复制的位置。不幸的是,该文件可能并没有同步写到磁盘,因为该信息是在缓存中,可能并没有刷新到磁盘文件master.info。文件中存储的信息可能是错误的,备库可能会尝试重新执行一些二进制日志事件,这可能导致主键冲突,就是我们常常看见的1062错误。除非能确定备库在哪里停止(很难),否则唯一的办法就是忽略那些错误。
三、master上删除一条记录时出现的故障。
在master上删除一条记录,但这条记录在slave库上并不存在的时候,同步会不会断开,下面我们瞧瞧看:
在slave上delete一条数据,模拟slave比master少了数据:
root@mysql-slave> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 5 | ZZ | 10002010 |
| 6 | AA | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
5 rows in set (0.00 sec) root@mysql-slave> delete from test where id=5;
Query OK, 1 row affected (0.00 sec) root@mysql-slave>
在master上进行dalete行记录的操作,此时的slave是不存在这条记录了的:
root@mysql-master> select * from test;
+----+------+----------+
| id | name | code |
+----+------+----------+
| 5 | ZZ | 10002010 |
| 6 | AA | 10002011 |
| 7 | bb | 10002012 |
| 8 | cc | 10002013 |
| 9 | dd | 10002014 |
+----+------+----------+
5 rows in set (0.00 sec) root@mysql-master> delete from test where id = 5;
Query OK, 1 row affected (0.00 sec)
回到slave库查看下状态,同步已经断开:
Replicate_Wild_Ignore_Table:
Last_Errno: 1032
Last_Error: Could not execute Delete_rows event on table xuanzhi.test; Can't find record in 'test', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000004, end_log_pos 4082
Skip_Counter: 0
Exec_Master_Log_Pos: 3920
Relay_Log_Space: 937
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table xuanzhi.test; Can't find record in 'test', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000004, end_log_pos 4082
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec) root@mysql-slave>
我们分析错误信息可以看到关键字是Delete_rows,这样处理就很简单了,因为master库是删除数据操作,所以slave库上没这条数据也没关系,所以在slave库上跳过此错误即可(当出现这种情况,就应该引起注意了,应该去检查是否还有更多的数据丢失了)
root@mysql-slave> stop slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> set global sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> start slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.132
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 4109
Relay_Log_File: localhost-relay-bin.000006
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
可以看到同步正常了。你在master上delete一条master都没有记录,同步是不会断开的。
四、slave的中继日志relay-log损坏
现在模拟slave库down机,relay-log损坏了,同步无法正常:
断电后启动slave库后,执行slave start后查看状态会报日志读不了或者损坏(有时直接断电slave并不一定损坏或者掉数据,如果配置参数合理的话):
root@mysql- show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.132
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000006
Read_Master_Log_Pos: 401269011
Relay_Log_File: localhost-relay-bin.000010
Relay_Log_Pos: 439914363
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1594
Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
Skip_Counter: 0
Exec_Master_Log_Pos: 590788350
Relay_Log_Space: 2398604371
show slave status几个重要参数说明:
Slave_IO_Running: 接收master的binlog信息
Master_Log_File: 正在云读取master上binlog日志名
Read_master_Log_Pos: 正在读取master上当前的binlog日志POS点
slave_SQL_Running: 执行写操作。
Relay_master_Log_File: 正在同步master上binlog日志名
Exec_master_log_Pos: 正在同步当前binlog日志的POS点
出现relay log损坏的话,以 Relay_master_Log_File 和 Exec_master_Log_Pos参数值为基准,从上面看到Relay_master_Log_File:mysql-bin.000004 、Exec_master_Log_Pos=590788350,这时我们需要做的就是change master操作:
root@mysql-slave> stop slave sql_thread;
Query OK, 0 rows affected (0.01 sec)
root@mysql-slave> change master to master_host='192.168.10.132',master_port=3306,master_user='root',master_password='',master_log_file='mysql-bin.000004',master_log_pos=590788350;
Query OK, 0 rows affected (0.04 sec) root@mysql-slave> start slave sql_thread;
Query OK, 0 rows affected (0.00 sec) root@mysql-slave> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Connecting to master
Master_Host: 192.168.10.132
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 590788573
Relay_Log_File: localhost-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 590788573
Relay_Log_Space: 107
这样会导致丢弃所有在磁盘上的中继日志。
如果出现以下的报错,也是按以上的方法解决:
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1593
Last_Error: Error initializing relay log position: I/ O error reading the header from the binary log
Skip_Counter: 0
Exec_Master_Log_Pos: 59078
通过这种方法去修改中继日志,是不是发现有些麻烦呢?其实MySQL5.5已经考虑到slave宕机中继日志损坏这一问题了,即在slave的配置文件my.cnf里要增加一个参数relay_log_recovery=1就可以了。
总结:
一、遇到同步断开时,不能一味的使用--slave-skip-errors=[error_code]来跳过错误代码,这样很容易导致数据不一致的发生
二、binlog为STATEMENT格式时,在mater进行更新或者删除一条slave库没有的数据,同步是不会断开的。
三、定期检查数据的完整性,可以用pt-table-checksum校验主从数据的一致性,数据的完整性,对一个公司来说,无疑是最重要的。
四、slave库上建议把一些重要的选项开启,例如设置为read only、relay_log_recovery、sync_master_info、sync_relay_log_info、sync_relay_log这些重要选项开启。
参考资料:
http://blog.itpub.net/25704976/viewspace-1318714
作者:陆炫志 出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111 您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。 |
常见的MySQL Replication Error的更多相关文章
- MySQL Replication Error 处理一例
故障现象 MySQL slave status详情 mysql> show slave status\G *************************** 1. row ********* ...
- MySQL Replication Report
很多人都会MySQL主从框架的搭建,但很多人没有真正理解同步基本用途.同步的基本原理,还有当Master和Slave同步断开后的处理以及导致Master和slave不同步的原因等等,当你对这些都了如指 ...
- MySQL Replication 优化和技巧、常见故障解决方法
MySQL 主从同步错误(error)解决(转) sql_slave_skip_counter参数 附: 一些错误信息的处理,主从服务器上的命令,及状态信息. 在从服务器上使用show slave s ...
- mysql replication常见错误整理
这篇文章旨在记录MySQL Replication的常见错误,包括自己工作中遇到的与网友在工作中遇到的,方面自己及别人以后进行查找.每个案例都是通过Last_IO_Errno/Last_IO_Erro ...
- MySQL Replication 主从复制全方位解决方案
1.1 主从复制基础概念 在了解主从复制之前必须要了解的就是数据库的二进制日志(binlog),主从复制架构大多基于二进制日志进行,二进制日志相关信息参考:http://www.cnblogs.com ...
- mysql replication principle--转
原文地址:http://www.codeweblog.com/mysql-replication-principle/ 1, the replication process Mysql replica ...
- 浅析 MySQL Replication(本文转自网络,非本人所写)
作者:卢飞 来源:DoDBA(mysqlcode) 0.导读 本文几乎涵盖了MySQL Replication(主从复制)的大部分知识点,包括Replication原理.binlog format.复 ...
- MySQL replication illegal mix of collations
MySQL replication case 一则 转载:http://www.vmcd.org/2013/09/mysql-replication-case-%E4%B8%80%E5%88%99/ ...
- 五大常见的MySQL高可用方案【转】
1. 概述 我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中 ...
随机推荐
- 无法使用备份文件 'D:\20160512.bak',因为原先格式化该文件时所用扇区大小为 512,而目前所在设备的扇区大小为 4096
删除原先备份的记录 这里再加一条,如果你备份的文件还原有兼容性的问题,那就用低版本的sql做备份,这样的话哪里都能用
- scala面向对象.高阶函数,柯里化,Actor编程简介
1.定义一个类 class Person{ //用val修饰的变量是只读属性,有getter但是没有setter val id ="111" //用var修饰的变量既有getter ...
- TCP粘包,拆包及解决方法
在进行Java NIO学习时,发现,如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况,这就是TCP协议中经常会遇到的粘包以及拆包的问题.我们都知道TCP属于传输 ...
- POJ - 2635 The Embarrassed Cryptographer(千进制+同余模)
http://poj.org/problem?id=2635 题意 给一个大数K,K一定为两个素数的乘积.现给出一个L,若K的两个因子有小于L的,就输出BAD,并输出较小的因子.否则输出GOOD 分析 ...
- centos7 cannot find a valid baseurl for repo
出现这个问题是因为yum在安装包的过程中,虽然已经联网,但是没法解析远程包管理库对应的域名,所以我们只需要在网络配置中添加上DNS对应的ip地址即可. 操作 1.打开网络配置文件 vi /etc/sy ...
- Solr之java操作
参考教程: http://www.cnblogs.com/xia520pi/p/3625232.html http://www.cnblogs.com/hujunzheng/p/5647896.htm ...
- Java——Struts2 之国际化 struts.custom.i18n.resources=globalMessages
1.在src下 建立 struts.properties 文件,内容为:struts.custom.i18n.resources=globalMessages struts.custom.i18n.r ...
- Java EE之Hibernate的HibernateSessionFactory
昨天,一下午都被一个bug缠身,最后逐层排查,发现是MyEclipse 2014自动生成的HibernateSessionFactory有问题.后观察网友提供的自动生成的HibernateSessio ...
- JS的call方法的作用解释,简单易懂
先看看关于call()的官方解释,“调用一个对象的一个方法,以另一个对象替换当前对象.”,看了这样的解释,或许让你更摸不着头脑了.看例子: var x = "我是全局变量"; // ...
- caffe-win10-cifar10另
上一篇主要以bat形式实现了leveldb形式的cifar10,因为对于shell脚本不甚熟悉,所以这次专门利用.sh调用来实现lmdb形式的cifar10. 1.下载数据 同上一篇. 2.数据转换和 ...