内容提要
文章梳理了MySQL高可用五层体系:单机层依靠WAL、redo/binlog两阶段提交与双1参数,保证崩溃时不丢数据;复制层通过异步或半同步方式将数据传到备库;GTID为事务提供全局唯一标识,使切换后能自动对齐且不重复;主备切换需先追平数据,并用fencing防止脑裂;Orchestrator以反证法检测故障并自动选主,probe-agent补充主机内部视角与执行能力。最后强调应用侧也需配合异步化、降级与熔断。
延伸解读
半同步的“隐形降级”风险
文章指出半同步复制在等待备库确认超时后会退化为异步,这是“名义强、实则可能悄悄降级”的坑。现网通过将超时参数设为极大值(8640000毫秒)并叠加三机房部署来避免退化,从而保障RPO=0。读者需注意:半同步的强一致性依赖参数配置和网络稳定性,否则故障时仍可能丢数据。
GTID如何简化切换与防重复
传统基于binlog位点的复制在切换时需人工寻找新主对应位点,极易出错。GTID为每个事务分配全局唯一标识,备库通过GTID集合自动对齐缺失事务,并利用幂等性避免重复执行。这使Orchestrator等自动化工具能安全地重新指向新主,是自动化切换的基础。
Orchestrator的反证法检测与选主逻辑
Orchestrator判断主库是否真死时,不只看自身连接,还检查备库是否仍能连接主库,避免网络抖动导致误切。选主时优先考虑GTID最完整的备库,并结合promotion rule(如must_not排除跨机房只读备)和版本兼容性。这种交叉验证和综合评估降低了误判风险。
应用侧配合:数据库高可用的另一半
文章强调数据库高可用不能只靠DB层,应用也需参与。在DB短暂不可写时,应用可通过异步化+MQ削峰、最终一致性、读降级、写降级/兜底存储、快速失败+熔断等手段优雅降级,避免雪崩。这要求应用建立“数据库随时可能短暂不可用”的意识并准备预案。
Q&A
MySQL 如何保证单机崩溃后已提交的事务不丢失?
MySQL 通过 WAL(预写日志)将修改先顺序写入 redo log,再异步刷数据页;同时用两阶段提交(redo prepare → binlog write → redo commit)保证 redo 和 binlog 一致;崩溃恢复时以 binlog 是否完整落盘裁决 prepare 事务;最后用“双 1”参数(innodb_flush_log_at_trx_commit=1 和 sync_binlog=1)确保每次提交都刷盘,从而实现单机不丢已提交事务。
MySQL 半同步复制中 AFTER_SYNC 和 AFTER_COMMIT 有什么区别?
AFTER_SYNC(5.7+ 默认,推荐)是主库 binlog 落盘后、引擎提交前等待备库确认,确认后才对外可见,一致性更强,幽灵读更少;AFTER_COMMIT 是主库引擎提交后再等备库确认,主库已可见但备库可能还没有,存在主库能读到而备库没有的“幽灵”风险。
GTID 在数据库高可用切换中解决了什么问题?
GTID 为每个事务分配全局唯一且终身不变的标识(server_uuid:transaction_id),备库维护已执行的 GTID 集合。切换新主后,备库通过 MASTER_AUTO_POSITION=1 自动上报集合,新主补差集,无需人肉找位点;同时备库应用事务前检查 GTID 是否已存在,避免重复执行。
主备切换时如何防止脑裂(双主)?
切换前先追平数据,确保备库数据最全;切换后对老主执行 fencing(隔离/围栏),手段包括 set read_only、杀连接、注销元数据等,确保老主再也写不进去,从而避免双主导致数据分叉。
Orchestrator 如何判断主库是否真的故障?
Orchestrator 采用反证法(holistic/cross-check):不仅看自己能否连上 master,还检查 master 的 replica 是否还能连上它。只有 master 连不上且 replica 也连不上时才判定 DeadMaster 并触发切换;若 orc 连不上但 replica 能连上,则视为 UnreachableMaster,不切换,避免网络抖动导致误切。
probe-agent 在 Orchestrator 高可用体系中起什么作用?
probe-agent 运行在 DB 主机本地,弥补 orc 外部探测的短板:通过心跳区分“DB 死”与“网络断”;检查本机负载;用 GTID 差判断大事务;探测磁盘故障;并具备本地写探测能力,为 orc 提供主机内部视角和执行兜底。
应用侧可以采取哪些措施配合数据库高可用?
应用侧可采取:异步化+MQ 削峰(写请求先入队列快速返回);最终一致性(允许稍后收敛);读降级(主库不可用时读备库/缓存);写降级/兜底存储(先落本地或缓存,恢复后补偿);快速失败+熔断(避免连接池被拖垮)。