面试题答案
一键面试检测主从数据不一致
- 基于主键或唯一键校验
- 编写脚本,从主库和从库中分别查询具有主键或唯一键的表数据,通过对比键值和对应的数据行,找出不一致的数据。例如,对于
users
表,有user_id
为主键,可以通过以下SQL获取数据:
然后在脚本中(如Python结合-- 主库 SELECT user_id, name, email FROM users; -- 从库 SELECT user_id, name, email FROM users;
pymysql
库)对查询结果进行对比。 - 编写脚本,从主库和从库中分别查询具有主键或唯一键的表数据,通过对比键值和对应的数据行,找出不一致的数据。例如,对于
- 使用pt - table - checksum工具
pt - table - checksum
是Percona Toolkit中的工具,可用于检测主从库之间的数据一致性。安装Percona Toolkit后,使用如下命令:
它会在主库上生成校验和,并将结果记录到指定的复制表(如pt - table - checksum --nocheck - binlog - format --replicate=test.checksums h=master_host,u=user,p=password
test.checksums
)中,然后在从库上重新计算校验和并与主库记录对比,报告不一致的表和行。 - 对比数据库的统计信息
- 对比主从库上相同表的行数、数据文件大小等统计信息。例如,通过以下SQL查询表行数:
如果行数不一致,很可能存在数据不一致情况。但这种方法不能精确指出哪些数据不一致。-- 主库 SELECT COUNT(*) FROM table_name; -- 从库 SELECT COUNT(*) FROM table_name;
可能导致不一致的具体原因
- 网络问题
- 网络延迟:主库向从库发送二进制日志(binlog)时,由于网络延迟,从库接收binlog不及时,导致从库应用relay log滞后,在这个过程中主库数据持续更新,最终导致主从数据不一致。
- 网络中断:网络短暂中断可能导致部分binlog丢失或损坏,从库无法完整应用主库的更改,从而造成数据不一致。
- 节点故障
- 主库故障:主库在写入数据后,还未来得及将binlog发送给从库就发生故障,重启后可能会丢失部分未发送的binlog,从库因此无法同步到这部分数据。
- 从库故障:从库在应用relay log过程中发生故障,可能导致relay log部分应用,重启后可能无法正确继续应用剩余日志,导致数据不一致。
- 配置问题
- 主从复制配置错误:例如,主从库的
server - id
配置重复,会导致复制异常。或者在配置主从复制时,指定的复制过滤规则(如replicate - do - db
、replicate - ignore - db
等)不一致,使得主从库同步的数据范围不同,最终造成数据不一致。 - 参数配置差异:主从库的一些MySQL参数配置不同,如
innodb_flush_log_at_trx_commit
、sync_binlog
等,可能影响数据写入的时机和持久性,导致数据不一致。
- 主从复制配置错误:例如,主从库的
- 复制过程中的异常操作
- 在从库上直接写入数据:如果在从库上直接执行
INSERT
、UPDATE
、DELETE
等操作,而不是通过主库同步过来的更改,会导致主从数据不一致。 - 主库上误操作:例如在主库上执行了
TRUNCATE
表操作,但从库由于某些原因(如网络延迟)未及时同步,后续又在主库上对该表进行其他操作,就会导致主从数据状态不一致。
- 在从库上直接写入数据:如果在从库上直接执行
恢复数据一致性的详细解决方案
- 停止主从复制
- 在从库上执行以下命令停止复制:
STOP SLAVE;
- 数据修复方法
- 基于备份恢复
- 如果有最近的全量备份,且备份时主从数据一致,可以将备份恢复到从库。例如,使用
mysqldump
进行备份恢复:- 首先在从库上停止MySQL服务:
systemctl stop mysql
- 然后删除从库的数据目录(假设为
/var/lib/mysql
):
rm -rf /var/lib/mysql
- 解压备份文件(假设备份文件为
backup.sql.gz
):
gunzip backup.sql.gz
- 恢复备份数据:
mysql -uuser -ppassword < backup.sql
- 重新配置从库复制:
-- 配置主库信息 CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='replication_user', MASTER_PASSWORD='replication_password', MASTER_LOG_FILE='master_binlog_file', MASTER_LOG_POS=master_binlog_position; -- 启动从库复制 START SLAVE;
- 如果有最近的全量备份,且备份时主从数据一致,可以将备份恢复到从库。例如,使用
- 手工同步数据
- 如果数据不一致的范围较小,可以手工同步数据。例如,对于某张表
orders
,在主库上执行SELECT
语句获取差异数据,然后在从库上执行对应的INSERT
、UPDATE
或DELETE
操作。 - 假设主库上有一条新订单记录在从库中不存在,在主库上通过如下SQL获取新订单数据:
SELECT * FROM orders WHERE order_id NOT IN (SELECT order_id FROM orders@slave_connection);
- 然后在从库上执行对应的
INSERT
语句插入这些数据:
INSERT INTO orders (order_id, order_date, customer_id, amount) VALUES (123, '2023 - 10 - 01', 456, 100.00);
- 如果数据不一致的范围较小,可以手工同步数据。例如,对于某张表
- 使用工具同步
- pt - table - sync工具:这是Percona Toolkit中的工具,可用于同步主从库之间的数据。例如,使用如下命令将主库数据同步到从库:
该工具会自动分析主从库数据差异,并执行必要的pt - table - sync --sync - to - master h=slave_host,u=user,p=password
INSERT
、UPDATE
、DELETE
操作来同步数据。
- 基于备份恢复
- 在不影响业务的前提下平稳修复数据
- 采用双写机制
- 在主库和从库修复数据期间,为了不影响业务,可以采用双写机制。即业务系统在写入数据时,同时向主库和从库发送写请求。这样可以保证在修复过程中,主从库的数据变化趋势一致。但这种方式需要业务系统有相应的改造,增加了系统的复杂性。
- 使用中间层
- 引入中间层(如MySQL Proxy、MaxScale等),在中间层上对读写请求进行处理。在修复数据时,将读请求均衡分配到主从库,写请求只发往主库。同时,中间层可以记录主从库的状态,当检测到主从数据不一致时,自动切换到合适的修复流程,而对业务系统透明。
- 选择业务低峰期修复
- 分析业务系统的使用情况,选择业务低峰期进行数据修复操作。这样可以最大程度减少对业务的影响。在修复前,提前通知相关业务部门或用户,做好相应的准备工作。修复完成后,进行全面的业务测试,确保数据一致性修复没有对业务功能产生影响。
- 采用双写机制