• ADADADADAD

    mysql innobackupex的备份原理总结[ mysql数据库 ]

    mysql数据库 时间:2024-11-28 13:03:30

    作者:文/会员上传

    简介:

    xtrabackup的官方下载地址为http://www.percona.com/software/percona-xtrabackup。xtrabackup包含两个主要的工具,即xtrabackup和innobackupex,二者区别如下:1 xtrabackup只能

    以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。

    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的备份原理总结.docx

    将本文的Word文档下载到电脑

    推荐度:

    下载
    热门标签: innobackupexmysql