MySQL运维实战之备份和恢复(8.6)将数据库恢复到指定时间点

俊达1年前技术文章738

恢复到指定时间点

使用全量备份和增量备份文件,都只能将数据库恢复到备份结束的时间。通过binlog,可以将数据库恢复到任意时间点(前提是备份和该时间点之间的binlog都存在)。


找到时间点对应的binlog

恢复到时间点,首先需要定位该时间点对应的binlog位点(binlog文件和文件内的偏移量)。每个binlog头部都记录了该binlog产生的时间,我们可以使用mysqlbinlog工具解析binlog,查看binlog的第一个event的时间:

# mysqlbinlog -v binlog.000021 | head
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#230625 16:44:06 server id 23480  end_log_pos 126 CRC32 0x245d7ed7 	Start: binlog v 4, server v 8.0.32 created 230625 16:44:06


如果我们需要恢复到某个时间点T,那么我们需要找的binlog开始时间不大于T,并且该binlog的下一个binlog的开始时间大于T。

这里提供一个python的脚本,可以批量查看binlog时间:

import sys
import struct

if len(sys.argv) >= 2:
   pattern = sys.argv[1]
else:
   pattern = 'mysql-bin.[0-9]*'

print ('binlog pattern: %s' % pattern)

def parse_binlog_header(filename):
    with open(filename, 'rb') as f:
        data = f.read(8)
        return struct.unpack('i', data[4:])[0]

def main():

    import glob
    from datetime import datetime
    for f in sorted(glob.glob(pattern), key=lambda x: int(x.split('.')[-1])):
        ts = parse_binlog_header(f)
        print f, ts, datetime.fromtimestamp(ts)

if __name__ == '__main__':
    main()


使用脚本,传入binlog匹配模式,显示binlog时间:

# python parse_binlog_time.py  'binlog/binlog.[0-9]*'
binlog pattern: binlog/binlog.[0-9]*
binlog/binlog.000001 1686640790 2023-06-13 15:19:50
binlog/binlog.000002 1686647377 2023-06-13 17:09:37
binlog/binlog.000003 1686647391 2023-06-13 17:09:51
......
binlog/binlog.000020 1687682137 2023-06-25 16:35:37
binlog/binlog.000021 1687682646 2023-06-25 16:44:06
binlog/binlog.000022 1687683127 2023-06-25 16:52:07


我们的全量备份binlog位点是binlog.000020:

# cat xtrabackup_binlog_info
binlog.000020	610	58224b02-09b7-11ee-90bd-fab81f64ee00:1-13191,7caa9a48-b325-11ed-8541-fab81f64ee00:1-27


假设我们希望将数据库恢复到2023-06-25 16:45:00,那么根据各个binlog的时间信息,我们需要恢复到binlog.000021,从该binlog中找到16:45:00对应的位点:

# mysqlbinlog --stop-datetime="2023-06-25 16:45:01" binlog/binlog.000021 | grep -A 1 "^# at" | tail -2

# at 340009
#230625 16:45:00 server id 23480  end_log_pos 340040 CRC32 0xa1841663 	Xid = 88279


我们需要应用binlog.000021偏移量340040之前的binlog。


方法一、使用mysqlbinlog解析binlog并执行


从前面的步骤,我们得到了需要执行的binlog:

binlog开始位点:binlog.000020,偏移量610。

binlog结束位点:binlog.000021,偏移量340040。


依次使用mysqlbinlog解析binlog,并发送给mysql执行。执行第一个binlog时指定参数start-position,执行最后一个binlog时,指定参数stop-position。


执行第一个binlog:

mysqlbinlog --start-position=610 binlog.000020 | mysql -uroot -h127.0.0.1 -P6380 -uroot -pabc123


执行中间的binlog(本测试案例中只有2个binlog)。不需要带start-position和stop-position参数。



执行最后一个binlog:

mysqlbinlog --stop-position=340040 binlog.000021 | mysql -uroot -h127.0.0.1 -P6380 -uroot -pabc123


binlog执行完成后,校验一下数据。



相关文章

MySQL运维实战(4.2) 关于SQL_MODE

早期mysql对一些不符合SQL标准的SQL语句和数据的容忍度比较高。mysql 5.7 修改了默认sql mode。系统从低版本升级或迁移到高版本时,需要经过全面的测试,避免影响程序的正常运行。5....

MySQL运维实战之备份和恢复(8.8)恢复单表

xtrabackup支持单表恢复。如果一个表使用了独立表空间(innodb_file_per_table=1),就可以单独恢复这个表。1、Prepareprepare时带上参数--export,xtr...

MySQL运维实战之Clone插件(10.2)Clone插件原理

MySQL运维实战之Clone插件(10.2)Clone插件原理

clone插件实现clone操作主要分为几个阶段:1、初始阶段。初始阶段,会开启页面跟踪(Page Tracking)。开启页面跟踪后,修改过的页面的编号会被记录下来。页面的修改可分为两个阶段:首先在...

 MySQL运维实战(1.2)安装部署:使用二进制安装部署

MySQL运维实战(1.2)安装部署:使用二进制安装部署

一般在生产环境,我们会使用二进制安装的方式安装MySQL。使用二进制安装,在处理单机多实例、升级MySQL等场景下更加方便。如果有特殊的需求(比如要打一些patch),我们还可以自己编译二进制。1、下...

MySQL运维实战之ProxySQL(9.1)ProxySQL介绍

MySQL运维实战之ProxySQL(9.1)ProxySQL介绍

mysql通过复制技术实现了数据库高层面的可用,但是对于应用来说,当后端MySQL发生高可用切换时,应该怎么处理?我们考虑几种方案:1、使用域名绑定。应用通过dns连接后端实例,当后端发生切换后,将d...

MySQL运维实战(5.5) 数据导入导出时的字符集问题

mysql可以使用load data/select into outfile或mysqldump工具进行数据导入导出。下面分别分析数据导入导出时的字符集相关问题。准备测试数据创建测试表,2个字段分别使...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。