第八篇:MySQL架构与主从复制——高可用的基石
前言在前面的文章中我们从索引、事务、锁、日志一路讲到慢查询优化。这些都是在单机MySQL上进行的操作。但生产环境中单机MySQL存在两个根本性问题单点故障MySQL宕机整个服务不可用读写压力所有请求打在一台机器上读多写少的场景下CPU和磁盘不堪重负解决这两个问题的核心方案就是主从复制。本文从MySQL的逻辑架构出发拆解主从复制的原理、Binlog三种格式的差异、主从延迟的成因和处理方案。本文核心问题MySQL的逻辑架构是什么样的各层分别做什么主从复制的原理是什么三个线程如何协作Binlog的三种格式STATEMENT、ROW、MIXED有什么区别各适合什么场景主从延迟是怎么产生的如何监控和处理主从切换有哪些方案各有什么优缺点MySQL常见的高可用架构有哪些读完本文你将对MySQL主从复制和高可用方案拥有系统性的理解。一、MySQL的逻辑架构疑问一条SQL从客户端发过来到返回结果MySQL内部经历了什么回答MySQL采用分层架构自上而下分为连接层、Server层、存储引擎层三层。每层各司其职。┌─────────────────────────────────────────────┐ │ 客户端 │ └────────────────┬────────────────────────────┘ │ ┌────────────────▼────────────────────────────┐ │ 连接层 │ │ 连接器建立连接、验证身份、获取权限 │ │ 线程池为每个连接分配一个线程或复用 │ └────────────────┬────────────────────────────┘ │ ┌────────────────▼────────────────────────────┐ │ Server层 │ │ │ │ 分析器词法分析、语法分析 → 生成语法树 │ │ ↓ │ │ 优化器选择索引、决定JOIN顺序 → 生成执行计划 │ │ ↓ │ │ 执行器调用存储引擎接口逐行读取/写入数据 │ │ │ │ 内置功能Binlog本层产生、权限校验、查询缓存│ └────────────────┬────────────────────────────┘ │ ┌────────────────▼────────────────────────────┐ │ 存储引擎层 │ │ │ │ InnoDB默认引擎支持事务、行锁、MVCC │ │ MyISAM不支持事务表锁适合只读场景 │ │ Memory数据存内存重启丢失适合临时表 │ │ │ │ 引擎层日志Redo Log、Undo LogInnoDB特有 │ └─────────────────────────────────────────────┘各层职责速记层级组件核心职责关键产物连接层连接器建立连接、身份验证、权限读取连接线程Server层分析器→优化器→执行器SQL解析、执行计划选择、数据调用Binlog存储引擎层InnoDB等数据存取、事务控制、崩溃恢复Redo Log、Undo Log二、主从复制的基本原理疑问主从复制是怎么工作的为什么从库能同步主库的数据回答主从复制的核心是Binlog——主库将所有写操作记录到Binlog中从库拉取这些日志并在本地重放从而实现数据同步。2.1 三个线程协作┌──────────┐ ┌──────────┐ │ 主库 │ │ 从库 │ │ │ │ │ │ Binlog ──┼──── 读取 ────→ ┌──┼─── I/O线程│ │ │ 推送Binlog │ │ │ │Dump线程 │ │ │ Relay Log│ │ │ │ │ │ │ │ │ │ SQL线程 │ │ │ │ │ 重放Relay│ │ │ │ │ Log │ └──────────┘ └──┴─────────┘三个线程各司其职线程位置职责Dump线程主库读取主库的Binlog并发送给从库I/O线程从库接收来自主库的Binlog并写入Relay LogSQL线程从库读取Relay Log中的事件并在从库上重放2.2 复制流程1. 从库执行 CHANGE MASTER TO 指定主库信息 2. 从库I/O线程连接主库 3. 主库创建Dump线程从指定的Binlog位置开始读取 4. Dump线程将Binlog事件推送给从库I/O线程 5. 从库I/O线程将事件写入Relay Log 6. 从库SQL线程读取Relay Log并执行 7. 从库记录当前应用的Binlog位置通过Master_Log_File和Read_Master_Log_Pos三、Binlog三种格式的差异疑问Binlog的三种格式有什么区别生产环境该选哪个回答STATEMENT记录SQL语句原文ROW记录每行数据的变更细节MIXED是两者的自适应切换。生产环境推荐ROW。3.1 STATEMENT格式-- 主库执行的SQLUPDATEuserSETageage1WHEREstatus1;-- Binlog记录的就是这条SQL语句原文优势劣势日志量小部分函数NOW()、UUID()、RAND()在主从间执行结果不同易读方便审计一些复杂的SQL无法被精确复制每种格式都有各自的成败案例——STATEMENT在处理不确定函数时是致命问题ROW在批量修改时是存储灾难MIXED试图取两者之优但也继承了各自的局限。3.2 ROW格式-- 主库执行的SQLUPDATEuserSETageage1WHEREstatus1;-- 假设影响了3行-- Binlog记录-- 第1行id1, age25 → age26-- 第2行id3, age30 → age31-- 第3行id5, age22 → age23优势劣势精确主从数据严格一致日志量大批量UPDATE可能产生百万行记录不会出现函数不确定性导致的主从差异难以直接阅读不便于人工审计3.3 MIXED格式默认使用STATEMENT记录 当MySQL检测到语句包含不确定性如UUID、用户变量时 → 自动切换为ROW格式记录该语句优势劣势兼顾日志量和准确性你不知道到底用了哪种格式大多数情况下使用STATEMENT排查问题时需要同时查看STATEMENT和ROW3.4 生产环境推荐ROW三个理由数据一致性ROW格式下主从数据绝对一致不会因为函数不确定性而产生差异。数据不一致的修复成本远高于日志量的存储成本闪回操作ROW格式记录了每行数据变更前后的完整值可以方便地生成回滚SQL。在生产环境出现误操作时这是快速恢复的重要手段审计追踪ROW格式精确记录了谁改了哪一行、改了什么值。配合审计需求可以直接追溯数据变更历史合规性更强四、主从延迟——成因与对策疑问主从延迟是怎么产生的从库总是比主库慢几秒这是正常的吗回答主从延迟是主从复制固有的问题核心原因在于主库可以并行写入从库只有一个SQL线程串行回放。差距越大延迟越高。4.1 延迟成因主库 100个并发连接 → 100个事务并行执行 → Binlog瞬间产生大量记录 从库 I/O线程 → 快速拉取Binlog到Relay Log很快 SQL线程 → 逐条执行Relay Log中的事件串行慢 瓶颈SQL线程单兵作战主库的并行写在从库被串行化4.2 监控主从延迟-- 在从库上执行查看延迟SHOWSLAVESTATUS\G 关键指标 Seconds_Behind_Master从库落后主库的秒数 Slave_IO_RunningI/O线程是否运行Yes/No Slave_SQL_RunningSQL线程是否运行Yes/No Relay_Log_SpaceRelay Log占用的空间4.3 延迟处理方案方案做法适用场景并行复制MySQL 5.7支持基于组提交的并行复制从库多个SQL线程并行回放一般延迟场景读写分离写操作走主库读操作根据延迟容忍度选择主库或从库延迟在可接受范围内强制走主库关键业务下单、支付直接查主库对数据实时性要求高的场景延迟监控告警超过阈值触发告警自动将读流量切换回主库延迟超标的应急方案4.4 怎么应对主从延迟不是消除延迟而是根据业务场景选择应对策略实时查询如订单支付结果走主库可接受延迟的查询如订单列表走从库关键业务兜底——延迟超标时读流量自动切回主库。五、主从切换——高可用的关键操作疑问主库宕机了怎么办怎么切换到从库回答主从切换是高可用的核心操作。核心步骤是选择新主库→通知从库切换→更新应用配置整个过程中数据一致性是关键考量。5.1 切换流程1. 确认主库确实故障监控告警或人工判断 2. 选择数据最新的从库作为新主库 3. 检查选中的从库是否已应用所有Relay Log 4. 停止该从库的复制进程 5. 重置该从库的复制状态 6. 其他从库重新连接到新主库 7. 更新应用配置指向新主库5.2 切换方案对比方案原理优势劣势MHA自动故障检测自动切换由Manager节点监控主库健康状态成熟稳定故障检测快需要额外部署Manager节点和维护VIPOrchestrator拓扑管理与自动恢复通过探测和状态分析触发切换可视化管理支持复杂拓扑配置复杂学习成本高MGRMySQL官方原生高可用方案多点写入故障自动切换仅支持InnoDB配置要求严格GTID事务级别的唯一标识简化主从切换时定位Binlog位置的操作不需要手动记录位置GTID在复杂事务场景下可能有性能开销5.3 GTID——让切换变简单-- 传统复制切换到新主库时需手动指定CHANGE MASTERTOMASTER_LOG_FILEmysql-bin.000012,MASTER_LOG_POS120;-- GTID复制不需要知道具体的文件和位置CHANGE MASTERTOMASTER_AUTO_POSITION1;-- 自动从正确的位置开始GTIDGlobal Transaction ID为每个事务分配一个全局唯一标识。从库切换时只需告诉新主库当前从库已经执行过的GTID集合新主库自动从正确的位置开始补传剩余事务。传统复制中主从切换时需要人工记录和指定Binlog文件和位移这是一个极易出错的环节。GTID让这个操作自动化。六、常见高可用架构疑问生产环境有哪些成熟的MySQL高可用方案各适合什么规模回答从单主到多主高可用方案根据数据一致性要求和可接受的故障切换时间递增。6.1 主从复制 手动切换┌──────┐ ┌──────┐ │ 主库 │────→│ 从库 │ └──────┘ └──────┘最基础的架构。适合开发环境和内部工具或读多写少的中小型应用。故障时需人工干预切换时间以分钟计。6.2 MHA自动切换┌──────┐ ┌──────┐ ┌──────┐ │ 主库 │────→│ 从库1 │ │ 从库2 │ └──────┘ └──────┘ └──────┘ ↑ ┌─────────┐ │ Manager │ ← 监控主库故障时自动切换 └─────────┘MHA在生产环境广泛使用。Manager节点定期探测主库发现主库故障后自动执行切换切换时间通常在秒级。6.3 MGRMySQL Group Replication┌──────┐ ┌──────┐ ┌──────┐ │ 主库 │←───→│ 从库1 │←───→│ 从库2 │ └──────┘ └──────┘ └──────┘ ↑ ↑ ↑ └──────────────┴──────────────┘ 组内所有节点可写MySQL官方原生方案。组内所有节点互通故障时自动剔除问题节点并同步新节点。原生支持多点写入但需要稳定网络环境和InnoDB引擎。适合对高可用要求极高的中小型集群。七、主从复制的常见问题问题现象解决主从数据不一致从库查到的数据和主库不一样用pt-table-checksum检查和pt-table-sync修复Relay Log损坏SQL线程意外停止无法继续应用重建复制STOP REPLICA; RESET REPLICA; 重建连接大事务延迟批量操作产生大量Binlog从库严重滞后拆分大事务提升从库硬件配置主键冲突从库插入时报唯一键冲突确保主从数据一致排查是否有对从库的直接写入总结MySQL分层架构连接层→Server层分析器优化器执行器→存储引擎层。Binlog在Server层产生Redo/Undo Log在引擎层主从复制 Dump线程主库推送 I/O线程从库写入Relay Log SQL线程从库回放。三个线程协同完成数据同步Binlog三种格式STATEMENTSQL原文日志量小但有不确定性风险→ ROW行级变更精确但日志量大→ MIXED自适应切换。生产环境推荐ROW主从延迟的根本原因主库并行写入从库只有一个SQL线程串行回放。解决方案并行复制、读写分离、关键业务强制走主库主从切换由MHA、Orchestrator、MGR等方案支持。GTID将切换操作从手动定位Binlog位置简化为自动匹配高可用三阶段单主手动切换 → MHA自动切换 → MGR原生多写。根据业务规模和数据一致性要求选择MySQL专栏完结本文是MySQL索引原理专栏的第八篇也是最后一篇。从B树索引到底层原理从联合索引到覆盖索引从MVCC到锁机制从Redo Log到Binlog从慢查询优化到主从复制——八篇文章形成了完整的MySQL知识体系。