阿里云的数据库的带宽是分档次的,默认是PL1,如果降级改使用PL0会从磁盘存储费用上节约大约45%的金额,由于目前“要把寒气传给每个人”,公司开始关注现金流,所以要求节流降本,于是很多的数据库都开始评估是否可以从PL1降配成PL0:
我们有一个数据库集群,里面有8个实例,先降了其中一个实例为PL0,观察了几天,发现日常没啥问题,于是又降了3个实例,灰度达到了50%。又平稳的走了几天,观察磁盘的吞吐都非常稳定,于是晚上11点把全部的实例都降了PL0。但是第二天早上突然系统开始告警,从日志来看是大量的数据库update超时,很多的SQL的耗时高:
二话不说,赶紧回滚成PL1,发现数据库的带宽也开始激增,CPU开始激增:
最后在DBA的提示下发现这个库当时是在optimize,原来是optimize把所有的带宽都占据了,导致正常的业务请求90%都会卡住,因为卡住而失败的请求又不断地重试,这样分母越来越大,请求成功率就暴跌。于是紧急KILL掉optimize语句和堆积的业务语句(堆积太多了,如果要消费掉要好久,这样就耽误其他正常的业务了),系统侧开始恢复正常,剩下的就是业务侧的手动补数据止血…
optimize的原理其实很简单:
1.创建一张新的临时表 tmp
2.把旧表锁住,禁止插入删除,只允许读写 (alisql已经优化了,它不会被锁住)
3.把数据不断的从旧表,copy到新的临时表
4.等表拷贝完后,进行瞬间的rename操作
5.旧表删除掉
由此可见,optimize是一个特别消耗带宽的操作,而且如果数据库delete的内容很多,optimize会执行很久,难免会跟正常业务请求重合,进而造成业务抖动。
这个事情之后,optimize就成了一个高危的操作(MYSQL官方也不建议很频繁的optimize),首先要一定避开业务时间,如果做成定时任务的话,到了业务时间一定要暂停,过了时间后再跑。
从这个故障里,我们也要重新的分析一下业务链路,出现告警的系统是结算的系统,他们一早更新账目状态,发现数据库update失败而请求失败。但是由于处理时间过长,而且这个数据库还有货品出仓的信息,结果影响了货品的出仓。所以我们要审视一下,结算的链路不应该影响出库这个发货链路,所以后期打算把结算做成异步链路弱依赖,这样强保出仓链路的稳定。