MySql binlog恢复数据
1. 直接导入数据库
mysqlbinlog --database=testdb mysql-bin. | mysql -uroot -f
2. 导出成SQL文
(1) 从binlog输出为SQL
mysqlbinlog -vv --database=testdb --base64-output=decode-rows mysql-bin. > .sql
grep "###" .sql > 0001_#.sql
导出的SQL文如下格式:
### UPDATE `test`.`test_data1`
### WHERE
### @1='2002001809730903086' /* VARSTRING(150) meta=150 nullable=0 is_null=0 */
### @2='2001001959581442003' /* VARSTRING(150) meta=150 nullable=0 is_null=0 */
### @3='0661594' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @4='758686' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @5=1449174648065 /* LONGINT meta=0 nullable=1 is_null=0 */
### @6=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @7=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @8=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @9=1458787027688 /* LONGINT meta=0 nullable=1 is_null=0 */
### @10=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @11=1458787027688 /* LONGINT meta=0 nullable=1 is_null=0 */
### @12=300 /* INT meta=0 nullable=1 is_null=0 */
### SET
### @1='2002001809730903086' /* VARSTRING(150) meta=150 nullable=0 is_null=0 */
### @2='2001001959581442003' /* VARSTRING(150) meta=150 nullable=0 is_null=0 */
### @3='0661594' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @4='758686' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @5=1449174648065 /* LONGINT meta=0 nullable=1 is_null=0 */
### @6=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @7=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @8=0 /* LONGINT meta=0 nullable=1 is_null=0 */
### @9=1458787027688 /* LONGINT meta=0 nullable=1 is_null=0 */
### @10=1458787191658 /* LONGINT meta=0 nullable=1 is_null=0 */
### @11=1458787191658 /* LONGINT meta=0 nullable=1 is_null=0 */
### @12=400 /* INT meta=0 nullable=1 is_null=0 */
### INSERT INTO `test`.`test_data2`
### SET
### @1='00020017b4c3418b' /* VARSTRING(48) meta=48 nullable=0 is_null=0 */
### @2='2002001809730903086' /* VARSTRING(150) meta=150 nullable=0 is_null=0 */
### @3='00003997' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @4='0661594' /* VARSTRING(150) meta=150 nullable=1 is_null=0 */
### @5=1458787191658 /* LONGINT meta=0 nullable=1 is_null=0 */
### @6=0 /* INT meta=0 nullable=1 is_null=0 */
(2) 需要将其转换可以在mysql客户端执行的SQL。我写了一个小程序处理这个格式,代码如下:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Set; /**
*
* @author Beef Liu
*
**/
public class BinLogSQLConverter {
public final static String RTN_LINE = "\r\n"; private final static String SQL_WORD_INSERT_INTO = "INSERT INTO";
private final static String SQL_WORD_UPDATE = "UPDATE";
private final static String SQL_WORD_DELETE = "DELETE"; private final static String SQL_WORD_SET = "SET";
private final static String SQL_WORD_WHERE = "WHERE"; private final static String LINE_COMMENT = "###";
private final static String REGEX_BLOCK_COMMENT = "/\\*[^\\n']*/"; public static class TableDesc {
private String _tableName;
private String[] _colNames; public TableDesc() {
} public TableDesc(String tableName, String[] colNames) {
_tableName = tableName;
_colNames = colNames;
} public String getTableName() {
return _tableName;
}
public void setTableName(String tableName) {
_tableName = tableName;
}
public String[] getColNames() {
return _colNames;
}
public void setColNames(String[] colNames) {
_colNames = colNames;
}
} public static void convertToSQL(
File inputBinSQL, File outputSQL,
Charset charset,
TableDesc[] tableDescs
) throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(inputBinSQL), charset)); try {
OutputStreamWriter writer = new OutputStreamWriter(
new BufferedOutputStream(new FileOutputStream(outputSQL)),
charset);
try {
List<String> lines = new ArrayList<String>(); while(true) {
String line = reader.readLine();
if(line == null) {
break;
} //trim '###'
if(line.startsWith(LINE_COMMENT)) {
line = line.substring(LINE_COMMENT.length());
} //trim block comment
line = line.replaceAll(REGEX_BLOCK_COMMENT, ""); if(startsWithAndIgnoreSpace(line, SQL_WORD_INSERT_INTO)
|| startsWithAndIgnoreSpace(line, SQL_WORD_UPDATE)
|| startsWithAndIgnoreSpace(line, SQL_WORD_DELETE)
) {
//format previous statement
if(lines.size() > 0) {
String formatedStmt = formatStatement(tableDescs, lines);
if(formatedStmt != null && formatedStmt.length() > 0) {
writer.append(formatedStmt).append(RTN_LINE);
}
} //new statement
lines.clear();
} lines.add(line);
} if(lines.size() > 0) {
String formatedStmt = formatStatement(tableDescs, lines);
if(formatedStmt != null && formatedStmt.length() > 0) {
writer.append(formatedStmt).append(RTN_LINE);
}
}
} finally {
writer.close();
}
} finally {
reader.close();
}
} private final static String formatStatement(TableDesc[] tableDescs, List<String> lines) {
String line; line = lines.get(0);
if(startsWithAndIgnoreSpace(line, SQL_WORD_INSERT_INTO)) {
return formatStatementOfInsert(tableDescs, lines);
} else if (startsWithAndIgnoreSpace(line, SQL_WORD_UPDATE)) {
return formatStatementOfUpdate(tableDescs, lines);
} else {
System.out.println("Not supported yet. statement type:" + line);
return "";
}
} private final static String formatStatementOfInsert(TableDesc[] tableDescs, List<String> lines) {
/*
INSERT INTO `test`.`test_data1`
SET
@1='00020017bae7830b'
@2='2002001280299806243'
@3='00004407'
@4='0661601'
@5=1458889871654
@6=0
*/ String tableName = findTableNameInLine(lines.get(0));
TableDesc tblDesc = getTableDesc(tableDescs, tableName);
if(tblDesc == null) {
return null;
} StringBuilder sql = new StringBuilder();
//INSERT INTO
sql.append(lines.get(0)).append(RTN_LINE);
//SET
sql.append(lines.get(1)).append(RTN_LINE); //@1=xxxx
for(int i = 2; i < lines.size(); i++) {
if (i > 2) {
sql.append(", ");
}
sql.append(substituteColName(tblDesc, lines.get(i))).append(RTN_LINE);
} sql.append(";").append(RTN_LINE); return sql.toString();
} private final static String formatStatementOfUpdate(TableDesc[] tableDescs, List<String> lines) {
/*
UPDATE `test`.`test_data2`
WHERE
@1='2002001280299806243'
@2='2001001394921721184'
@3='0661601'
@4='758029'
@5=1450922125360
@6=0
@7=1458889670699
@8=0
@9=1458889682247
@10=0
@11=1458889682247
@12=300
SET
@1='2002001280299806243'
@2='2001001394921721184'
@3='0661601'
@4='758029'
@5=1450922125360
@6=0
@7=1458889670699
@8=0
@9=1458889682247
@10=1458889871654
@11=1458889871654
@12=400
*/ String tableName = findTableNameInLine(lines.get(0));
TableDesc tblDesc = getTableDesc(tableDescs, tableName);
if(tblDesc == null) {
return null;
} StringBuilder sql = new StringBuilder();
//UPDATE
sql.append(lines.get(0)).append(RTN_LINE); List<String> blockOfWhere = new ArrayList<String>();
List<String> blockOfSet = new ArrayList<String>(); //@1=xxxx
List<String> blockRef = blockOfWhere;
for(int i = 1; i < lines.size(); i++) {
String line = lines.get(i); if(startsWithAndIgnoreSpace(line, SQL_WORD_SET)) {
blockRef = blockOfSet;
} line = substituteColName(tblDesc, line);
blockRef.add(line);
} //output SET block
sql.append(blockOfSet.get(0)).append(RTN_LINE);
for(int i = 1; i < blockOfSet.size(); i++) {
if(i > 1) {
sql.append(", ");
}
sql.append(blockOfSet.get(i)).append(RTN_LINE);
} sql.append(blockOfWhere.get(0)).append(RTN_LINE);
for(int i = 1; i < blockOfWhere.size(); i++) {
if (i > 1) {
sql.append("AND ");
}
sql.append(blockOfSet.get(i)).append(RTN_LINE);
} sql.append(";").append(RTN_LINE); return sql.toString();
} private final static String substituteColName(
TableDesc tblDesc, String line) {
int index0 = line.indexOf('@');
if(index0 < 0) {
return line;
} int index1 = line.indexOf('=', index0);
if(index1 < 0) {
return line;
} int colNum = Integer.parseInt(line.substring(index0 + 1, index1));
return line.substring(0, index0)
.concat("`").concat(tblDesc.getColNames()[colNum - 1]).concat("`")
.concat(line.substring(index1))
;
} private final static String findTableNameInLine(String line) {
int index1 = line.lastIndexOf('`');
int index0 = line.lastIndexOf('`', index1 - 1); return line.substring(index0 + 1, index1);
} private final static TableDesc getTableDesc(TableDesc[] tableDescs, String tableName) {
for(TableDesc desc : tableDescs) {
if(desc.getTableName().equalsIgnoreCase(tableName)) {
return desc;
}
} return null;
} private final static boolean startsWithAndIgnoreSpace(String str, String prefix) {
int begin;
for(begin = 0; begin < str.length(); begin++) {
char c = str.charAt(begin);
if(c != ' ') {
break;
}
} return str.startsWith(prefix, begin);
} }
调用的例子:
@Test
public void test1() {
try {
File input = new File("test/restore001_#.sql");
File output = new File("test/restore001_#formated.sql"); BinLogSQLConverter.convertToSQL(
input, output,
Charset.forName("utf-8"),
new BinLogSQLConverter.TableDesc[] {
new BinLogSQLConverter.TableDesc(
"test_data1",
new String[] {"code","name","col3","col4"}
),
new BinLogSQLConverter.TableDesc(
"test_data2",
new String[] {"code","name","col3","col4"}
),
}
);
} catch (Throwable e) {
e.printStackTrace();
}
}
MySql binlog恢复数据的更多相关文章
- mysql binlog恢复数据实战
在前面,我们了解了mysql binlog日志的作用以及使用方法: http://www.php20.cn/article/237 在后面讲到了,可以通过binlog进行恢复数据,那么,具体步骤是怎 ...
- MySQL 5.7 - 通过 BINLOG 恢复数据
日常开发,运维中,经常会出现误删数据的情况.误删数据的类型大致可分为以下几类: 使用 delete 误删行 使用 drop table 或 truncate table 误删表 使用 drop dat ...
- Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~
导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...
- 不小心删除数据--利用MySQL的binlog恢复数据
MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...
- Mysql使用binlog恢复数据解决误操作问题的两种方法
为保证没有其他参数配置影响,重新安装配置了一台最小化安装的CentOS7虚拟机 1. 基础知识 安装mysql5.6数据库Mysql binlog初步理解 2. 配置mysql 开启binlog.修 ...
- 利用mysql的binlog恢复数据
MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...
- mysql利用binlog恢复数据详细例子
模拟数据恢复的案例 有些时候脑瓜就会短路,难免会出错 场景:在生产环境中,我们搭建了mysql主从,备份操作都是在从备份数据库上 前提:有最近一天或者最近的全备 或者最近一天相关数据库的备份 最重要的 ...
- mysql利用binlog恢复数据
需求:需要给开发提供一个2018年9月30号的数据,按照我们公司正常备份策略来说,直接找到对应时间的备份数据,解压导入即可,恰好这个时间节点的数据没有,只备份到2018年9月25号的,糟糕了吧 咋办呢 ...
- mysql binlog恢复
MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...
随机推荐
- Spring IoC容器初始化过程学习
IoC容器是什么?IoC文英全称Inversion of Control,即控制反转,我么可以这么理解IoC容器: 把某些业务对象的的控制权交给一个平台或者框架来同一管理,这个同一管理的平台可以称为I ...
- es6 ajax
简单的co用例: var co=require("co") class view{ constructor(){ co(function*(){ var p1=this.ajax1 ...
- openfire使用自定义用户表
转自:http://blog.csdn.net/nomousewch/article/details/7546083 在最近的项目中使用openfire服务器实现消息推送功能,如果使用openfire ...
- ipxe引导远程的windows
使用ipxe解决本地引导远程系统 本地安装的centos7,然后修改grub.cfg来使用ipxe技术引导远程windows,实现双系统 os-->centos7 修改grub.cfg 在文件最 ...
- 微信小程序(应用号)资源汇总整理
微信小应用资源汇总整理 开源项目 WeApp - 微信小程序版的微信 wechat-weapp-redux-todos - 微信小程序集成Redux实现的Todo list wechat-weapp- ...
- [转]ORACLE函数大全
SQL中的单记录函数 1.ASCII返回与指定的字符对应的十进制数;SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ' ...
- Issue 1:sigmod 撞车
11.6晚22:40,距离论文截止还有5天.在最后的紧要关头,竟然发现学术上撞车了,非常戏剧性的一幕,这么狗血的事情尽然就这么发生了. 自2015年8月份以来,本人一直在研究快速检查点领域.最近一篇t ...
- visio任意角度精确旋转图形
visio 2013 步骤: 选中图形 点击"视图->显示->任务窗格->大小和位置" 然后会出现一个小窗口,里面可以输入图形的旋转角度
- windows2008吃尽内存的解决办法
最近才用上windows2008,之前一直用的是windows2003,发现系统运行一段时间后,内存吃紧,赶紧打开资源查看器,发现当前运行的程序占有内存都很小,后经查资料,原来是被windows200 ...
- 【转】Deadlock的一些总结(死锁分析及处理)
1.1.1 摘要 在系统设计过程中,系统的稳定性.响应速度和读写速度至关重要,就像12306.cn那样,当然我们可以通过提高系统并发能力来提高系统性能总体性能,但在并发作用下也会出现一些问题,例如死锁 ...