Java 面试题

MySQL主从复制:异步/半同步/复制延迟生产方案

"MySQL主从复制原理是什么?线上复制延迟怎么处理?"

为什么面试官会问这道题

MySQL高可用的核心。延迟是每个生产团队都踩过的坑。面试官想看你懂日志传输机制和"读自己的写"这种延迟引发的anomaly——不是只会说"写主读从"。

如何回答

  1. 1

    讲三个线程:master把每个变更写binlog;slave的IO线程去master拉binlog事件写入本地relay log;slave的SQL线程读relay log回放到本地数据。三个线程:master dump、slave IO、slave SQL。

  2. 2

    binlog三种格式:STATEMENT(记SQL,体积小但NOW()、UUID()等非确定性函数会出问题)、ROW(记行变更,大但安全)、MIXED(混合)。生产几乎都用ROW。

  3. 3

    异步vs半同步:默认异步——master commit完立即返回,slave慢慢追,主挂了没传过去的binlog就丢了。半同步要求至少一个slave ACK收到binlog才返回客户端,牺牲1-2ms延迟换数据安全。

  4. 4

    补MGR(Group Replication):Paxos协议,多主或单主带自动选主和冲突检测,重但一致性强。

  5. 5

    延迟处理:监控Seconds_Behind_Master或pt-heartbeat;常见原因是长事务、DDL、SQL线程单线程跑热点;5.7+支持并行复制(slave_parallel_workers)通常能降3-5倍延迟;关键读要回主库,或用GTID based的WAIT_FOR_EXECUTED_GTID_SET阻塞等slave追齐。

参考回答示例

MySQL复制的本质是binlog从主库到从库的日志传输。主库所有数据变更都写一份binlog;从库有个IO线程建复制连接过来拉binlog事件,写入本地relay log;从库另一个SQL线程读relay log把事件回放到本地数据。binlog有三种格式。STATEMENT记SQL文本,体积小,但NOW()、UUID()、RAND()、没有ORDER BY的LIMIT这类非确定性函数会导致主从数据不一致。ROW记实际行变更,体积大但完全确定。MIXED按语句自动选。生产几乎都用ROW,配binlog_row_image = MINIMAL省空间。默认复制是异步的——主库commit完立即响应客户端,binlog异步传过去。主库挂了、最后一段binlog没传出去就永远丢了。半同步复制改成主库至少等一个从库ACK已收到(不是已执行)binlog,才返回客户端。延迟加1-2ms,换单节点故障零数据丢失。MGR是更强的方案,Paxos协议做多主或单主集群,自动选主+行级冲突检测,重但强一致。复制延迟是运维痛点。监控Seconds_Behind_Master(粗略)或pt-heartbeat(精确)。常见原因:主库大事务卡住binlog;某个DDL卡住SQL线程;单线程SQL线程跑热点表CPU打满。5.7+的并行复制按schema或logical clock分组并行回放,开slave_parallel_workers > 0通常能让延迟降3-5倍。"读自己的写"问题的标准解法是写完的关键读暂时回主库,或者用GTID based的MASTER_POS_WAIT / WAIT_FOR_EXECUTED_GTID_SET让会话阻塞到slave追齐自己刚写的位点再读。

实用技巧

  • 讲出三个线程的名字——master dump、slave IO、slave SQL,是懂协议不只是懂概念的信号。

  • 并行复制和GTID-based读等待是高级岗差异化点。

  • STATEMENT vs ROW要举NOW()这种经典例子。

  • 临场忘了命令,即答侠可以提示pt-heartbeat、Seconds_Behind_Master、WAIT_FOR_EXECUTED_GTID_SET。

常见问题

GTID是什么?

全局事务ID,集群唯一的事务编号。取代了"binlog文件+位点"方式,让故障切换和从库切换干净很多。

从库能变主库吗?

能,这就是故障切换的核心。MHA、Orchestrator这些工具会自动把一个从库提升为新主库。

半同步所有从库都挂了会永远阻塞吗?

不会。rpl_semi_sync_master_timeout(默认10秒)超时后降级为异步复制。这是可用性和持久性之间的取舍。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠