十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本篇内容主要讲解“MySQL innobackupex的备份原理总结”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“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的备份原理总结”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!