数据库运维这活儿,干久了你会发现,它不像外界想的那么高深莫测,但绝对比想象中更磨人。你维护的不只是一堆跑着SQL的进程,而是整个业务系统的命脉。日常监控和故障应对,就像开车时的仪表盘和备胎,前者让你心里有数,后者让你在爆胎时不至于车毁人亡。今天就把这些年踩过的坑、攒下的经验,掰开揉碎了跟你聊聊,从监控到救火,一条龙说透。

先聊日常监控。很多人以为监控就是装个Zabbix或者Prometheus,看CPU、内存、磁盘用了多少,绿了就万事大吉。这想法太天真了。真正的监控,是你要对数据库的“脾气”了如指掌。比如MySQL,你得盯着慢查询日志,不是看它有没有,而是看它每一条的耗时趋势。昨天同样的查询要80毫秒,今天突然跳到200毫秒,哪怕还没到慢查询阈值,这就是警报。还有连接数,别等它报“too many connections”才去查,那会儿业务已经报错了。你得提前设个阈值,比如平时稳定在50个连接,那跑到80就要去看是哪个应用在偷连,是连接池没释放,还是真有突发流量。监控的粒度要细到能反映出“异常的前兆”,而不是只反映“已经挂了”。
再说说磁盘空间,这绝对是运维的“隐形杀手”。很多事故不是CPU打满,也不是内存爆了,就是磁盘悄悄满了。而且它有个狠毒的地方——它不会突然满,它是慢慢涨的。今天剩20%,你觉得没事,明天15%,后天12%,等哪天业务高峰期突然涨到5%,binlog一写,瞬间就满了。数据库直接只读,应用层立马报错,用户开始骂娘,你才慌慌张张去清理。所以监控磁盘,不能只看使用率,要看增长速率。给每个库、每个表的数据量做个基线,定期对比,哪个表一周涨了10%,就得评估是不是要归档了。日志文件也是,binlog、redo log、error log,它们的增长速度比业务数据还猛,经常是磁盘爆掉的元凶。
监控中间件和连接池,也容易被忽略。你们可能用了MyCat、ProxySQL或者ShardingSphere,这些家伙本身也是进程,也会挂,也会内存泄漏。你得监控它们到后端数据库的连接数,以及它们自身的线程池状态。我碰到过一次,前端应用连接池配置得太大,每个节点100个连接,三个节点就是300个,而数据库的最大连接数才200,结果数据库直接被压垮。你查数据库这边,连接数爆满,以为是攻击,回头一查是应用配置不合理。这种问题,光盯着数据库的监控还发现不了,得把整个链路打通了看。
日常巡检,也讲究个“固定动作”。我习惯每天早上十点,趁着业务低峰期,跑一遍固定的巡检脚本。查什么?查主从复制的延迟,这个要重点看。主从延迟秒级是正常的,一旦变成分钟级,甚至小时级,那就麻烦了。查死锁记录,查InnoDB的状态,查缓冲池命中率。命中率低于95%,说明内存配小了,或者有大量全表扫描。还有,看看error log里有没有奇怪的警告,比如“connection reset by peer”这种,虽然不影响业务,但频率高了说明网络或者防火墙有问题。这些固定动作,就像老中医的望闻问切,每天看看,心里有底。
真正到了故障应对环节,考验的就是心理素质和预案熟练度了。先说最常见的——数据库连接数被打满。这时候别急着去kill进程,先分清是“真满”还是“假满”。真满就是连接全被正常业务占用了,假满是有些连接卡在某个状态,比如Sleep、Waiting for table metadata lock,这些是僵尸连接,占了茅坑不拉屎。用show processlist看一眼,如果大部分是Sleep且时间很长,那就是应用连接池没回收,直接kill掉这些Sleep连接,瞬间就能腾出空间。如果是metadata lock,那得找到持有锁的那个事务,看看是哪个长事务没提交,把它kill了,或者等它跑完。这里有个小技巧,别一次性kill太多,先kill个几十个,缓解一下,再慢慢清理,不然把正在跑的好交易也误杀了。
主从延迟,也是让人头秃的故障。延迟一旦上来,你写主库没问题,但读从库的应用就会读到旧数据,业务上叫“数据不一致”。这时候先别慌,看看延迟是在涨还是在降。如果只是瞬间的延迟,比如主库做了个大事务,从库在追,那等等就好。如果延迟稳定在某个高位不下,那得看从库的硬件IO是不是瓶颈,或者有没有个大查询在从库上跑着,抢了IO资源。实在不行,还有一招杀手锏——让从库跳过这个事务,或者重新拉一个从库。但这招要慎用,跳过事务可能造成数据永久不一致,得跟业务方确认好,这个事务的影响可不可接受。
还有一个故障,比连接数爆满更吓人——数据库突然只读。这台机器可能磁盘满了,或者主从切换后配置不对。遇到只读,第一反应是看磁盘,df -h看一眼,满了就清。清理的时候注意,别光删binlog,要确认这些binlog是不是已经被备份了,不然删了无法恢复,那可是大事故。如果磁盘还有空间,那就是参数问题,看看readonly和superreadonly是不是被误设置了。这时候千万别重启,重启可能起不来,得先冷静分析。
再聊一个高级点的故障——性能突然劣化。比如页面从500毫秒变成5秒。这时候别一头扎进数据库,先看应用日志,是不是有慢接口调用。如果确认是数据库的问题,那就抓正在执行的SQL,用performanceschema或者sys库,看看有没有长时间运行的查询。很可能是一个新上线的功能,写了个烂SQL,没走索引,或者大表join小表,驱动表选错了。这时候,你有两个选择:一是直接kill掉这个查询,让业务先恢复,再跟开发沟通优化SQL;二是用explain分析一下,给它加个索引,或者改写SQL。但记住,线上操作要快、准、狠,别犹豫,业务恢复是第一优先级。
故障应对的最高境界,不是反应快,而是复盘透彻。每次故障处理完,别急着庆祝,拉上开发、DBA、运维一起复盘。问三个问题:第一,根因是什么?是真没监控到,还是监控到了没报警,还是报警了没人看?第二,处理过程有没有可以优化的?比如是不是能更快定位到问题,是不是有些操作可以做成自动化脚本?第三,怎么防止下次再发生?是加监控、加告警,还是改架构、做限流?我见过很多团队,故障处理得挺溜,但从来不复盘,结果同一个坑踩三次,这种就是白干了。
回到题目说的“全攻略”。其实数据库运维的核心要点,总结起来就三句话:监控要看得见前兆,故障要处置得果断,复盘要挖得到根子。日常监控不是走流程,是养兵千日;故障应对不是凭运气,是用兵一时。你把每一分钟的监控数据都当回事,把每一次故障都当成一次演习,时间久了,你就能从“救火队员”变成“防火专家”。到那时候,你会发现,数据库运维这活儿,虽然磨人,但真挺有意思的——它像个老朋友,你摸透了它的脾气,它会用稳定运行回报你。别嫌监控烦,别怕故障来,你准备的每一分,都会在关键时刻变成业务连续性的底气。


