fix README
This commit is contained in:
parent
a4800228fd
commit
53c8ba00ad
104
README.md
104
README.md
|
@ -10,8 +10,7 @@ Parse MySQL binlog to SQL you want.
|
|||
|
||||
* 数据回滚
|
||||
* 主从切换后数据不一致的修复
|
||||
* 审计
|
||||
* 从binlog生成的标准SQL,带来的衍生功能
|
||||
* 从binlog生成标准SQL,带来的衍生功能
|
||||
|
||||
|
||||
安装
|
||||
|
@ -25,48 +24,85 @@ pip install -r requirements.txt
|
|||
使用
|
||||
=========
|
||||
|
||||
* 解析出标准SQL
|
||||
|
||||
```bash
|
||||
python binlog2sql.py --host='127.0.0.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002'
|
||||
```
|
||||
|
||||
* 解析出回滚SQL
|
||||
|
||||
```bash
|
||||
python binlog2sql.py --flashback --host='127.0.0.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002' --start-pos=1240 --end-file='mysql-bin.000004' --end-pos=9620
|
||||
```
|
||||
* 主从切换后数据不一致的修复
|
||||
|
||||
```bash
|
||||
1. 取出老master额外的事务;
|
||||
python binlog2sql.py --popPk --host='10.1.1.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002' --start-pos=1240 > oldMaster.sql
|
||||
2. 回滚老master额外的事务;
|
||||
python binlog2sql.py --flashback --host='10.1.1.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002' --start-pos=1240 | mysql -h10.1.1.1 -P3306 -uadmin -p'admin'
|
||||
3. 在新master重新执行事务;
|
||||
mysql -h10.1.1.2 -P3306 -uadmin -p'admin' < oldMaster.sql
|
||||
```
|
||||
|
||||
|
||||
注意事项
|
||||
=========================
|
||||
|
||||
#### MySQL server必须设置以下参数:
|
||||
### MySQL server必须设置以下参数:
|
||||
|
||||
[mysqld]
|
||||
server-id = 1
|
||||
log_bin = /var/log/mysql/mysql-bin.log
|
||||
expire_logs_days = 10
|
||||
max_binlog_size = 1000M
|
||||
binlog-format = row
|
||||
|
||||
#### 如果使用flashback模式,一次性处理的binlog不宜过大,不能超过内存大小。恢复操作有风险,请在备库操作或是在经验丰富的同学指导下进行。
|
||||
|
||||
#### flashback模式只用于恢复DML语句引起的误操作,不支持DDL语句。
|
||||
|
||||
###基本用法
|
||||
|
||||
**解析出标准SQL**
|
||||
|
||||
```bash
|
||||
python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t tbl1 tbl2 --start-file='mysql-bin.000002'
|
||||
```
|
||||
|
||||
**解析出回滚SQL**
|
||||
|
||||
```bash
|
||||
python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t tbl1 tbl2 --start-file='mysql-bin.000002' --start-pos=1240 --end-file='mysql-bin.000004' --end-pos=9620
|
||||
```
|
||||
###选项
|
||||
**mysql连接配置**
|
||||
|
||||
-h host; -P port; -u user; -p password
|
||||
|
||||
**解析模式**
|
||||
|
||||
--realtime 持续同步binlog。可选。不加则同步至执行命令时最新的binlog位置。
|
||||
|
||||
--popPk 对INSERT语句去除主键。可选。
|
||||
|
||||
-B, --flashback 生成回滚语句。可选。与realtime或popPk不能同时添加。
|
||||
|
||||
**解析范围控制**
|
||||
|
||||
--start-file 起始解析文件。必须。
|
||||
|
||||
--start-pos start-file的起始解析位置。可选。默认为start-file的起始位置;
|
||||
|
||||
--end-file 末尾解析文件。可选。默认为start-file同一个文件。若解析模式为realtime,此选项失效。
|
||||
|
||||
--end-pos end-file的末尾解析位置。可选。默认为end-file的最末位置;若解析模式为realtime,此选项失效。
|
||||
|
||||
**对象过滤**
|
||||
|
||||
-d, --databases 只输出目标db的sql。可选。默认为空。
|
||||
|
||||
-t, --tables 只输出目标tables的sql。可选。默认为空。
|
||||
|
||||
###应用案例
|
||||
|
||||
**主从切换后数据不一致的修复**,详细描述可参见[example/FixOldMasterExtraData.md](./example/FixOldMasterExtraData.md)
|
||||
|
||||
1. 提取old master未同步的数据,并对其中的insert语句去除主键(为了防止步骤3中出现主键冲突)
|
||||
```
|
||||
$ python binlog2sql.py --popPk -h10.1.1.1 -P3306 -uadmin -p'admin' --start-file='mysql-bin.000040' --start-pos=125466 --end-file='mysql-bin.000041' > oldMaster.sql
|
||||
```
|
||||
2. 将old master回滚,开启同步。同步正常;
|
||||
```
|
||||
$ python binlog2sql.py --flashback -h10.1.1.1 -P3306 -uadmin -p'admin' --start-file='mysql-bin.mysql-bin.000040' --start-pos=125466 --end-file='mysql-bin.000041' | mysql -h10.1.1.1 -P3306 -uadmin -p'admin'
|
||||
```
|
||||
3. 在new master重新导入改造后的sql;
|
||||
```
|
||||
$ mysql -h10.1.1.2 -P3306 -uadmin -p'admin' < oldMaster.sql
|
||||
```
|
||||
|
||||
###限制
|
||||
* mysql server必须开启,离线模式下不能解析binlog
|
||||
* binlog格式必须是行模式
|
||||
* flashback模式只支持DML,DDL将不做输出
|
||||
* flashback模式,一次性处理的binlog不宜过大,不能超过内存大小(有待优化)
|
||||
|
||||
|
||||
参考资料
|
||||
==============
|
||||
[1] 彭立勋, [MySQL下实现闪回的设计思路](http://www.penglixun.com/tech/database/mysql_flashback_feature.html)
|
||||
|
||||
[2] \_\_七把刀__, [MySQL binlog格式解析](http://www.jianshu.com/p/c16686b35807?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io)
|
||||
|
||||
[3] noplay, [Pure Python Implementation of MySQL replication protocol build on top of PyMYSQL](https://github.com/noplay/python-mysql-replication)
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ def concat_sql_from_binlogevent(cursor, binlogevent, row=None, flashback=False,
|
|||
class Binlog2sql(object):
|
||||
|
||||
def __init__(self, connectionSettings, startFile=None, startPos=None, endFile=None,
|
||||
endPos=None, only_schemas=[], only_tables=[], popPk=False, flashback=False, realtime=False):
|
||||
endPos=None, only_schemas=None, only_tables=None, popPk=False, flashback=False, realtime=False):
|
||||
'''
|
||||
connectionSettings: {'host': 127.0.0.1, 'port': 3306, 'user': slave, 'passwd': slave}
|
||||
'''
|
||||
|
|
|
@ -1,53 +1,63 @@
|
|||
MySQL主从切换后如何进行数据修复
|
||||
========================
|
||||
|
||||
目前的MySQL高可用方案中,主从切换后数据不一致是一个常见问题。以业界常用的MHA为例,当出现网络故障或硬件故障,无法通过SSH访问到老master,则有可能出现数据丢失。本文对主从切换后的数据不一致提供了一种解决方案。
|
||||
目前的MySQL高可用方案多是基于replication实现。MySQL replication默认是异步复制,它有个重要缺陷:主从延迟。当出现主从延迟时,如果master出现宕机且无法将全部数据发送至slave,则slave将丢失这部分数据。半同步复制和同步复制能避免主从延迟发生,但会使得性能大大下降,以至于诸多采用mysql存储的高性能系统仍旧采用异步复制。本文对主从切换后的数据不一致提供了一种新的解决办法。
|
||||
|
||||
### 主从切换后的状态
|
||||
|
||||
old master(10.1.1.1:3306)有一部分binlog(unreplicated binlog)未同步到new master(10.1.1.2:3306),切换完成后new master开始有新数据进入。
|
||||
如下图所示,切换完成后,old master(10.1.1.1:3306)有一部分binlog(unreplicated binlog)未同步到new master(10.1.1.2:3306),new master已经有新数据进入。此时,主从数据已经不一致。
|
||||
|
||||

|
||||
|
||||
### 笨办法1
|
||||
直接将old master连接new master,开启同步。此时一般会报错duplicate entry for key 'primary'。此时可选择,
|
||||
### 常见办法
|
||||
将old master指向new master,开启同步。执行命令如下:
|
||||
|
||||
1. 一直跳过错误直到连接正常
|
||||
```bash
|
||||
> CHANGE MASTER TO MASTER_HOST='10.1.1.2', MASTER_PORT=3306, MASTER_USER='xxx', MASTER_PASSWORD=xxx;
|
||||
> CHANGE MASTER TO master_log_file='mysql-bin.000001',master_log_pos= 2448;
|
||||
> start slave;
|
||||
```
|
||||
此时一般会报错duplicate entry for key 'primary'。DBA们往往会选择以下几种方式来处理,
|
||||
|
||||
1. 粗暴跳过所有错误,直到复制不再报错。
|
||||
|
||||
缺点:主从数据不一致,留下安全隐患
|
||||
缺点:主从数据不一致,留下安全隐患。
|
||||
|
||||
2. 根据报错,逐个修old master数据
|
||||
2. 根据报错信息,逐次修old master数据。如报duplicate entry for key 'primary' for table a where id=12345, 则将old master 表a id=12345的数据删除,再继续开启同步。
|
||||
|
||||
缺点:unreplicated binlog丢失,手工修复起来相当繁琐
|
||||
缺点:手工修复起来繁琐;unreplicated binlog部分事务丢失;如果unreplicated binlog较多的话,主从数据很大概率还是会不一致。
|
||||
|
||||
### 笨办法2
|
||||
对old master进行flashback至mysql-bin.00040 120,再开启同步。同步正常。
|
||||
3. 将old master回滚至mysql-bin.00040 120,再开启同步。同步正常。
|
||||
|
||||
缺点:unreplicated binlog丢失
|
||||
缺点:unreplicated binlog丢失。
|
||||
|
||||
### 新思路
|
||||
1. 提取old master未同步的数据,并对其中的insert去除主键;
|
||||
2. 对old master进行flashback至mysql-bin.00040 120,开启同步;
|
||||
### 新办法
|
||||
**步骤**
|
||||
|
||||
1. 提取old master未同步的数据,并对其中的insert语句去除主键(为了防止步骤3中出现主键冲突);
|
||||
2. 将old master回滚至mysql-bin.00040 120,开启同步。同步正常;
|
||||
3. 在new master重新导入改造后的sql;
|
||||
|
||||
```bash;
|
||||
python binlog2sql.py --popPk --host='10.1.1.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002' --start-pos=1240 > oldMaster.sql
|
||||
我们使用了纯Python开发的工具[binlog2sql](https://github.com/danfengcao/binlog2sql)来操作,执行命令如下
|
||||
|
||||
python binlog2sql.py --flashback --host='10.1.1.1' -P3306 -uadmin -p'admin' --start-file='mysql-bin.000002' --start-pos=1240 | mysql -h10.1.1.1 -P3306 -uadmin -p'admin'
|
||||
```bash
|
||||
$ python binlog2sql.py --popPk -h10.1.1.1 -P3306 -uadmin -p'admin' --start-file='mysql-bin.000040' --start-pos=125466 --end-file='mysql-bin.000041' > oldMaster.sql
|
||||
|
||||
mysql -h10.1.1.2 -P3306 -uadmin -p'admin' < oldMaster.sql
|
||||
$ python binlog2sql.py --flashback -h10.1.1.1 -P3306 -uadmin -p'admin' --start-file='mysql-bin.mysql-bin.000040' --start-pos=125466 --end-file='mysql-bin.000041' | mysql -h10.1.1.1 -P3306 -uadmin -p'admin'
|
||||
|
||||
$ mysql -h10.1.1.2 -P3306 -uadmin -p'admin' < oldMaster.sql
|
||||
```
|
||||
|
||||
**优点**
|
||||
|
||||
数据丢失最少,操作简单快捷。
|
||||
|
||||
**注意**
|
||||
|
||||
修完数据后,表数据可能会与业务逻辑预想的有区别。需要与业务方沟通后再做修复操作。
|
||||
|
||||
|
||||
**限制**
|
||||
|
||||
如果表的主键id是有业务含义的,则务必与业务方确认可行后再操作。
|
||||
|
||||
|
||||
###参考文献
|
||||
[1] 易固武, [MySQL数据库的高可用性分析](https://www.qcloud.com/community/article/203)
|
||||
|
||||
[2] 曹单锋, [Parse MySQL binlog to SQL you want](https://github.com/danfengcao/binlog2sql)
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 38 KiB |
Loading…
Reference in New Issue