数据库可靠性工程与生产排障

数据库故障往往不是单一的“数据库问题”。连接池耗尽可能来自应用重试,复制延迟可能来自大事务,磁盘写满可能由日志保留失控,慢查询也可能是统计信息、锁等待或数据分布变化。可靠性工程的目标,是建立从用户症状到连接、事务、锁、执行计划、存储和复制的证据链,并确保恢复操作不会扩大数据风险。

本文以 MySQL 与 PostgreSQL 的通用方法为主。具体命令、视图和参数应以实际版本官方文档为准,生产变更前必须备份并在测试环境验证。

一、数据库可靠性的四个目标

  1. 正确性:提交的数据不丢失、不重复、不产生不可解释的状态。
  2. 可用性:在目标时间内接受请求,并对故障进行切换或降级。
  3. 性能:在设计负载和数据规模下满足延迟与吞吐目标。
  4. 可恢复性:能够从误操作、损坏和灾难中恢复到明确时间点。

高可用不能替代备份:主库误删除会复制到从库,存储损坏也可能同步传播。备份同样不能替代高可用:恢复备份需要时间,无法承担秒级切换目标。

二、建立最小观测面

至少收集以下信息:

  • 连接总数、活跃连接、等待连接和连接创建速率;
  • QPS/TPS、事务提交和回滚数量;
  • P95、P99 查询延迟及慢查询样本;
  • 锁等待、死锁、长事务和空闲事务;
  • 缓存命中、临时文件、排序和全表扫描;
  • 磁盘使用、IOPS、吞吐、延迟和队列深度;
  • WAL/binlog 增长速度、保留量和复制延迟;
  • 备份结果、恢复演练结果和最近可恢复时间点。

监控标签应包含集群、实例、角色、数据库和版本,但不要把完整 SQL、用户输入或高基数 ID 直接作为指标标签。

三、生产故障的第一分钟

先控制风险,不要立即重启数据库:

  1. 确认用户症状、开始时间和影响范围;
  2. 判断是连接失败、查询变慢、写入失败还是数据错误;
  3. 暂停高风险发布、批处理和结构变更;
  4. 采集当前连接、锁、事务、复制和系统资源快照;
  5. 检查磁盘是否接近写满、文件系统是否只读;
  6. 建立事故时间线并指定操作人;
  7. 任何终止会话、切主或重启操作都记录理由和验证结果。

重启可能暂时清空连接和锁,但也会丢失现场证据、延长恢复、触发大规模重连,甚至使未完成恢复的节点反复启动。

四、连接耗尽怎么排查

现象

  • 应用出现 connection timeout 或 too many connections;
  • 数据库 CPU 不一定很高;
  • 活跃连接少,但空闲连接很多;
  • 连接创建速率突然增加。

排查顺序

  1. 对比连接上限、当前连接和真正执行中的连接;
  2. 按应用、用户、来源地址和状态分组;
  3. 检查连接池是否泄漏、最大池是否按实例数叠加过大;
  4. 检查长事务、idle in transaction 和网络中断;
  5. 检查应用是否在超时后无退避重试;
  6. 确认代理、负载均衡和数据库连接生命周期是否一致。

不要把 max_connections 无限调高。每个连接占用内存和后台结构,更多连接会放大上下文切换与锁竞争。优先控制应用连接池总量,并为管理、监控和故障处置保留连接配额。

五、慢查询不等于缺少索引

慢查询需要分层判断:

  • 是否等待锁,而不是执行慢;
  • 执行计划是否变化;
  • 估算行数与实际行数是否偏差巨大;
  • 是否读取了不必要的列和行;
  • 排序、聚合是否写入临时磁盘;
  • 缓存是否冷却,I/O 延迟是否异常;
  • 参数值或数据倾斜是否导致计划不适用;
  • 数据量增长后原有索引是否失去选择性。

使用 EXPLAIN 或 EXPLAIN ANALYZE 时要理解风险:后者会实际执行语句,针对写语句或高成本查询必须先在安全环境评估。不要为了一个查询建立大量重叠索引,索引会增加写放大、占用空间并延长维护。

六、锁等待与死锁

锁等待表示事务正在等待资源;死锁表示形成循环等待,数据库通常会中止其中一个事务。处理步骤:

  1. 找出阻塞会话、被阻塞会话和等待时长;
  2. 获取事务开始时间、SQL、应用来源和锁对象;
  3. 判断阻塞者是否仍在工作,还是遗留空闲事务;
  4. 优先联系业务确认,再决定取消语句或终止会话;
  5. 保留死锁图或数据库日志,修复访问顺序和事务边界。

常见根因包括事务过长、批量更新过大、不同代码路径以不同顺序更新资源、缺少索引导致锁定范围扩大,以及用户交互期间保持事务不提交。

七、长事务的隐性风险

长事务除了持有锁,还可能:

  • 阻碍垃圾回收或旧版本清理;
  • 导致 undo/WAL/binlog 大幅增长;
  • 延长复制追赶和恢复时间;
  • 让备份和 DDL 行为变得复杂;
  • 在失败回滚时占用大量时间和 I/O。

应用应设置合理的语句和事务超时,大批量操作分批提交,并保证重试幂等。不能只在数据库侧强制终止而不修复应用逻辑。

八、复制延迟排查

先确认延迟定义:时间延迟、日志位置差、待应用字节数或回放时间可能含义不同。排查维度包括:

  • 主库是否产生大事务或突发写入;
  • 网络吞吐、丢包和跨区域延迟;
  • 从库 I/O、CPU 和锁竞争;
  • 单线程或并行回放能力;
  • DDL、长查询或备份是否阻塞回放;
  • 日志保留是否足以支撑从库追赶;
  • 从库读取流量是否挤占恢复资源。

如果从库已经落后,不应盲目切主。先确认它的数据时间点、可接受的数据损失和客户端写入路径。

九、磁盘接近写满

数据库磁盘满属于高风险事故。首先确认增长来源:数据文件、事务日志、归档日志、临时文件、审计日志、慢日志、备份或快照。

安全处置原则:

  • 不直接删除正在使用的数据或日志文件;
  • 不在未确认恢复链的情况下删除 WAL/binlog;
  • 优先停止异常增长来源和非必要写入;
  • 扩容或迁移前确认文件系统和存储支持方式;
  • 清理备份要遵守保留策略,并确认有其他有效副本;
  • 恢复空间后检查实例是否只读、复制是否中断、归档是否恢复。

建议为数据、日志、临时文件和备份设置独立阈值,按增长速率预测耗尽时间,而不是等到固定的 90% 告警。

十、高可用切换前的决策

切主至少要回答:

  1. 原主库是否仍可能接受写入,如何避免双主;
  2. 候选节点的数据是否足够新;
  3. 允许的数据损失是多少;
  4. 应用、代理、DNS 和连接池如何切换;
  5. 原主恢复后如何隔离和重新加入;
  6. 切换后如何验证写入、读取、任务和复制;
  7. 谁批准可能的数据损失。

自动故障转移也要有仲裁和防脑裂设计。网络分区时“两个节点都认为对方故障”是比单节点停机更危险的情况。

十一、备份与恢复验证

备份成功日志不能证明可恢复。至少进行:

  • 文件完整性和校验检查;
  • 在隔离环境恢复全量备份;
  • 应用增量日志恢复到指定时间点;
  • 验证表数量、关键记录、约束和应用查询;
  • 记录实际 RTO、可恢复时间点和操作步骤;
  • 验证密钥、证书、账号和外部依赖是否齐全。

恢复演练应覆盖误删、实例损坏和区域不可用等不同场景。演练数据必须脱敏并限制访问。

十二、结构变更的生产保护

  • 评估锁级别、扫描量、额外空间和日志量;
  • 对大表使用分阶段、可暂停的方法;
  • 避开备份、批处理和高峰窗口;
  • 设置锁等待和语句超时,避免长时间阻塞;
  • 先扩展结构,待应用兼容后再收缩旧结构;
  • 观察复制延迟和从库查询;
  • 明确停止条件,不能以“已经执行一半”为理由继续。

十三、故障证据模板

用户症状:订单查询超时,写入正常
开始时间:10:21
数据库角色:主库写入,从库读取
连接:总连接 92%,活跃 18%,等待连接增长
锁:无大规模锁等待
慢查询:某报表查询 P99 从 2s 升到 38s
系统资源:CPU 45%,磁盘读延迟从 3ms 升到 70ms
根因:报表全表扫描与备份读取重叠
止血:停止报表任务,限制备份读取速率
修复:增加合适索引并错开任务窗口
验证:P99 恢复、连接池恢复、复制延迟正常

十四、常见错误

  • 看到慢就加索引,不检查锁和执行计划;
  • 看到连接满就提高连接上限;
  • 故障时先重启,丢失现场证据;
  • 从库延迟时直接切主;
  • 手工删除数据库日志释放磁盘;
  • 只备份不恢复,密钥和配置也没有纳入;
  • 监控只有实例存活,没有业务查询与复制状态;
  • 数据库变更与应用全量发布同时执行。

十五、把排障结果转化为长期改进

事故恢复后应把临时命令和判断过程整理为可复用资产:

  • 将有效查询写入只读诊断脚本,并标明适用版本和权限;
  • 把“连接耗尽、复制延迟、磁盘增长”等症状映射到 Dashboard;
  • 为危险命令增加确认、目标检查和影响说明;
  • 将根因对应到代码、索引、参数、容量或流程整改;
  • 为同类问题补充合成查询和提前量告警;
  • 用恢复演练验证修复,而不是只关闭工单;
  • 记录哪些证据当时缺失,并补齐日志或审计字段。

数据库 Runbook 应区分“只读取证”“可逆止血”和“可能改变数据”三类操作。终止会话、切主、跳过复制事件和修改系统表等操作不能与普通查询混在一起。对可能造成数据损失的步骤,应写明审批人、备份点、停止条件和业务验证。

十六、生产检查清单

  • [ ] 连接、事务、锁、慢查询、磁盘和复制均有监控;
  • [ ] 管理与故障处置保留独立连接能力;
  • [ ] 长事务、空闲事务和语句超时有治理规则;
  • [ ] 数据库变更具有兼容窗口和停止条件;
  • [ ] 高可用方案有防脑裂和数据损失决策流程;
  • [ ] 备份经过隔离恢复与时间点恢复验证;
  • [ ] 容量预测包含数据、日志、临时空间和复制保留;
  • [ ] Runbook 记录采证、止血、恢复和业务验证步骤。

十七、参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-18 22:49:34

results matching ""

    No results matching ""