共计 8321 个字符,预计需要花费 21 分钟才能阅读完成。
本篇内容主要讲解“mysql innobackupex 的备份原理总结”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“mysql innobackupex 的备份原理总结”吧!
xtrabackup 的官方下载地址为
http://www.percona.com/software/percona-xtrabackup。
xtrabackup 包含两个主要的工具,即 xtrabackup 和 innobackupex,二者区别如下:
1 xtrabackup 只能备份 innodb 和 xtradb 两种引擎的表,而不能备份 myisam 引擎的表;2 innobackupex 是一个封装了 xtrabackup 的 Perl 脚本,支持同时备份 innodb 和 myisam,但在对 myisam 备份时需要加一个全局的读锁。还有就是 myisam 不支持增量备份。
innobackupex 工具的备份过程原理:!!!
一:早期版本的 innobackupex 备份过程如下图所示:
这里的 FTWRL(flush tables with read lock)把锁持有的时间主要与非 innodb 表的数据量有关,如果非 innodb 表数据量很大,备份很慢,那么持有锁的时间就会很长。即使全部是 innodb 表,也会因为有 mysql 库系统表存在,导致会锁一定的时间。为了解决这个问题,Percona 公司对 Mysql 的 Server 层做了改进,引入了 BACKUP LOCK(备份锁),具体而言,通过 LOCK TABLES FOR BACKUP 命令来获取一致性数据(包括非 innodb 表); 通过 LOCK BINLOG FOR BACKUP 来获取一致性位点,尽量减少因为数据库备份带来的服务受阻!
https://www.percona.com/doc/percona-server/5.6/management/backup_locks.html#interaction-with-other-global-locks — 官方文档的位置
二:引入备份锁的优势
2.1、LOCK TABLES FOR BACKUP: 只阻塞非事务表的操作! 不阻塞 innodb 表的 dml
作用:获取一致性数据
a)禁止非事务引擎 (非 InnoDB) 表写入(也即 DML)。
b)禁止所有表的 DDL。
优点:
a)不会被大查询阻塞。
b)不会堵塞 innodb 表的读取和更新,这点非常重要,对于业务表全部是并 innodb 的情况,则备份过程中 DML 完全不受损。
2.2、LOCK BINLOG FOR BACKUP:
作用:获取一致性位点。
a)禁止对 binlog 的位点操作(不允许 DML、DDL)
优点:
a)时间短,对 db 的影响很小。
三:具体 innobackupex 备份的过程:
3.1、低版本的 innobackupex,(2.2.0)的流程:
1.get Redo LSN
2.copy 系统表空间 + 事务引擎表的数据文件 + 后台子进程 (IBACKUP) 拷贝 Redo
3.FLUSH TABLES WITH READ LOCK
4.copy 所有 *.frm 文件,非事务引擎表 (MyISAM、ARCHIVE 等) 数据 + 索引文件
5.Get the binary log coordinates(坐标 / 位点)
6.finalize the background copy of REDO log
7.unlock tables;
3.2、高版本的 innobackupex,(也就是 =2.2.0 版本)的流程:(增加了备份锁,不再使用 FLUSH TABLES WITH READ LOCK)
1.get Redo LSN
2.copy 系统表空间 + 事务引擎表的数据文件 + 后台子进程 (IBACKUP) 拷贝 Redo
3.LOCK TABLES FOR BACKUP(这时候一直在拷贝 redo)
4.copy 所有 *.frm 文件,非事务引擎表 (MyISAM、ARCHIVE 等) 数据 + 索引文件(这时候一直在拷贝 redo)
5.LOCK BINLOG FOR BACKUP (为了得到一致性的 binlog 点位,所有需要写 binlog 的操作不能执行)
6.finalize the background copy of REDO log (包括 flush redo bufer 到磁盘)
7.get the binary log coordinates(坐标 / 位点)
8.UNLOCK BINLOG ;
9.UNLOCK TABLES;
注意:
一):避免在业务高峰期执行备份任务:
如果第四步骤完成之后,开始执行 LOCK BINLOG FOR BACKUP,获取到 binlog 锁之后,然后 SHOW MASTER STATUS 来获取一致性的 binlog, 然后开始 flush redo buffer 里的 redo 到磁盘(具体命令:FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS),以便于复制所有的 redo, 这里会有个问题,
如果当你的 redo buffer 比较大,并且在第四步复制非事务表的期间产生的 redo 非常多,这就会造成第 6 步骤时间比较长,进而导致持有 binlog backup 锁的时间就会变长,最后造成数据库的阻塞时间变长,影响业务时间变长,所以需要在业务少的时候来执行备份任务!
二):mysql RR 和 RC 隔离级别下,LOCK table tablename WRITE 会阻塞 LOCK TABLES FOR BACKUP 的执行, 但是 lock table tablename read 以及 LOCK TABLES FOR BACKUP 都不会阻塞 LOCK TABLES FOR BACKUP 的执行!
具体试验过程:
session 1 执行 lock table t write!
root@localhost : liuwenhe 20:48:15 LOCK table t WRITE;
Query OK, 0 rows affected (0.04 sec)
然后另一个窗口执行备份:发现卡在 Executing LOCK TABLES FOR BACKUP.,并且一直读取的都是同一个 lsn 号 (56989476423) 的 redo!
[root@beijing-fuli-hadoop-04 ~]# innobackupex -uroot -p V@1qaz /data/backup/
200310 21:00:17 [01] Copying ./sys/sys_config.ibd to /data/backup/2020-03-10_21-00-09/sys/sys_config.ibd
200310 21:00:17 [01] …done
200310 21:00:17 Executing LOCK TABLES FOR BACKUP…
200310 21:00:17 log scanned up to (56989476423)
200310 21:00:18 log scanned up to (56989476423)
200310 21:00:19 log scanned up to (56989476423)
200310 21:00:20 log scanned up to (56989476423)
此时查看进程,发现是 LOCK TABLES FOR BACKUP 在等待 Waiting for backup lock
root@localhost : (none) 17:33:17 show processlist;
+—-+————-+———–+———-+———+——–+——————————————————–+————————+———–+—————+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+—-+————-+———–+———-+———+——–+——————————————————–+————————+———–+—————+
| 3 | system user | | NULL | Connect | 100359 | Waiting for master to send event | NULL | 0 | 0 |
| 4 | system user | | NULL | Connect | 75664 | Slave has read all relay log; waiting for more updates | NULL | 0 | 0 |
| 17 | root | localhost | liuwenhe | Sleep | 0 | | NULL | 0 | 0 |
| 21 | root | localhost | NULL | Query | 164 | Waiting for backup lock | LOCK TABLES FOR BACKUP | 0 | 0 |
| 23 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
+—-+————-+———–+———-+———+——–+——————————————————–+————————+———–+—————+
5 rows in set (0.00 sec)
dml 操作没提交也不会阻塞的,其实是因为没 commit 的事务产生的 redo 不需要备份,因为恢复的时候不需要这些 redo!
具体试验过程:
session1:执行 dml 操作不 commit
root@localhost : liuwenhe 17:34:44 start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost : liuwenhe 17:35:59 delete from liu where id=100;
Query OK, 1 row affected (0.07 sec)
然后开始执行备份,发现是可以执行的! 说明个别的 dml 操作不提交也不会阻塞
[root@beijing-fuli-hadoop-04 ~]# innobackupex -uroot -p V@1qaz /data/backup/
xtrabackup: Transaction log of lsn (53883827670) to (53883827695) was copied.
200310 17:40:24 completed OK!
结论:LOCK table tablename WRITE 会阻塞 LOCK TABLES FOR BACKUP 的执行, 但是
lock table tablename read 以及 LOCK TABLES FOR BACKUP 都不会阻塞 LOCK TABLES FOR BACKUP 的执行! 一定要注意当你 mysqldump 备份的数据文件里面是带 lock table name write 的,注意不要和物理备份冲突了,导致物理备份被阻塞而执行时间过长
四:执行 innobackupex 备份之前打开 genary log
看到如下具体的过程:
2020-03-05T12:20:40.187735Z 221 Connect root@localhost on using Socket
2020-03-05T12:20:40.188456Z 221 Query set autocommit=1
2020-03-05T12:20:40.194768Z 221 Query SET SESSION wait_timeout=2147483
2020-03-05T12:20:40.224959Z 221 Query SELECT CONCAT(@@hostname, @@port)
2020-03-05T12:20:40.245466Z 221 Quit
2020-03-05T12:20:40.257504Z 222 Connect root@localhost on using Socket
2020-03-05T12:20:40.257854Z 222 Query SET SESSION wait_timeout=2147483
2020-03-05T12:20:40.258527Z 222 Query SET SESSION autocommit=1
2020-03-05T12:20:40.258759Z 222 Query SET NAMES utf8
2020-03-05T12:20:40.258983Z 222 Query SHOW VARIABLES
2020-03-05T12:20:40.280937Z 222 Query SHOW ENGINE INNODB STATUS
2020-03-05T12:20:40.465253Z 222 Query SELECT PLUGIN_NAME, PLUGIN_LIBRARY FROM information_schema.plugins WHERE PLUGIN_STATUS = ACTIVE AND PLUGIN_TYPE = KEYRING
2020-03-05T12:20:40.467169Z 222 Query SELECT
CONCAT(table_schema, / , table_name), engine
FROM information_schema.tables
WHERE engine NOT IN (
MyISAM , InnoDB , CSV , MRG_MYISAM
)
AND table_schema NOT IN (
performance_schema , information_schema , mysql
)
2020-03-05T12:20:51.604076Z 222 Query SET SESSION lock_wait_timeout=31536000
2020-03-05T12:20:51.604317Z 222 Query LOCK TABLES FOR BACKUP
2020-03-05T12:20:54.525210Z 222 Query LOCK BINLOG FOR BACKUP
2020-03-05T12:20:54.525306Z 222 Query SHOW MASTER STATUS
2020-03-05T12:20:54.525417Z 222 Query SHOW VARIABLES
2020-03-05T12:20:54.759369Z 222 Query FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS
2020-03-05T12:20:54.968260Z 222 Query UNLOCK BINLOG
2020-03-05T12:20:54.968348Z 222 Query UNLOCK TABLES
2020-03-05T12:20:55.003416Z 222 Query SELECT UUID()
2020-03-05T12:20:55.017367Z 222 Query SELECT VERSION()
2020-03-05T12:20:55.245540Z 222 Quit
注释:
一):首先会话级别修改 lock_wait_timeout 参数(默认就是 31536000 秒),保证当执行 lock binlog for backup 之后事务不会由于等待元数据锁时间过长而 timeout! 获取元数据锁的超时时间,例如 alter table。这个适合用于除了系统表之外的所有表(mysql 库之外)
二):FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 的作用是:将 innodb 层的重做日志持久化到磁盘,但是不触发 binlog buffer 涮新到磁盘; 然后会有相关进程来进行拷贝 redo。
说白了就是在所有的事务表和非事务表备份完成,获取全局读锁,且使用了 show master status 语句获取了 binlog 的 pos 之后,执行刷新 redo log buffer 中的日志到磁盘中,然后 redo log copy 线程拷贝这最后的 redo log 日志数据。因为当执行 LOCK BINLOG FOR BACKUP 获取到 binlog 备份锁到 unlock BINLOG 释放锁之前,不会再有请求进来(所有写 binlog 的操作都不能进行),保证 binlog 是不能变化的,进而保证了一致性的 binlog 点位!
三):关于是先 UNLOCK BINLOG 还是先 UNLOCK TABLES?
官方文档看到的是:先 unlock binlog 后 unlock tables
但是在 genary log 里看到的是:先 unlock binlog 后 unlock tables:
2020-03-05T12:20:51.604076Z 222 Query SET SESSION lock_wait_timeout=31536000
2020-03-05T12:20:51.604317Z 222 Query LOCK TABLES FOR BACKUP
2020-03-05T12:20:54.525210Z 222 Query LOCK BINLOG FOR BACKUP
2020-03-05T12:20:54.525306Z 222 Query SHOW MASTER STATUS
2020-03-05T12:20:54.525417Z 222 Query SHOW VARIABLES
2020-03-05T12:20:54.759369Z 222 Query FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS
2020-03-05T12:20:54.968260Z 222 Query UNLOCK BINLOG
2020-03-05T12:20:54.968348Z 222 Query UNLOCK TABLES
2020-03-05T12:20:55.003416Z 222 Query SELECT UUID()
2020-03-05T12:20:55.017367Z 222 Query SELECT VERSION()
2020-03-05T12:20:55.245540Z 222 Quit
那到地是谁先谁后呢?
首先他们各自的目的:
LOCK TABLES FOR BACKUP:是为了得到一致性的数据,阻塞非 innodb 表的修改,它不阻塞
innodb 表的修改,通过备份 innodb 表修改产生的 redo 日志来实现一致性!
LOCK BINLOG FOR BACKUP:是为了得到一个一致性的 gtid 点,期间所有表 (包括 innodb 表) 的修改操作都被阻塞,也就是所有写 binlog 的操作都被阻塞,这样 binlog 就不变化了,进而可以得到一致性的 binlog 点位!
可以看出来,binlog backup 锁 (阻塞所有表的修改) 比 lock tables for backup(只阻塞非 innodb 表修改)的范围广,所以我认为当 LOCK BINLOG FOR BACKUP 执行后,原则上 LOCK TABLES FOR BACKUP 这个锁就可以被释放了(因为 lock binlog 能起到 lock tables for backup 的作用),如果没有 unlock binlog,即便是你 unlock tables 了,那么依旧是整个实例无法进行任何写 binlog 的操作,所以这个顺序如果 mysql 设计的时候,没有考虑的话,那么这个顺序就没有确定的顺序,也就是都可以先执行,
如果是这样的话,那么 unlock binlog 是要等待 show master status 完成,并且 flush redo log 完成并且完成拷贝 redo 的操作,而 unlock tables 需要等待拷贝所有 *.frm 文件,非事务引擎表 (MyISAM、ARCHIVE 等) 数据 + 索引文件的操作完成,并且 LOCK BINLOG FOR BACKUP 之后,才能 unlock tables, 如果备份的时候数据库操作特别少,那么 show master status 和 flush redo log 完成并且完成拷贝 redo 的操作就特别快,那么 unlock binlog 就可能比 unlock tables 先完成,如果数据库比较繁忙的话,那么就是先 unlock tables 然后 unlock binlog!
比较遗憾的是,我模拟大量的 insert 操作的时候,同时备份,结果 general log 里面还是先 unlock binlog 后 unlock tables,所以我很迷惑到底官方文档写的准确性!
到此,相信大家对“mysql innobackupex 的备份原理总结”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!