fix README

This commit is contained in:
danfengcao 2016-12-07 15:27:53 +08:00
parent a4800228fd
commit 53c8ba00ad
6 changed files with 104 additions and 58 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

104
README.md
View File

@ -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模式只支持DMLDDL将不做输出
* 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)

View File

@ -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}
'''

View File

@ -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已经有新数据进入。此时主从数据已经不一致
![](./static/master-slave-inconsistency.jpg)
### 笨办法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)

BIN
example/static/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 38 KiB