数据库内核月报 - 2017 / 02

MySQL · myrocks · myrocks之备份恢复

myrocks支持逻辑备份和物理备份,逻辑备份仍然采用mysqldump,物理备份采用自己开发的myrocks_hotbackup工具,传统的物理备份工具Xtrabackup不支持rocksdb。由于rocksdb的存储特性,myrocks不管是逻辑备份还是物理备份,与innodb的备份恢复均有较大差别。

逻辑备份

myrocks的mysqldump工具支持rocksdb的逻辑备份,其使用方式与原生的mysqldump备份innodb没有区别,一般的使用方式如下

mysqldump -uroot -h 127.0.0.1 -P 3306 --default-character-set=binary --single-transaction --master-data=2 --all-databases

虽然使用方式相同,但内部实现会用一些差别
传统的mysqldump备份方式简化如下

  1. 加锁FTWL:FLUSH TABLE WITH READ LOCK
  2. 设置RR模式:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
  3. 开启一致读:START TRANSACTION WITH CONSISTENT SNAPSHOT
  4. 获取位点:SHOW MASTER STATUS
  5. 解锁:UNLOCK TABLES
  6. 依次导出数据select * from table

myrocks的mysqldump备份方式简化如下

  1. 设置读取时不缓存到block cache:SET SESSION rocksdb_skip_fill_cache=1
  2. 设置RR模式:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
  3. 开启一致读:START TRANSACTION WITH CONSISTENT ROCKSDB SNAPSHOT
  4. 依次导出数据select * from table

可以看出myrocoks mysqldump导数据时,设置了engine层的优化rocksdb_skip_fill_cache。同时少了传统的FTWL的加锁和解锁操作,换了新的快照获取方式START TRANSACTION WITH CONSISTENT ROCKSDB SNAPSHOT, 此方式会加一些内存锁(LOCK_log等)同时返回位点信息,此方式比FTWL更高效。

mysql> START TRANSACTION WITH CONSISTENT ROCKSDB SNAPSHOT;
+------------------+----------+------------------------------------------+
| File             | Position | Gtid_executed                            |
+------------------+----------+------------------------------------------+
| mysql-bin.000003 |     1010 | a3d923e4-f19b-11e6-ba57-2c44fd7a5210:1-4 |
+------------------+----------+------------------------------------------+
1 row in set (0.00 sec)

myrocoks mysqldump不能同时备份innodb和rocksdb, 备份innodb时也采用新的START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT方式。如果需支持同时备份innodb和rocksdb,需修改mysqldump采用老的START TRANSACTION WITH CONSISTENT SNAPSHOT方式,同时开启innodb和rocksdb的快照。

物理备份

myrocks 有专门的物理备份工具myrocks_hotbackup,此工具是一个python脚本,源码在scripts/myrocks_hotbackup,总共才600多行,整个备份逻辑比较简单。

分析myrocks_hotbackup之前,先介绍下myrocks的checkpoint快照功能
执行以下语句会在目录/path/to/backup下创建一个一致性的数据快照
SET GLOBAL rocksdb_create_checkpoint = '/path/to/backup'
创建快照过程如下

  1. 禁止SST文件的删除操作
  2. 创建空目录/path/to/backup
  3. 在/path/to/backup下为每个SST文件的创建硬链接
  4. copy MANIFEST和OPTIONS文件到/path/to/backup下
  5. 备份WAL文件,最后一个WAL文件通过copy方式,其他WAL文件通过硬链接备份到/path/to/backup下
  6. 允许SST文件的删除操作

Note: SST内容是不会变化的,从而能够以硬链接的方式备份文件,充分利用硬链接的特性。同时快照过程中禁止删除SST文件,从而保证MANIFEST文件的一致性。

checkpoint快照中SST文件占主要部分,SST通过hardlink方式建立,使得快照操作比较快,同时也节省了空间。

再来看看myrocks_hotbackup的备份过程

  1. 通过SET GLOBAL rocksdb_create_checkpoint=‘path_n’建立快照
  2. 依次备份快照中的文件,先备份SST文件再备份, 再备份WAL,MANIFEST和OPTIONS文件。备份SST过程会比较长,如果超过checkpoint_interval(由参数–interval指定)SST文件还没有备份完,就会清理当前快照,返回步骤1重新开始。
  3. 步骤1,2完成后,rocksdb相关的文件备份完成,清理最后一次checkpoint快照文件。步骤1,2可能重复执行多次。
  4. 开始备份mysql其他文件。比如其他数据库文件,test,mysql数据等,另外还有datadir下其他文件,但过滤掉这些文件’master.info’, ‘relay-log.info’, ‘worker-relay-log.info’,’auto.cnf’, ‘gaplock.log’, ‘ibdata’, ‘ib_logfile’。
  • checkpoint renewing

上面步骤1,2重复建立快照的过程称为checkpoint renewing,图片来自Facebook
屏幕快照 2017-02-19 上午7.01.20.png

checkpoint renewing 过程中已经备份过的SST文件不会重复备份,只在最后一次checkpoint snapshot中备份WAL文件,MANIFEST和OPTIONS文件。checkpoint renewing 使得我们备份的数据比较新,从而通过此备份集建立的备库与主库同步的时间比较短。

  • 远程备份

myrocks_hotbackup只支持远程备份,暂时不支持本地备份。支持tar, xbstream, 另外还支持 facebook开源的网络传输工具WDT, 号称性能有10倍的提升。

一个用tar方式备份的例子

myrocks_hotbackup -u root -P 3306 --stream=tar --checkpoint_dir='xxx' | ssh  xx.xx.xx.xx  'tar -xi -C dest_path'

备份日志如下,从日志也可以看整个备份的过程

2017-02-14 15:26:37.076 INFO Starting backup.
2017-02-14 15:26:37.092 INFO Set datadir: /path/data/
2017-02-14 15:26:37.092 INFO Creating checkpoint at /xxx/1
2017-02-14 15:26:37.096 INFO Created checkpoint at /home/zhangyuan.zy/build/fbmyrocks/backup_tmp/1
2017-02-14 15:26:37.096 INFO Starting backup from snapshot: target files 2
2017-02-14 15:26:37.112 INFO Backup WAL..
2017-02-14 15:26:37.113 INFO Backup Manifest..
2017-02-14 15:26:37.131 INFO Cleaned up checkpoint from /xxx/1
2017-02-14 15:26:37.131 INFO Sent   0.00 GB of sst files, 2 files in total.
2017-02-14 15:26:37.131 INFO RocksDB Backup Done.
2017-02-14 15:26:37.132 INFO Taking MySQL misc backups..
2017-02-14 15:26:37.132 INFO Starting MySQL misc file traversal from database test..
2017-02-14 15:26:37.139 INFO Starting MySQL misc file traversal from database performance_schema..
2017-02-14 15:26:37.145 INFO Starting MySQL misc file traversal from database mysql..
2017-02-14 15:26:37.601 INFO Traversing misc files from data directory..
2017-02-14 15:26:37.601 INFO Skipping gaplock.log
2017-02-14 15:26:37.607 INFO Skipping auto.cnf
2017-02-14 15:26:37.613 INFO MySQL misc backups done.
2017-02-14 15:26:37.614 INFO All Backups Done.
  • 备份恢复

备份完成后,所有的数据都在同一个目录下,我们需要通过--move_back 将数据移动到我们需要的地方。

myrocks_hotbackup --move_back --datadir=/path/data --rocksdb_datadir=/path/data/.rocksdb --rocksdb_waldir=/path/data/.rocksdb --backup_dir=dest_path
  • 通过备份集搭建一个备库

传统的物理备份工具xtrabackup备份过程中会通过加锁获取一致的binlog位点信息,并保存到文件中,恢复后通过这些位点信息来重建复制关系。而myrocks_hotbackup备份过程中没有加锁,也没有保存位点信息。

在myrocks中enging层rocksdb会保持位点信息,每次事务提交时,都会将binlog位点以及gtid信息保存到数据字典BINLOG_INFO_INDEX_NUMBER中。

BINLOG_INFO_INDEX_NUMBER
key: Rdb_key_def::BINLOG_INFO_INDEX_NUMBER (0x4)
value: version, {binlog_name,binlog_pos,binlog_gtid}

备份集通过--move_back恢复后,直接启动mysqld,mysqld在recover 过程中会将数据字典BINLOG_INFO_INDEX_NUMBER的信息打印到错误日志中,例如

RocksDB: Last binlog file position 1010, file name mysql-bin.000003
RocksDB: Last MySQL Gtid a3d923e4-f19b-11e6-ba57-2c44fd7a5210:4

从错误日志中解析出位点,然后可以通过以下方式建立复制关系

show gtid_executed in '$binlog_file' from $binlog_pos;
set global gtid_purged='$gtid_executed';
change master to master_host='xx.xx.xx.xx', master_port=${MASTER_MYPORT}, master_user='root', master_auto_position=1, master_connect_retry=1;
set global gtid_purged='$gtid_executed';
start slave;
  • myrocks_hotbackup仅支持rocksdb备份,不支持innodb备份

总结

myrocks支持物理备份和逻辑备份,但这两种方式都只支持rocksdb备份,如果需要同时指出innodb和rocksdb的备份,还需要对备份逻辑稍加改造才行。
myrocks的物理备份方式比较高效,一般建议采用myrocks_hotbackup物理备份方式。