MySQL使用tokuDB引擎无法备份问题排查

一、问题背景

​ 之前线上和线下测试环境数据库仅允许为MyISAM和InnoDB引擎存在,但本次数据迁移中存在tokuDB引擎的库,一直使用percona提供的xtrabackup每天进行数据备份,innobackup自动恢复数据。但由于该情况并不支持tokuDB引擎的备份,故本次数据迁移生成的十几个集群备份全部无效,后面决定使用mydumper来进行备份恢复。

二、备份方案及问题处理

1、备份恢复流程

​ 使用mydumper+myloader来进行tokuDB引擎库的备份恢复,简易备份恢复流程如下:

  1. 使用mydumper备份:mydumper -h x.x.x.x -P port -u root -p xxxx -t 16 -e -c -o /path/to/backup

    使用16个线程对某主机上某个端口的数据库来进行压缩备份,备份到目录’/path/to/backup’中

  2. 创建一个和备份库同版本的数据库

  3. 使用myloader恢复:myloader --user root --password xxxxxxxx --port 3487 --host 127.0.0.1 -C --directory /path/to/backupDataPath/data --threads 8 --verbose 3 > load.log 2>&1

    由于备份时进行了压缩,故恢复时需要用-C参数来进行解压,并输出恢复日志load.log

  4. 创建主从关系:主从信息位于备份目录下的data/metadata文件中,文件内容大致如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    ## 如果想让恢复库为备份主机的从库,则用metadata中show master status中的信息创建主从关系,此时master_host为备份机IP;
    ## 若需要恢复库和备份机为同一个主库,则使用metadata中show slave status的信息创建主从关系即可。
    Started dump at: 2020-08-03 02:37:02
    SHOW MASTER STATUS:
    Log: mysql-bin.000671
    Pos: 16910
    GTID:

    SHOW SLAVE STATUS:
    Host: x.x.x.x
    Log: mysql-bin.000668
    Pos: 51101690
    GTID:

    Finished dump at: 2020-08-03 04:05:38


    ## 登陆数据库,执行
    change master to = 'x.x.x.x',
    master_port=xxxx,
    master_user='xx'
    master_password='xxxxxxxxxx',
    master_log_file='mysql-bin.xxxxx',
    mysql_log_pos=xxxxxxxxxx;

    ## 开启主从同步
    start slave;

2、问题处理

1. 开启主从时出现1062报错

1. 报错信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@(none))>show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: x.x.x.x
Master_User: xx
Master_Port: 3487
Connect_Retry: 60
Master_Log_File: mysql-bin.000783
Read_Master_Log_Pos: 360153174
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 283
Relay_Master_Log_File: mysql-bin.000668
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Error 'Duplicate entry '426922153' for key 'PRIMARY'' on query.

2. 问题原因

本次出现该问题是由于在备份过程中原数据库有数据写入,导致数据冲突。故使用备份数据进行恢复时出现’Duplicate entry’报错。在网上查找解决方法时发现其他人出现这个问题是由于两个库有相同表名、相同表结构的表同时进行恢复,这个还未进行测试验证。

3. 解决方法

mydumper备份时添加--lock-all-tables参数,即强制在备份开始时开启flush table with read lock;,则在备份时该库无法写入数据,所有的更新操作都会被阻塞,从而强制获得一致性备份数据。由于所有备份都是在从库执行,所以写入阻塞没有很大影响,但数据量较大时会导致主从延迟出现。如果主库备份数据,还是使用mysqldump来进行备份比较稳妥。后面可以考虑用mysqlpump来实现所有备份操作。

开启备份库的全日制可以看到,在备份开始时开启了FTWRL,备份完成后释放。