step 1. xtrabackup热备innodb数据文件和日志文件
所谓热备,就是备份数据文件的时候,其它事务可以修改这些数据文件,所以这一步备份出来的数据文件在时间点上是不一致的,有的数据块里存的是老的数据。任何事务修改innodb数据文件之前,都会记录日志,通过日志文件的内容可以将数据文件恢复到一个统一的时间点,所以xtrabackup热备的时候会同时备份innodb的日志文件,由于日志文件是循环使用的,老的日志文件会被覆盖掉,所以xtrabackup需要及时备份日志文件,每隔一定时间将日志文件的变更记录下来。
step 2. flush tables with read lock
step 1备份的只是innodb的数据文件,要将这些数据恢复出来,还需要备份mysql的数据字典等文件和表结构定义文件等(*.frm)。为了让备份能做出新的slave,也需要记录数据库当前binlog的位置。
step 3. 记录数据库当前的binlog位置,如果在slave上备份,记录当前日志恢复点。
执行show master status记录master的binlog位置,如果是slave,执行show slave status,记录当前这个slave日志恢复的位置(Relay_Master_Log_File, Exec_Master_Log_Pos)。
数据库锁住之后innodb 日志的位置,也需要记录下来,因为step 1备份完成之后、step 2锁数据库之前,数据库有可能还有变动。
step 4. back 表结构文件(*.frm), *.myd, *.myi, .etc
copy文件
step 5. unlock tables
释放锁
step 6. 应用innodb transaction log
将step 1记录的innodb日志应用到数据文件上,得到一个时间点一致的备份
step 7. 恢复数据库
step 8. 设置slave
根据step 3记录的binlog位置,设置新的slave(change master)
innobackupex 脚本包装了上面这个过程
flush tables with read lock有什么作用?
flush tables with read lock会将整个mysqld锁住,不能进行DML,也不能进行DDL,如下面pstack显示:
#0 0x00000031ac40ab99 in pthread_cond_wait@@GLIBC_2.3.2 ()
#1 0x00000000005b1612 in wait_if_global_read_lock ()
#2 0x00000000005ccac0 in mysql_execute_command ()
#3 0x00000000005cd52a in mysql_parse ()
#4 0x00000000005cd933 in dispatch_command ()
#5 0x00000000005cebc4 in do_command ()
#6 0x00000000005bf554 in handle_one_connection ()
#7 0x00000031ac4064a7 in start_thread () from /lib64/libpthread.so.0
#8 0x00000031ab8d3c2d in clone () from /lib64/libc.so.6