在很多MySQL使用场景中,随着业务的发展和技术的不断进步,MySQL数据库的数据量从最初的几百GB 增长到TB级别(这主要归因于业务规模的扩大、数据保留需求的增长以及系统设计的考虑)。当数据库数据量增长到TB级别时,从节点的复制问题变得愈发复杂和难以处理。在这种情况下,任何复制中断都可能导致数据不一致,并需要消耗大量时间去恢复。常见的复制问题包括:
- 复制断开一段时间后未被发现,导致主节点的binlog被清除,从而使得从节点无法继续同步数据。
- 由于版本Bug,复制进程可能出现假死状态,虽然状态显示为YES,但实际上复制进程已经停止。
- 从节点因误操作导致数据冲突,进而引发复制进程断开。
面对这些问题,常见的恢复策略包括直接备份主节点并重新搭建从节点,或从最近的备份中恢复从节点的数据。然而,对于TB级别的数据量,备份所需的空间和时间成本成倍增加,备份时间可能估计需要1天以上。因此,在实现快速恢复时需要考虑更高效的策略,如跳过错误事务或重新建立复制连接等(有很大可能导致数据不一致)。
下面介绍在binlog存在的情况,如何快速恢复。提供三种方式。
从库快速恢复方式
1.binlog回放
- 通过mysqlbinlog 一个一个回放binlog。到目前主库存在的binlog文件位置。
回放binlog命令行如下所示:
回放binlog命令行如下所示:
#批量应用日志:
mysqlbinlog binlog.000001 binlog.000002 binlog.000003|mysql -uroot -p
注意:按照1G的binlog大小量,每个binlog回放速度有可能在5分钟~15分钟以内。
2.从备份binlog,重新注册到主节点日志中
通过每天备份的binlog,放置主节点上的binlog目录下,把之前的binlog信息注册到mysql-bin.index中,同时binlog文件拷贝到主节点目录下。之后需要把主节点服务重新启动。
#1.拷贝备份binlog文件到主节点binlog目录:
shell> cp mysql-bin.000001 mysql-bin.000002 mysql-bin.000003 mysql/binlog/
#2.注册binlog文件:
shell> vim mysql-bin.index
#3.服务底层文件权限:
shell> chown -R mysql.mysql mysql-bin.000001 mysql-bin.000002 mysql-bin.000003
#4.binlog过期设置:
mysql> SET persist binlog_expire_logs_seconds =100000000;
mysql> SET persist expire_logs_days=30;
注意:
- binlog过期参数需要调整,重新启动服务有可能被清除掉。
- 拷贝的binlog 要赋予对应的文件权限。
3.CHANGE MASTER指定从节点的relay日志。
在MySQL中,relay日志是主节点binlog的的副本。当从节点relay日志存在的时,使用relay日志进行恢复。因为RELAY_LOG_FILE和RELAY_LOG_POS方式仅支持传统的位置点方式,所以不能开启auto_position方式。下面采用CHANNEL方式,指定新的复制频道。因为不能采取GTID模式所以relay日志文件和postion位置准确性非常重要。也需要MySQL服务重新启动。
#1.设置复制通道:
mysql> change master to
master_host = '10.10.10.1',
master_port = 3380,
master_user = 'repl01',
master_password = '******',
RELAY_LOG_FILE = 'relay-log-repl02.000008',
RELAY_LOG_POS = 4
FOR CHANNEL 'repl02';
#2.注册Relay文件:
shell> vim relay-log-repl02.index
relay-log-repl02.000001
relay-log-repl02.000008
#3.仅启动SQL回放进程:
mysql> START SLAVE sql_thread FOR CHANNEL 'repl02';
4.解析备份binlog转化为标准的SQL语句。
通过shell脚本可以实现binlog解析明文SQL语句。其实跟第一种 通过mysqlbinlog回放也一样效果。但执行效率会更高。
注释事项
上述快速恢复中过程中,其注释事项:
- 可以把从库的双1改成0,加快速度。双1参数:sync_binlog,innodb_flush_log_at_trx_commit
mysql> SET GLOBAL innodb_flush_log_at_trx_commit =0;
mysql> SET GLOBAL sync_binlog=0;
2.从mysql8.0版本开始可以关闭Redo这个不建议),可以提高性能。
关闭或开启Redo Log的语法是:
mysql>ALTER INSTANCE DISABLE INNODB REDO_LOG
mysql>ALTER INSTANCE ENABLE INNODB REDO_LOG
3.同时需要把expire参数时间拉长。MySQL8.0版本存在两个binlog清除个参数 :binlog_expire_logs_seconds ,expire_logs_days
mysql> SET persist binlog_expire_logs_seconds =100000000;
mysql> SET persist expire_logs_days=30;
4.禁止自动启动复制进程
MySQL服务启动时,禁止自动启动复制进程(即SQL线程和I/O线程)。
shell> vim my.cnf
skip_slave_start = ON #复制进程
总结
对于TB级别的MySQL数据库从节点的恢复,需要采用适当的方法和手段。当让从备份中恢复是最可靠的,但因数据量大时效性就比较差。建议日常维护中也需要注重binlog的备份。