如果不小心对数据库进行误操作,而又没有及时备份怎么办?这恐怕是广大的coder经常遇到的一类问题。 我今天就因为不小心删除了某个数据库,但最后的备份是1个礼拜前的,唯一能解决的办法就是通过mysqlbinlog来恢复了。解决方案如下:
1、如果MySQL服务器启用了二进制日志,你可以使用mysqlbinlog工具来恢复从指定的时间点开始(例如,从你最后一次备份)直到现在或另一个指定的时间点的数据。
2、要想从二进制日志恢复数据,你需要知道当前二进制日志文件的路径和文件名。
3、一般可以从配置文件(一般情况,Linux下为my.cnf ,windows系统下为my.ini,取决于你的系统)中找到路径。如果未包含在选项文件中,当服务器启动时,可以在命令行中以选项的形式给出。
4、启用二进制日志的选项为–log-bin。
5、要想确定当前的二进制日志文件的文件名,输入下面的MySQL语句:
SHOW BINLOG EVENTS \G;
或者还可以从命令行输入下面的内容:
mysql –user=root -pmypasswd -e ‘SHOW BINLOG EVENTS \G’ 将密码mypasswd替换为你的MySQL服务器的root密码。
6、比如得到的日志文件名为:
mysql-bin.000001 1. 指定恢复时间
对于MySQL5.1.54,可以在mysqlbinlog语句中通过–start-date和–stop-date选项指定DATETIME格式的起止时间。
7、举例说明,比如在今天下午14:02(今天是2012年3月15日),不小心执行SQL语句删除了一个数据表,但发现没有最新的备份(当然,这只是开发环境,并不是正式的生产环境,正式环境还得定时做数据备份)。要想恢复表和数据,可以通过mysqlbinlog恢复指定时间的备份,输入:
mysqlbinlog –stop-date=”2012-03-15 14:02:00″ /data1/log/mysql/mysql-bin.000001 | mysql -u root -pmypasswd
该命令将恢复截止到在–stop-date选项中以DATETIME格式给出的日期和时间的所有数据。
8、如果你没有检测到输入的错误的SQL语句,可能你想要恢复后面发生的数据库活动。 根据这些,你可以用起使日期和时间再次运行mysqlbinlog:
mysqlbinlog –start-date=”2012-03-15 00:01:00″ /data1/log/mysql/mysql-bin.000001 | mysql -u root -pmypasswd
9、在该行中,从今天凌晨0:01登录的SQL语句将运行,组合执行前夜的转储文件和mysqlbinlog的两行可以将所有数据恢复到今天凌晨0:01前一秒钟。 你应检查日志以确保时间确切。
10、和–stop-date恢复指定时间段的数据库活动记录,如下:
mysqlbinlog –start-date=”2012-03-09 02:00:00″ –stop-date=”2012-03-15 14:00:00″ /data1/log/mysql/mysql-bin.000001 > /tmp/mysql_restore_030915.sql
通过这种方式,就能获取最后一个备份的文件时间2012-03-09 02:00:00到今天删除数据库之前2012-03-15 14:02这段时间的数据库活动事务操作
11.数据大概是在14:20左右删除的,首先利用mysqlbinlog命令导出那段时间的日志,执行下面的命令:
mysqlbinlog --start-datetime="2017-10-13 14:15:00" --stop-datetime="2017-10-13 14:25:00" mysql_bin.xxxxxx > data.sql
将14:15至14:25的日志记录导出到data.sql文件中,打开data.sql文件,查找定位到被删除数据的表:
如上图就是一条SQL语句的执行记录,其中黄色字体部分就是实际执行的SQL语句,语句经过BASE64编码,可以使用-v参数,让mysqlbinlog将执行的语句通过注释的方式显示出来,再使用-base64-output=decode-rows参数让mysqlbinlog把看不懂的BASE64编码隐藏起来,最后执行的命令变成这样:
mysqlbinlog --base64-output=decode-rows -v --start-datetime="2017-10-13 14:15:00" --stop-datetime="2017-10-13 14:25:00" mysql_bin.xxxxxx > data.sql
打开data.sql文件,查找定位到被删除数据的表:
可以看到执行的删除语句了,而且日志还帮我们把被删除记录的每个字段值都记录下来了,只要复制这些字段的值,就可以恢复被删除的记录了!
# 查看当前binlog状态
show master status\G;
# mysql中查看指定binlog信息
show binlog events in ‘mysql-bin.000010‘;
# 查询指定时间段内/位置的删除语句
mysqlbinlog --no-defaults --start-datetime=‘2020-03-03 07:00:00‘ --stop-datetime=‘2020-03-03 07:30:00‘ mysql-bin.000003 -d dbname -v | grep DELETE -A 5
mysqlbinlog --start-position=331 --stop-position=465 --database=test mysql-bin.000014 -v
# 恢复
mysqlbinlog --start-position=331 --stop-position=465 --database=test mysql-bin.000014 -v --skip-gtids | mysql -v test
# 将delete语句恢复成insert
mysqlbinlog --database=test mysql-bin.000014 --start-position=331 --stop-position=465 -v --base64-output=deco
de-rows | sed -n ‘/###/p‘ | sed -n ‘s/###//p‘ > test.sql
# 实例: 恢复delete语句删除的数据(本实例表只有3列,结合实际自行修改)
mysqlbinlog --database=test mysql-bin.000014 --start-position=331 --stop-position=465 -v --base64-output=decode-rows | sed -n ‘/###/p‘ | sed -n ‘s/###//p‘ > test.sql
sed ‘s/DELETE FROM/insert into/g‘ test.sql | sed ‘s/WHERE/select/g‘ | sed ‘s/@3.*/\0;/g‘ | sed ‘s/@[1-2].*/\0,/g‘ | sed ‘s/[^@]\(.*\)=//g‘ > execSQL.sql
source execSQL.sql