背景

出于对XtraBackup工作原理好奇,做了下面的日志解读

备份输出日志解读

[root@node1 09:23:35 /root]
#time innobackupex --defaults-file=/data/mysql/mysql3306/my3306.cnf -S /tmp/mysql3306.sock -uroot -plmlm /data/backup/
180525 09:24:24 innobackupex: Starting the backup operation
#开始备份操作
#为什么使用innobackupex,因为5.7及以前版本,mysql表是myisam引擎表,innobackupex可以备份所有引擎表
IMPORTANT: Please check that the backup run completes successfully.
           At the end of a successful backup run innobackupex
           prints "completed OK!".
#重要提示:请检查备份运行是否成功完成。
#在成功的备份运行结束时,innobackupex会打印“completed OK!”,也就是完成状态是OK。
180525 09:24:24  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/tmp/mysql3306.sock' as 'root'  (using password: YES).
#版本检查:使用DSN连接到MySQL服务器,DSN是数据源名称,也就是连接数据库需要的参数。
180525 09:24:24  version_check Connected to MySQL server
180525 09:24:24  version_check Executing a version check against the server...
#对服务器执行版本检查
180525 09:24:24  version_check Done.
180525 09:24:24 Connecting to MySQL server host: localhost, user: root, password: set, port: 3306, socket: /tmp/mysql3306.sock
Using server version 5.7.22-log
#连接到MySQL服务器,使用的参数是:host=localhost,user=root,password=使用命令行输入的,但不打印进日志;
port=3306,socket=/tmp/mysql3306.sock,使用的版本是5.7.22
innobackupex version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
#innobackupex版本是2.4.11,是基于64位Linux的5.7.19版本的MySQL服务器
xtrabackup: uses posix_fadvise().
#xtrabckup:使用posix_fadvise()函数,这是程序的函数入口?
xtrabackup: cd to /data/mysql/mysql3306/data
#xtrabckup:cd到/data/mysql/mysql3306/data目录下
xtrabackup: open files limit requested 65535, set to 65535
#xtrabckup:打开文件请求限制65535,设置为65535
xtrabackup: using the following InnoDB configuration:
#xtrabckup:使用以下InnoDB配置信息
xtrabackup:   innodb_data_home_dir = .
#设置innodb数据的存放目录为当前目录
xtrabackup:   innodb_data_file_path = ibdata1:100M:autoextend
#设置innodb共享表空间文件的个数和初始分配大小值,autoextend是自动扩展
xtrabackup:   innodb_log_group_home_dir = ./
#设置innodb日志文件的存放目录为当前目录(.和./是等效的)
xtrabackup:   innodb_log_files_in_group = 3
#设置innodb日志文件的个数为3
xtrabackup:   innodb_log_file_size = 104857600
#设置innodb日志文件的大小为100M
xtrabackup: using O_DIRECT
#使用无缓存的输入、输出
InnoDB: Number of pools: 1
#备份的线程是1个,还是线程池?不太明白
180525 09:24:24 >> log scanned up to (2643241)
#从2643241字节开始扫描日志
xtrabackup: Generating a list of tablespaces
#生成表空间列表
InnoDB: Allocated tablespace ID 2 for mysql/plugin, old maximum was 0
#为mysql/插件分配的表空间ID 2,旧的最大值为0
180525 09:24:25 [01] Copying ./ibdata1 to /data/backup/2018-05-25_09-24-24/ibdata1
180525 09:24:25 [01]        ...done
#首先完成ibdata1的拷贝,这是存放innodb引擎表的元数据信息
180525 09:24:25 [01] Copying ./mysql/plugin.ibd to /data/backup/2018-05-25_09-24-24/mysql/plugin.ibd
180525 09:24:25 [01]        ...done
#接着完成一堆ibd文件的拷贝,也就是innodb引擎表的数据和索引
180525 09:24:25 [01] Copying ./mysql/servers.ibd to /data/backup/2018-05-25_09-24-24/mysql/servers.ibd
180525 09:24:25 [01]        ...done
.....省略部分输出......
180525 09:24:25 [01] Copying ./db1/tb1.ibd to /data/backup/2018-05-25_09-24-24/db1/tb1.ibd
180525 09:24:25 [01]        ...done
180525 09:24:25 >> log scanned up to (2643241)
#日志扫描到2643241
180525 09:24:26 Executing FLUSH NO_WRITE_TO_BINLOG TABLES...
#执行刷新表的语句,作用是关闭所有打开的表,但是不记录到二进制日志里面
180525 09:24:26 Executing FLUSH TABLES WITH READ LOCK...
#执行FTWRL操作,对整个实例施加只读锁,只能读,不能写
#实际他做的是关闭所有表,使用全局读锁来锁定所有数据库的所有表。
180525 09:24:26 Starting to backup non-InnoDB tables and files
#开始备份非innodb引擎表和文件,这里主要是为了备份mysql库,sys库和performance_schema库,因为该库下的表都是myisam引擎表
#Performance Schema 收集数据库服务器性能参数,并且表的存储引擎均为PERFORMANCE_SCHEMA
180525 09:24:26 [01] Copying ./mysql/db.opt to /data/backup/2018-05-25_09-24-24/mysql/db.opt
180525 09:24:26 [01]        ...done
.....省略部分输出......
180525 09:24:26 [01] Copying ./performance_schema/session_status.frm to /data/backup/2018-05-25_09-24-24/performance_schema/session_status.frm
180525 09:24:26 [01]        ...done
180525 09:24:26 Finished backing up non-InnoDB tables and files
#完成非innodb引擎表和文件的备份
180525 09:24:26 [00] Writing /data/backup/2018-05-25_09-24-24/xtrabackup_binlog_info
#往xtrabackup_binlog_info写入信息,也就是GTID执行过的值和binlog的位点信息
180525 09:24:26 [00]        ...done
180525 09:24:26 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...
#执行FEL,但不记录到二进制日志
#为已安装的存储引擎关闭和重新打开任何可刷新的日志。这是因为,InnoDB会把日志刷新到磁盘。
xtrabackup: The latest check point (for incremental): '2643232'
#有关自增的最后一个检查点是2643232
xtrabackup: Stopping log copying thread.
#停止日志拷贝线程
.180525 09:24:26 >> log scanned up to (2643241)
#日志扫描到2643241字节
180525 09:24:26 Executing UNLOCK TABLES
#执行UNLOCK TABLES,也就是是否全局读锁
180525 09:24:26 All tables unlocked
#所有的表解锁
180525 09:24:26 [00] Copying ib_buffer_pool to /data/backup/2018-05-25_09-24-24/ib_buffer_pool
180525 09:24:26 [00]        ...done
#拷贝内存中的数据到相应的备份文件中
180525 09:24:26 Backup created in directory '/data/backup/2018-05-25_09-24-24/'
#备份创建在/data/backup/2018-05-25_09-24-24/目录里面
MySQL binlog position: filename 'mysql-bin.000012', position '194', GTID of the last change '81c310cb-5428-11e8-8c27-080027801684:1-21'
#打印出备份结束位点信息和执行过的GTID信息
180525 09:24:26 [00] Writing /data/backup/2018-05-25_09-24-24/backup-my.cnf
180525 09:24:26 [00]        ...done
#开始写backup-my.cnf文件
180525 09:24:26 [00] Writing /data/backup/2018-05-25_09-24-24/xtrabackup_info
#开始写xtrabackup_info文件
180525 09:24:26 [00]        ...done
xtrabackup: Transaction log of lsn (2643232) to (2643241) was copied.
#lsn编号从2643232到2643241的事务日志已经拷贝完成
180525 09:24:26 completed OK!

real    0m2.122s
user    0m0.177s
sys     0m0.261s

general log解读

2018-05-26T06:31:22.661529Z         3 Connect   root@localhost on  using Socket
2018-05-26T06:31:22.662086Z         3 Query     SET SESSION wait_timeout=2147483
2018-05-26T06:31:22.662627Z         3 Query     SELECT CONCAT(@@hostname, @@port)
2018-05-26T06:31:22.666879Z         3 Quit
2018-05-26T06:31:22.667426Z         4 Connect   root@localhost on  using Socket
2018-05-26T06:31:22.667619Z         4 Query     SET SESSION wait_timeout=2147483
2018-05-26T06:31:22.667913Z         4 Query     SHOW VARIABLES
#查看MySQL服务器的环境变量状态
2018-05-26T06:31:22.670727Z         4 Query     SHOW ENGINE INNODB STATUS
#查看InnoDB引擎状态信息
2018-05-26T06:31:22.673329Z         4 Query     SELECT PLUGIN_NAME, PLUGIN_LIBRARY FROM information_schema.plugins WHERE PLUGIN_STATUS = 'ACTIVE' AND PLUGIN_TYPE = 'KEYRING'
#查看活跃的类型是KEYRING的插件
2018-05-26T06:31:22.674371Z         4 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'
)
2018-05-26T06:31:23.984461Z         4 Query     SET SESSION lock_wait_timeout=31536000
2018-05-26T06:31:23.985374Z         4 Query     FLUSH NO_WRITE_TO_BINLOG TABLES
2018-05-26T06:31:23.989832Z         4 Query     FLUSH TABLES WITH READ LOCK
2018-05-26T06:31:24.392888Z         4 Query     SHOW MASTER STATUS
#获取当前数据库的位置
2018-05-26T06:31:24.393268Z         4 Query     SHOW VARIABLES
2018-05-26T06:31:24.396572Z         4 Query     FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS
#把日志刷到磁盘
2018-05-26T06:31:24.603445Z         4 Query     UNLOCK TABLES
2018-05-26T06:31:24.623980Z         4 Query     SELECT UUID()
2018-05-26T06:31:24.625019Z         4 Query     SELECT VERSION()
2018-05-26T06:31:24.835667Z         4 Quit

总结

第一阶段:检查与连接的准备阶段
执行备份命令之后,备份开始,XtraBackup工具尝试去连接MySQL服务器,连接成功之后,执行MySQL版本检查,版本检查完毕。使用给定的用户、密码、端口、socket文件连接使用5.7.22版本的MySQL服务器。

第二阶段:持续拷贝redo log
这部分内容并没有在备份的输出日志里体现,推测通过开启general log可以看到,也不一定,也许要通过源码才能看到。
修正:我的测试备份环境是一个静止的数据库,在备份时,既没有发生写操作,也没有发生读操作。所以没有看到一直在做"输出看到大量log scanned up to (xxx),对应就是持续扫描redo log"

第三阶段:拷贝ibdata1和ibd文件
xtrabackup进程开始执行一系列工作
1、调用系统函数posix_fadvise(),该函数是用来清理缓存的,不太理解此处使用的意图?了解的童鞋给我科普下,谢谢。
2、进入到/data/mysql/mysql3306/data目录下面
3、把打开文件请求限制调整为65535
4、使用以下InnoDB配置:
innodb_data_home_dir = .
#innodb数据存放在当前目录
innodb_data_file_path = ibdata1:100M:autoextend
#innodb共享表空间文件为1个,初始大小为100M,类型为自动扩展
innodb_log_group_home_dir = ./
#innodb日志文件存放在当前目录
innodb_log_files_in_group = 3
#innodb日志文件个数为3个
innodb_log_file_size = 104857600
#innodb日志文件大小为100M
5、使用O_DIRECT标志,目的为绕过缓冲区高速缓存,直接把数据传递到文件或设备,实际就是无需缓存来拷贝数据
6、默认使用单线程进行备份
7、日志扫描到2643241字节的位置
8、形成一个表表空间的列表
9、为mysql/plugin分配表空间为2,旧的最大值是0
10、把ibdata1文件拷贝到备份目录下面,直到完成
11、把ibd文件拷贝到备份目录下面,直到所有的ibd文件拷贝完成

第四阶段:备份非事务表的准备阶段
innobackupex进程开始执行一系列工作
1、扫描日志文件到2643241,这是已经写入redo的LSN
2、执行FLUSH TABLES,关闭所有打开的表,使用NO_WRITE_TO_BINLOG选项,也就是该语句不会被记录到binlog里面
3、执行FTWRL,使用全局读锁来锁定整个实例

第五阶段:备份非事务表
开始拷贝非innodb引擎表和文件,包括所有的.frm文件等,直到所有的都拷贝完成
修正:
.frm文件:保存了每个表的元数据,包括表结构的定义等;
.ibd文件:InnoDB引擎开启了独立表空间(my.ini中配置innodb_file_per_table = 1)产生的存放该表的数据和索引的文件。

第六阶段:整个备份完成后的后续工作
1、开始写xtrabackup_binlog_info文件,此处推测,获取执行过的GTID值和位点信息的语句在general log里面有记录
2、执行引擎的日志刷新,也就是把日志刷新到磁盘
3、最后的检查点是2643232字节的位置,也就是数据持久化到的LSN
4、停止拷贝线程
5、扫描日志文件到2643241
6、执行UNLOCK TABLES,释放全局读锁
7、开始拷贝ib_buffer_pool,直到拷贝完成,这是一堆数字,不知道做什么用处,了解的童鞋给我科普下,谢谢。
修正:拷贝缓冲池里的数据,以备恢复后,可以快速加载和预热访问量最高的数据。
8、打印出备份结束的位点和执行过的GTID值
9、写backup-my.cnf文件
10、写xtrabckup_info
11、LSN从2643232到2643241的事务日志拷贝完成
12、打印备份成功的标志,completed OK!