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恢复数据的更多相关文章

  1. mysql binlog恢复数据实战

    在前面,我们了解了mysql binlog日志的作用以及使用方法:  http://www.php20.cn/article/237 在后面讲到了,可以通过binlog进行恢复数据,那么,具体步骤是怎 ...

  2. MySQL 5.7 - 通过 BINLOG 恢复数据

    日常开发,运维中,经常会出现误删数据的情况.误删数据的类型大致可分为以下几类: 使用 delete 误删行 使用 drop table 或 truncate table 误删表 使用 drop dat ...

  3. Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~

    导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...

  4. 不小心删除数据--利用MySQL的binlog恢复数据

    MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...

  5. Mysql使用binlog恢复数据解决误操作问题的两种方法

    为保证没有其他参数配置影响,重新安装配置了一台最小化安装的CentOS7虚拟机 1. 基础知识
 安装mysql5.6数据库Mysql binlog初步理解 2. 配置mysql 开启binlog.修 ...

  6. 利用mysql的binlog恢复数据

    MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...

  7. mysql利用binlog恢复数据详细例子

    模拟数据恢复的案例 有些时候脑瓜就会短路,难免会出错 场景:在生产环境中,我们搭建了mysql主从,备份操作都是在从备份数据库上 前提:有最近一天或者最近的全备 或者最近一天相关数据库的备份 最重要的 ...

  8. mysql利用binlog恢复数据

    需求:需要给开发提供一个2018年9月30号的数据,按照我们公司正常备份策略来说,直接找到对应时间的备份数据,解压导入即可,恰好这个时间节点的数据没有,只备份到2018年9月25号的,糟糕了吧 咋办呢 ...

  9. mysql binlog恢复

    MySQL Binary Log也就是常说的bin-log, ,是mysql执行改动产生的二进制日志文件,其主要作用有两个: * 数据回复 * 主从数据库.用于slave端执行增删改,保持与maste ...

随机推荐

  1. python+selenium生成测试报告后自动发送邮件

    标签(空格分隔): 自动化测试 运行自动化脚本后,会产生测试报告,而将测试报告自动发送给相关人员,能够让对方及时的了解测试情况,查看测试结果. 整个脚本包括三个部分: 生成测试报告 获取最新的测试报告 ...

  2. 暗黑战神客户端(IOS和Android)打包教程

    先说下遇到的严重问题: 1.暗黑战神的资源管理有2套流程,一套开发使用(Resources.Load),一套正式上线使用(AssetBundles, 流畅),而走AssetBundles流程的代码则有 ...

  3. oracle数据库连接慢的问题

    1.现象 工程为spring+mybatis+xfire,webservice工程服务,实现的接口数据功能 2.修复方法 经过各种尝试: 1.重新部署工程     无果 2.重新部署tomcat   ...

  4. 【leedcode】 Median of Two Sorted Arrays

    https://leetcode.com/problems/median-of-two-sorted-arrays/ There are two sorted arrays nums1 and num ...

  5. gitlab

    这里解决gitlab文件上传大小限制 http://blog.csdn.net/fdipzone/article/details/45544497 通过浏览器debug知道是nginx服务解释器 进入 ...

  6. sql之连表查询--效率 通过分析各种连接查询的实现原理来了解

    1. 左连接 2.右连接 3.内连接 4.Cross join 笛卡尔乘积

  7. C#正则表达式判断输入日期格式是否正确

      /// <summary>        /// 是否为日期型字符串        /// </summary>        /// <param name=&qu ...

  8. php 下载文件代码段

    /** * 下载 * @param [type] $url [description] * @param string $filename [description] * @return [type] ...

  9. GPS部标平台的架构设计(四)-百度地图设计

    部标GPS软件平台之百度地图设计 地图是客户端中不可缺少的一个模块,很多人在设计和画图时候,喜欢加上地图引擎这样高大上的字眼,显得自己的平台有内涵,说白了就是用第三方的SDK来开发,早期的GPS监 控 ...

  10. SD卡读写一些函数

    /SPI2 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPI2_ReadWriteByte(u8 TxData) { u16 retry=0;   while((S ...