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 ...
随机推荐
- 记一次【求n以内的素数个数】的优化记录
最近在leetCode上刷提,还是满锻炼人的,为以后面试打基础吧.不多说下面开始. 问题:求[2,n]之间的素数的个数. 来源:leetCode OJ 提示: Let's start with a i ...
- scanf、printf、gets、puts的应用及区别
1.scanf()函数 函数scanf()按指定的格式从键盘读取数据,并将其赋给一个或多个变量.例如: scanf(“%d %f”, &x,&rate); 输入多个变量时,scanf ...
- ACM集训的Day3 B。。。盲目搜索之DFS。。。
milk 一.题目描述: gzp有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数, 最初,A和B桶都是空的,而C桶是装满牛奶的.有时,农民把牛奶从一个桶倒到 另一个桶中,直到被灌 ...
- Apache+Tomcat配置方法
一. 修改应用服务器的server文件: 1.找到wizbank项目下的conf文件夹,打开server文件,加入以下内容: <Connector port="8009" p ...
- ui-grid
html代码: <html ng-app="myApp"> <head> <meta charset="utf- ...
- DS-5建工程
DS-5教程-使用ARM DS-5 和DSTREAM仿真器调试裸机程序 http://bbs.elecfans.com/jishu_453909_1_1.html i2c( 楼主 )2014-10-1 ...
- simple mail example for smtp debug
vim /etc/mail.rc head /etc/rc.local | mail -s "test_email" pyz_sub1@mailtest.com
- KEEPALIVED 双机自动切换部署备忘
1.配置文件的名字不要型错了.开始我将配置文件写成keeplive.conf,运行后也不报错,但无法看到VIP.日志里也看不到任何有价值信息.直到后来反复检查才发现可能配置文件名有问题,修正为keep ...
- oracle同一个数据库实例不同的用户之间的表、序列授权操作
1.背景:用户jtuser中有jtproduct中表A,B的同义词,在用户jtuser中向表A,B插入数据,提示“权限不够” 2.将A,B表授权给jtuser用户 $ sqlplus / as sys ...
- 怎样给Myeclipse配置tomcat服务器
http://jingyan.baidu.com/article/4853e1e53465271909f72690.html Meclipse是java Web企业级开发中最流行的工具,java we ...