记一次阿里云RDS与自建数据库同步中断的补救过程
背景
2018年4月24日上午9点左右,小编在即将托管的服务器上建立数据库,并通过openvpn建立加密隧道,从而实现阿里云RDS和本地自建数据库之间同步。在托管服务器上配置openvpn后,重启openvpn客户端时,一直获取不到ip,后面重启了一下openvpn服务端,本地托管服务器获取到了IP,之后小编很开心的配置着MySQL主从同步。但是到11:00左右,有同事反应线上自建数据库无法访问,小编通过查看,发现在阿里云虚拟机上的自建MySQL同步中断,从而导致本地同步也中断,并且已经同步停止了2个小时。为了保证业务的正常运行,小编做了如下操作。
当前数据库同步架构图
补救策略
- 在RDS上获取gtid点,在从库上从新设置同步点,使从库正常运行起来,保证业务的流畅
- 通过解析RDS binlog,把binlog转换成SQL语句,然后把SQL语句插入到从库中
- 重新做RDS到自建库的数据同步
- 数据库同步架构改进,解决单点问题。
补救过程
1. 先让同步正常运行,保证业务不中断
1. 在RDS上获取gtid节点
- 命令 :
show master status\G
- 结果 :
*************************** 1. row ***************************
File: mysql-bin.000886
Position: 324398134
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 005304be-d260-11e7-b402-6c92bf475505:1-219538493,
759ccfb9-70d0-11e7-b7d5-6c92bf47591d:1-2572999,
936b4aea-70d0-11e7-b7d6-6c92bf4757fb:1-132842752,
df8f8121-d25f-11e7-b401-6c92bf4757d1:1-44768267
共返回 1 行记录,花费 5 ms.
2. 配置从节点过滤主键不存在的错误 编辑 从库配置文件(小编的配置文件为/etc/my.cnf)
slave-skip-errors = 1062,1053,1032
3. 重启数据库
service mysqld restart
4. 在从节点重新设置同步点
- 停止同步
stop slave
- reset 同步
reset slave all;
reset master;
- 重新设置同步点
set global gtid_purged='005304be-d260-11e7-b402-6c92bf475505:1-219538493,
759ccfb9-70d0-11e7-b7d5-6c92bf47591d:1-2572999,
936b4aea-70d0-11e7-b7d6-6c92bf4757fb:1-132842752,
df8f8121-d25f-11e7-b401-6c92bf4757d1:1-44768267';
CHANGE MASTER TO
MASTER_HOST='xxxxxxxx',
MASTER_USER='xxxxx',
MASTER_PASSWORD='xxxxxxxx',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1,
MASTER_CONNECT_RETRY=10;
5. 启动同步
start slave
6. 查看同步是否正常
show slave status\G
2. 弥补数据
由于从库无法通过运行RDS的binlog来修复数据,所以需要解析RDS的binlog,让其转换成SQL语句,然后再在各个从库上执行解析出来的SQL语句,具体流程如下:
1. 下载binlog在阿里云控制台,选择RDS的日志备份,并获取下载地址,在服务器上通过如下命令下载
wget -c '日志地址' -O xxx.tar.gz
2. 获取某一时间段的binlog并转换成可识别语句
mysqlbinlog --no-defaults --base64-output=decode-rows -v -v --start-datetime='2018-04-27 08:58:38' --stop-datetime='2018-04-27 11:58:37' mysql-bin.000797 > 797_10_11.txt
3. 使用下列脚本把上面转换后的binlog解析成SQL语句
- 脚本binlog_parse_to_sql.py
小编千辛万苦终于找到了一可以把binlog转换成SQL语句的脚本,github地址为:https://github.com/yy1117/binlog_parse_to_sql。但是该脚本直接使用不适合小编的需求,所以小编对代码进行了更改,满足了自己的需求。
#!/usr/bin/python
# -*- coding:utf8 -*-
#version_1.2
#######Comment:####################################################################
## Author:GuiJiaoQi&XuYou MAIL:yinyi1117@126.com;QQ:85531861 ##
###### set global group_concat_max_len =1024000;避免group_concat 默认长度不够 ##
###### 如果binlog文件的表在后面发生表结果变化,这个解析会报错 ##
###### 如果columns是二进制的解析会报错,如果有二进制的还请换工具,抱歉 ##
###################################################################################
import os,sys
import re
import MySQLdb
import optparse
def main():
p = optparse.OptionParser()
p.add_option('-u','--user',type='string',dest='user',default='root',
help='User for login ')
p.add_option('-p','--password',type='string',dest='password',
help='Password to use when connecting')
p.add_option('-s','--socket',type='string',dest='socket',
help='The socket file to use for connection.')
p.add_option('-f','--file',type="string",dest='filename',