运维工程师面试题精选:数据库运维实战与高可用
数据库运维面试最怕背概念:参数背得再熟,主从切换手抖、备份没演练过,一样救不了场。这组题按生产顺序组织——先保数据(切换、备份、容灾),再保性能(慢查询、连接、CPU 打满),最后是 Redis 专题。每题先给结论再列要点,流程、证据、风险点讲全才算过关。
本文题目一览
- 主从切换的完整流程与风险点
- 备份恢复演练怎么做才算数
- 慢查询治理的闭环:发现、定位、优化、防复发
- 连接池与连接数怎么规划
- Redis 哨兵与集群模式的区别与故障切换
- Redis 大 key 与热 key 的发现与治理
- 数据库磁盘空间治理:binlog 清理与表碎片
- 跨机房容灾方案的取舍:同步、异步与 RPO/RTO
- 实战题:数据库 CPU 打满的排查路径
- 主从延迟的成因与排查
- 死锁与元数据锁(MDL)怎么定位
- 连接数打满的应急处置
- Redis 持久化与内存淘汰策略的取舍
高可用与备份恢复
1. 主从切换的完整流程是什么?有哪些风险点?
结论:切换的本质是三件事——确认数据一致、完成流量切换、隔离旧主防脑裂。只说"提升从库、改连接串"的回答不完整。
- 切换前:确认从库复制延迟归零、relay log 全部回放完,新主置为可写前先把旧主置只读并断开写入入口;
- 切换中:提升从库(停止复制、关闭 read_only),流量通过 VIP、代理层或配置中心统一切到新主,避免逐台改应用配置;
- 切换后:在新主写一条标记记录,多端核对可见;旧主必须隔离,不能直接当从库挂回,要按位点或全量重建后再同步;
- 风险点:双主同时可写造成数据分叉、GTID 位点不一致导致切换后复制报错、长事务未提交完就切换丢数据、应用残留旧连接继续往旧主写。
2. 备份恢复演练怎么做才算数?
结论:备份成功不等于能恢复。演练算数的标准是"在隔离环境里真恢复出来、启动成功、数据校验通过,并实测出恢复耗时"。
- 完整性:全量备份与增量/binlog 链都要校验,断链的备份等于没有备份;
- 恢复实测:定期自动把备份恢复到隔离实例,启动后做行数、校验和、关键业务表抽查,再跑一遍应用冒烟;
- 量化产出:记录实际 RTO(从发起恢复到可提供服务)和实际 RPO(能恢复到的时间点),与业务承诺对比,差距形成整改项;
- 演练报告要有失败记录:恢复中遇到的问题、补的步骤,比"演练成功"四个字有价值得多。
# 恢复后的一致性抽查示例
mysql -e "SELECT COUNT(*) FROM app_db.orders;"
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000123 | tail -20
3. 跨机房容灾方案怎么选?RPO 和 RTO 怎么定?
结论:先按数据等级定 RPO/RTO,再谈技术方案;同步、异步没有优劣,只有延迟、可用性和成本的取舍。
- 异步复制:主库性能不受对端影响,但机房级故障时 RPO 等于复制延迟,极端情况下丢分钟级数据;
- 半同步/同步:RPO 接近零,代价是写入延迟随跨机房 RTT 上升,网络抖动时主库会被对端拖住,要设计退化策略;
- 双活只适合能解决写冲突的业务:自增步长、唯一键冲突、数据回环都要有方案,否则双活就是双写事故;
- RTO 不只算数据库切换,还要算流量切换与应用预热,演练实测值才是对外承诺的依据。
性能治理
4. 慢查询治理的闭环怎么做?
结论:按"发现 → 定位 → 优化 → 防复发"走完闭环,只会加索引的是半成品答案。
- 发现:开启慢日志并设合理阈值,用 Performance Schema 的 digest 聚合统计按总耗时排序找 TOP SQL,而不是盯单条最慢的;
- 定位:EXPLAIN 看访问类型、实际选用的索引、预估行数和 Extra(Using filesort、Using temporary 是常见信号),再判断是索引还是写法问题;
- 优化:补索引、改写 SQL(深分页改游标式翻页、大事务拆批)、冷热数据分离,优化后用同一组参数复测对比;
- 防复发:上线前 SQL 评审、慢查询日报自动推送责任人、核心接口耗时告警,让新慢查询在变成事故前被看见。
5. 连接池与连接数怎么规划?
结论:连接数按"实例能承受的并发活跃线程"算,不是越大越好;连接廉价的是句柄,昂贵的是每个连接背后的会话内存与活跃线程调度。
- 估算:活跃连接会占用排序缓冲、临时表等会话级内存,max_connections 须结合实例内存反推,并留运维通道余量;
- 看两个指标分开判断:Threads_connected 是连接总数,Threads_running 才是真正干活的并发,后者长期远超 CPU 核数就是在排队烧 CPU;
- 多应用共用一个实例时,总连接数等于各应用连接池上限之和,要统一盘点,防止每个应用都按"最大"配;
- 治理:设置连接超时与空闲回收,连接池开启有效性检测,防连接泄漏慢慢吃满。
6. 实战题:数据库 CPU 打满,你的排查路径是什么?
结论:先抓"谁在跑",再谈优化。CPU 打满绝大多数是少数 SQL 的并发放大,按现场证据一步步收敛,不要上来就重启或加配置。
- 第一步定性:看 Threads_running 是否异常抬升,排除备份、统计收集等计划任务的影响;
- 第二步抓现行:查正在执行的会话列表和按 digest 聚合的 TOP SQL,定位耗时与调用量双高的语句;
- 第三步分类型:全表扫描突增(新上线 SQL 或执行计划突变)、锁等待连锁(看似在跑其实在等)、连接风暴(应用重试放大)、数据量跨过临界点后索引失效;
- 应急处置:kill 问题会话或对来源应用限流,先保核心业务,再做根因修复;
- 复盘:把出事 SQL 纳入慢查询治理与上线评审,补上对应的监控告警。
SHOW FULL PROCESSLIST;
SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;
7. 主从延迟的常见成因与排查方法?
结论:延迟先看积压量再看成因,Seconds_Behind_Master 在并行复制下并不完全可靠,要结合位点差值判断。
- 成因一:主库大事务(一次更新百万行),从库回放只能整段执行完才推进位点;
- 成因二:从库回放能力不足——并行复制未开或并行度不够、从库硬件弱于主库、磁盘 IO 是瓶颈;
- 成因三:无主键表的大范围更新,从库回放要逐行扫描定位,是延迟的经典来源;
- 排查:看 relay log 积压量与 GTID 位点差、回放线程状态、从库 IO 与 CPU;治理手段是开启并行复制、拆分大事务、给大表补主键、延迟敏感业务降级读主。
8. 死锁与元数据锁(MDL)怎么定位?
结论:死锁看引擎状态的最近记录,MDL 看谁持有表级元数据锁——两类定位入口完全不同。
- 死锁:用 SHOW ENGINE INNODB STATUS 看 LATEST DETECTED DEADLOCK 段,能看到两个事务各自持有和等待的锁与 SQL,回滚代价小的事务会被引擎自动牺牲;
- MDL 阻塞:长事务(哪怕一条未提交的查询)持有表的 MDL,后面的 DDL 与新查询全部排队,表面像"数据库卡死";
- 治理:事务瘦身、批量操作固定加锁顺序、DDL 放在低峰并设置锁等待超时、先 kill 持锁长事务再执行变更;
- 预防:开启死锁与锁等待日志留痕,核心表的大事务操作纳入评审。
SHOW ENGINE INNODB STATUS\G
SELECT * FROM performance_schema.metadata_locks WHERE LOCK_STATUS = 'GRANTED';
9. 连接数打满(Too many connections)怎么应急?
结论:先恢复通道,再找来源。处理顺序错了——比如直接重启实例——会把小事故放大成大事故。
- 先用预留给高权限账号的连接通道登入(MySQL 会为 SUPER 权限保留额外连接),确认实例本身还活着;
- 按用户和来源主机聚合现有连接,定位是哪个应用、哪台机器在吃连接,区分正常流量上涨与连接泄漏;
- 临时处置:清理长时间空闲连接、对异常来源限流或摘除问题应用实例;直接调大 max_connections 要先评估内存是否吃得住;
- 根因常见于:应用连接池配置过大且实例多、连接用完不归还的泄漏、发布后新旧版本同时在线导致连接翻倍。
SELECT USER, SUBSTRING_INDEX(HOST, ':', 1) AS src_host, COUNT(*) AS cnt
FROM information_schema.PROCESSLIST
GROUP BY USER, src_host ORDER BY cnt DESC;
空间与维护
10. 数据库磁盘空间怎么治理?binlog 和碎片怎么处理?
结论:空间治理靠保留策略和增速预警,不靠出事后手动删文件;binlog 只能用官方命令清理,直接 rm 数据文件是事故操作。
- binlog:设置自动过期(binlog_expire_logs_seconds),清理前确认所有从库已消费到位点,需要手动清时用 PURGE BINARY LOGS 按时间或位点清;
- 碎片:大量删除后表空间不会自动回收,评估碎片率后用在线重建工具在低峰处理,预留双倍空间并监控耗时;
- 增速治理:对数据目录和单表大小做增速曲线与容量预警,提前识别异常写入(比如某张日志表突然暴涨);
- 大字段与历史数据:冷数据归档、按时间分区并定期下线旧分区,比无限扩容磁盘更可持续。
SHOW BINARY LOGS;
PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY);
Redis 专题
11. Redis 哨兵与集群模式有什么区别?故障切换怎么做?
结论:哨兵解决的是单分片的高可用,集群解决的是容量与吞吐的分片扩展,两者不是同一维度的选项。
- 哨兵模式:一主多从,哨兵集群监控主节点,主观下线加客观下线(quorum 达成)后选举新主并通知客户端改连,数据总量受单机内存上限约束;
- 集群模式:数据按 16384 个槽分片到多个主节点,每个主带从节点,故障时从节点顶替并接管槽位,扩容靠槽迁移(reshard);
- 选型:数据量装得下、要的是简单可靠高可用,选哨兵;容量或写入吞吐超过单机,选集群;
- 注意点:集群模式下多 key 操作要求同槽(用 hash tag 归拢),事务与 Lua 的跨槽限制要在设计阶段就交代清楚。
12. Redis 大 key 与热 key 怎么发现、怎么治理?
结论:大 key 伤在阻塞与迁移,热 key 伤在单点倾斜;发现靠工具加监控,治理靠拆分与分流。
- 发现大 key:用 redis-cli --bigkeys 抽样扫描,结合内存 TOP key 统计;发现热 key:开启 LFU 后用 --hotkeys,或从监控看单分片 CPU、带宽明显倾斜;
- 大 key 危害:删除时阻塞主线程、主从同步与槽迁移时传输卡顿、内存分配不均;删除要用 UNLINK 异步释放,禁止在高峰期直接 DEL 超大 key;
- 热 key 危害:流量全压在一个分片一个 key 上,单点 CPU 打满而整体水位不高;治理手段是应用本地缓存、多副本读分流、key 加随机后缀打散后聚合读;
- 预防:接入层对 value 大小设上限并告警,大 key 的产生方(多为批量聚合写入)要在代码评审阶段拦截。
13. Redis 持久化与内存淘汰策略怎么选?
结论:持久化按"能容忍丢多少"选,淘汰策略按"Redis 在业务里扮演什么角色"选,两项都要在上线前定死并写进容量基线。
- RDB:快照恢复快、文件紧凑,但两次快照之间的数据会丢,适合可回放、可重建的数据;
- AOF:appendfsync everysec 是常用折中,最多丢约 1 秒,代价是文件大、重写期 IO 与内存开销明显;要求兼顾时可用混合持久化;
- 淘汰策略:纯缓存用 allkeys-lru/lfu;混有不能丢的数据时用 volatile-* 系列并慎重给关键 key 设过期——策略设错会在内存压力下误删或拒绝写入;
- 容量:maxmemory 不要按机器内存顶格设,给 fork 子进程(持久化与重写)留足余量,内存水位与碎片率都要有告警。
面试官视角
这组题的区分度不在名词,而在三个细节:一是顺序感——切换先隔离旧主、应急先保通道、排查先抓现行,顺序错说明没真正上过手;二是量化意识——RTO/RPO 报实测值、延迟看位点差、连接数能反推内存;三是闭环习惯——最后能落到监控、评审、演练等防复发动作。只会背参数、讲不出风险与验证方法的,经验再长也要打问号。







