☘️博主介绍☘️:
✨又是一天没白过,我是奈斯,DBA一名✨
✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌✌️
❣️❣️❣️大佬们都喜欢静静的看文章,并且也会默默的点赞收藏加关注❣️❣️❣️
久违的碰面,心中满是欢喜。今天作为逻辑迁移工具的最后一篇------使用mysqldump全量+mysqlbinlog增量完成实例的全库恢复。这篇文章算是一个经典的实战恢复案例,这一实战恢复案例不仅对于数据库管理员至关重要,也是每个希望确保数据完整性和安全性的用户必须了解的内容。众所周知, 单纯的mysqldump逻辑备份只能将MySQL实例恢复到备份文件所对应的时间点 。若将全量定时备份设置的间隔时间过长,这时如果还没发起下一个全量备份,但是又想要上一份全量备份到现在时间的全部数据,如果没有备份二进制日志的话就只能恢复到备份文件所对应的时间点,那么就会丢失上一份备份文件之后到现在的所有数据。因此,MySQL在备份时必须同时保留二进制日志,以便我们能够使用mysqlbinlog工具追溯并恢复备份之间的数据变更。接下来将详细解析这一过程,领略如何通过mysqldump与mysqlbinlog的完美结合,将MySQL实例精准地恢复到最新的时间点。
MySQL逻辑迁移工具的介绍和案例,我会分成四篇内容内容进行讲解,四篇的内容分别如下:
- 第一篇:一文搞清mysqldump逻辑迁移工具的用法和定时全备实例
- 第二篇:一文搞清mysqlpump逻辑迁移工具的用法和定时全备实例
- 第三篇:mysqlpump和mysqldump参数区别总汇
- 第四篇:使用mysqldump全量+mysqlbinlog增量完成实例的全库恢复**(当前篇)**
目录
2、使用mysqldump全量+mysqlbinlog增量完成实例的全库恢复
1、mysqlbinlog工具介绍:
在开始恢复之前先介绍mysqlbinlog工具,这样才能更好的开展恢复工作。
mysqlbinlog是MySQL数据库提供的一个命令行工具,用于 解析和显示MySQL二进制日志文件 (binlog)的内容。这个工具可以用于查看二进制日志中的SQL语句,以及进行数据恢复、备份和复制等操作。通过使用mysqlbinlog命令来查看二进制日志文件的内容,然后根据需要进行相应的处理。
在使用mysqlbinlog工具之前,需要确保MySQL服务器已开启binlog功能。开启binlog功能后,就可以使用mysqlbinlog命令来查看、解析或处理binlog文件了。
二进制日志是什么:
记录mysql所有的DDL和DML(除了数据查询语句select)语句事件。用来记录数据库中发生的修改情况,数据的修改、表的创建及修改等。它既可以记录涉及修改的SQL,也可以记录数据修改的行变化记录,同时也记录了执行时间。类似于oracle的归档日志,二进制有可能会被重做日志替代(自己的猜测哦😁)。
官方文档对mysqlbinlog的介绍(8.0版本):
MySQL :: MySQL 8.0 Reference Manual :: 6.6.9 mysqlbinlog --- Utility for Processing Binary Log Files
mysqlbinlog工具参数详解:
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 参数选项 | 描述 |
| -j, --start-position=# | 解码二进制日志从第一个事件的位置等于或大于参数。指定的是show master status;的Position列的值,一般start-position的值为154,因为新的二进制日志切换后就是154,二进制的头部信息。 |
| --stop-position=# | 在第一个位置大于或等于参数的事件中停止解码二进制日志 。指定的是show master status;的Position列的值,Position是多少就设置多少,表示当前二进制的日志最后的写入位置。Position的位置数值,同样也是文件的bytes字节大小 |
| --start-datetime=name | 二进制日志开始的时间点,格式:mysqlbinlog --start-datetime="2005-12-25 11:25:56" binlog.000003 |
| --stop-datetime=name | 二进制日志结束的时间点,格式:mysqlbinlog --stop-datetime="2005-12-26 11:25:56" binlog.000003 |
| --base64-output=name | 此选项确定何时应使用BINLOG语句将事件编码为base-64字符串进行显示。该选项具有以下三个允许值(不区分大小写): **AUTO:**AUTO("自动")或UNSPEC("未指定")在必要时自动显示BINLOG语句(即用于格式描述事件和行事件)。如果没有给出--base64-output输出选项,效果与--base64-output=AUTO相同。 **NEVER:**NEVER导致不显示BINLOG语句。如果发现必须使用BINLOG显示的行事件,mysqlbinlog将退出并返回错误。 **DECODE-ROWS:**DECODE-ROWS通过指定--verbose选项,向mysqlbinlog指定要解码的行事件,并将其显示为注释SQL语句。与NEVER一样,DECODE-ROWS禁止显示BINLOG语句,但与NEVER不同的是,如果发现行事件,它不会退出并出现错误。 |
| -v, --verbose | 重构行事件,并将其显示为带注释的SQL语句,并在适用的情况下提供表分区信息。如果两次给定此选项(通过传递其中一个"-vv"或"--verbose --verbose"),则如果binlog_rows_query_log_events变量设置为TRUE,则输出包括指示列数据类型和某些元数据的注释,以及行查询日志事件等信息性日志事件。 |
| --bind-address=name | 远程主机的ip地址 |
| -d, --database=name | 指定数据库,不能指定表针对性恢复 |
| -o, --offset=# | 跳过前N行 |
| --skip-gtids | 不要将二进制日志文件中的GTID包括在输出转储文件中,也就是忽略二进制日志中关于每个事务的GTID信息。这个参数一般在是gtid模式下的同机上恢复二进制日志或者异机上恢复二进制日志应用不了的情况,因为在gtid模式下二进制日志中每个事务在数据库是唯一的,而要恢复的二进制日志中gtid编号要比当前数据库的要旧或者都不是同一个gtid(server_uuid),所以就会出现二进制日志应用不了的情况,因为gtid(server_uuid)要是同一个并且只能向前推进,可以两种办法解决: 方式一:在mysqlbinlog中加上--skip-gtids参数 --skip-gtids参数:不要将二进制日志文件中的GTID包括在输出转储文件中,也就是忽略二进制日志中关于每个事务的GTID信息。 这种方式需要在mysqlbinlog工具每应用完成一个二进制日志后就需要查看Position点的变化(变化通过show master status;命令查看) 加上--skip-gtids参数后,通过对比工具对比解析成明文的二进制日志中每个事务都会忽略关于GTID信息部分(红框中的内容) 方式二: reset master; 如果是新实例的话,可以执行reset master(清空所有二进制日志,重新开始新的二进制),该命令在清空所有二进制日志的同时也会重置show master status命令中的File日志序号、Position点、Executed_Gtid_Set执行的gtid。相当于gtid重新计数。 |
使用mysqlbinlog恢复时的注意事项:
在进行数据恢复时Oracle数据库以其强大的recover功能而著称,通过recover database using backup controlfile until cancel;命令通知数据库以联机日志的最大scn为终点,能够高效地利用归档日志实现数据库的精确恢复。然而,相比之下,MySQL并没有内置类似Oracle recover database这样的自动恢复机制。对于MySQL而言,要达到时间点恢复的目的,通常需要 依赖mysqlbinlog工具,手动对二进制日志进行分析和恢复操作 。这种方式虽然相对繁琐,但在掌握了一定技巧后,依然能够实现精确且可靠的数据恢复。
以下是在进行mysqlbinlog恢复时需要注意的内容:
(1)恢复二进制通过使用"|"****(官方恢复命令)****管道符连接mysqlbinlog命令和mysql命令进行数据恢复。不能使用">"标准输出文件命令连接mysqlbinlog命令和mysql命令,使用">"虽然没有报错但日志不会被应用。
(2)恢复二进制使用mysqlbinlog命令时,输入mysqlbinlog --skip-gtids即可应用日志,使用mysqlbinlog --skip-gtids --base64-output=DECODE-ROWS --verbose --verbose反而不能应用日志,虽然没有报错但日志不会被应用。
(3)如果目标库开了gtid模式(gtid_mode=on和enforce_gtid_consistency=1),在对二进制恢复时会发生日志应用不了的情况,因为在gtid模式下二进制日志中每个事务在数据库是唯一的,而要恢复的二进制日志中gtid编号要比当前数据库的要旧或者都不是同一个gtid(server_uuid),所以就会出现二进制日志应用不了的情况,因为gtid(server_uuid)要是同一个并且只能向前推进,可以两种办法解决:
****方式一:****在mysqlbinlog中加上--skip-gtids参数
--skip-gtids 参数:不要将二进制日志文件中的GTID包括在输出转储文件中,也就是忽略二进制日志中关于每个事务的GTID信息。
这种方式需要在mysqlbinlog工具每应用完成一个二进制日志后就需要查看Position点的变化(变化通过show master status;命令查看)
加上 --skip-gtids 参数后, 通过对比工具对比解析成明文的二进制日志中每个事务都会忽略关于GTID信息部分 (红框中的内容)
****方式二:****reset master;
如果是新实例的话,可以执行r eset maste r(清空所有二进制日志,重新开始新的二进制),该命令在清空所有二进制日志的同时也会重置 show master status 命令中的File日志序号、Position点、Executed_Gtid_Set执行的gtid。相当于gtid重新计数。
(4)mysqlbinlog命令支持多日志联合解析,没有像binlog2sql有--start-file和--stop-file参数,直接binlog.000001 binlog.000002即可。
使用mysqlbinlog恢复语法:
sql
[root@mgr1 ~]# mysqlbinlog --stop-position=pos_point --stop-position=pos_point 二进制日志 | mysql -uroot -p'密码' 数据库名 --force
###恢复二进制通过使用"|"(官方恢复命令)管道符连接mysqlbinlog命令和mysql命令进行数据恢复
恢复二进制日志官方文档( 时间点(增量)恢复 ):
MySQL :: MySQL 8.0 Reference Manual :: 9.5 Point-in-Time (Incremental) Recovery
2、使用mysqldump全量+mysqlbinlog增量完成实例的全库恢复
源库备份:
一、对生产的MySQL实例进行mysqldump的定时全库备份和binlog日志的定时备份。这里可以参考之前写的文章实现定时备份哦(直通车 👉【MySQL篇】一文搞清mysqldump逻辑迁移工具的用法和定时全备实例(第一篇,总共四篇)-CSDN博客👈****)****
mysqldump的定时全库备份:
binlog日志的定时备份:
二、插入几条测试数据,然后再执行一次binlog日志的定时备份
(1)插入测试数据
sqlmysql> flush logs; ---刷新(切换)BINARY、ENGINE、ERROR、GENERAL、RELAY、SLOW日志 mysql> create table test04 (id int,name varchar(20)); insert into test04 values (1,'itpux01'); insert into test04 values (2,'itpux02'); insert into test04 values (3,'itpux03'); select * from test04; mysql> flush logs; ---刷新(切换)BINARY、ENGINE、ERROR、GENERAL、RELAY、SLOW日志
(2)binlog日志的定时备份: 新增了34到43序号的binlog日志
目标库恢复:
一、将源库的mysqldump的定时全库备份和binlog日志的定时备份传输到目标库上
二、创建一个新的MySQL实例
这里就是初始化一个MySQL实例,初始化MySQL实例这步在这里就不做演示了,等以后会专门写一篇关于初始化MySQL的文章哦
三、将备份的mysqldump全库备份导入新实例
(1)后台导入备份文件
sql[root@mysql ~]# nohup mysql -uroot -p123456 --socket=/mysql/data/3306/mysql.sock --force < mysqldump_full_20240130.sql & ###全备导出时用户和权限也导出了(因为权限和用户都在mysql数据库中,备份的文件包括mysql数据库,所以导入mysql库会引起冲突,使用--force:强制继续)
(2)后台任务消失导入才算完成:
sql[root@mgr2 data]# ps -ef | grep force
(3)查看恢复过程的后台日志:
sql[root@mgr2 full]# tail -200f /mysql/backup/full/nohup.out 日志输出一:[Warning] Using a password on the command line interface can be insecure.告警提示在命令中使用了明文密码,所以导致的提示,可以忽略,如果有其他内容需要具体看报错分析原因 日志输出二:提示多个Table already exists,因为备份采用了--all-databases导出所有数据库,所以也就是导出了mysql这个数据库,但是每个新建的实例都是有mysql这个库的,所以就会有冲突的情况,所以这个可以忽略。要特别关心其他数据库有没有报错
四、恢复权限和用户(方式一或方式二,任选一个)
方式一:导出默认数据库mysql中的权限(因为权限都在mysql数据库中)
sql[root@mgr2 full]# more mysqldump_full_20240130.sql | grep --color '/*!32312' ###备份采用了--all-databases导出所有数据库。对于默认数据库只导出数据库mysql,其他三个库不导出
方式二:通过语句导出SQL,直接在恢复机上执行
sql[root@mgr2 full]# more mysql_exp_grants_out_20240130.sql
五、通过mysqlbinlog恢复增量数据
(1)查看备份时记录的日志序号和position,那么就需要从记录的日志序号和position开始恢复数据
sql[root@mgr2 full]# more mysqldump_full_20240130.sql
(2)根据传输过来的最后一个binlog日志的position点确定最后需要恢复的--stop-postition 位置(position点就是字节大小)
注意: 要在恢复之前就要确定最后需要恢复的--stop-postition位置。因为在逻辑导入时就会产生二进制日志,所以一定要确定position点,不然数据重复(物理恢复时不会产生日志,所以可以先导入,然后确定position位置)
(3)总结一下需要从哪里开始恢复,到哪里结束
那么就要从33号日志的212点开始(备份记录的点),到传输过来的最后一个43号日志的264点中间的所有二进制日志
(4)通过mysqlbinlog进行二进制恢复
注意: 应用二进制之前,需要先记录下当前写入的二进制日志文件名,因为可能会因为GITD点导致二进制日志未应用。
如果目标库开了gtid模式(gtid_mode=on和enforce_gtid_consistency=1) ,在对二进制恢复时会发生日志应用不了的情况,因为在gtid模式下二进制日志中每个事务在数据库是唯一的,而要恢复的二进制日志中gtid编号要比当前数据库的要旧或者都不是同一个gtid( server_uuid ),所以就会出现二进制日志应用不了的情况,因为gtid( server_uuid )要是同一个并且只能向前推进,可以两种办法解决:
****方式一:****在mysqlbinlog中加上--skip-gtids参数
--skip-gtids 参数:不要将二进制日志文件中的GTID包括在输出转储文件中,也就是忽略二进制日志中关于每个事务的GTID信息。
这种方式需要在mysqlbinlog工具每应用完成一个二进制日志后就需要查看Position点的变化(变化通过show master status;命令查看)
加上 --skip-gtids 参数后, 通过对比工具对比解析成明文的二进制日志中每个事务都会忽略关于GTID信息部分 (红框中的内容)
****方式二:****reset master;
如果是新实例的话,可以执行r eset maste r(清空所有二进制日志,重新开始新的二进制 ),该命令在清空所有二进制日志的同时也会重置 show master status 命令中的File日志序号、Position点、Executed_Gtid_Set执行的gtid。相当于gtid重新计数。
通过mysqlbinlog应用二进制日志:
sql[root@mgr2 binlog]# mysqlbinlog --start-position=212 itpuxdb-binlog.000033 | mysql -uroot -p'123456' --socket=/mysql/data/3306/mysql.sock --force ###从33号日志的212点开始(备份记录的点)开始恢复 mysql> show master status; [root@mgr2 binlog]# mysqlbinlog itpuxdb-binlog.000034 itpuxdb-binlog.000035 itpuxdb-binlog.000036 itpuxdb-binlog.000037 itpuxdb-binlog.000038 itpuxdb-binlog.000039 itpuxdb-binlog.000040 itpuxdb-binlog.000041 itpuxdb-binlog.000042 | mysql -uroot -p'123456' --socket=/mysql/data/3306/mysql.sock --force ###mysqlbinlog命令支持多日志联合解析,直接binlog.000001 binlog.000002即可。为了更好的看每个日志被应用建议使用逐个日志应用,也可以考虑多日志联合应用 mysql> show master status; [root@mysql1 binlog]# mysqlbinlog --stop-position=264 itpuxdb-binlog.000043 | mysql -uroot -p'123456' --socket=/mysql/data/3306/mysql.sock --force ###最后一定要指定日志结束的pos点 mysql> show master status;
六、验证目标库与源库的数据、对象
第一步:查看用户以及权限
sqlmysql> select host,user from mysql.user; mysql> show grants for root@'%';
第二步:验证数据库是否恢复和备份之后创建表的数据是否恢复
sqlmysql> show databases; mysql> select * from test04;
第三步:验证对象数量
sqlmysql> select * from sys.schema_object_overview where db='itpuxdb'; ---数据对象
sqlmysql> select engine,count(*) from information_schema.tables group by engine; ---存储引擎分类
别继续往下滑啦,今天的内容已经圆满收官!相信学完这篇,你已经稳稳掌握了通过mysqlbinlog工具进行增量恢复的技巧。再见啦!