100ms的SQL把服務器搞崩潰了
前言
一個項目上線了兩個月,除了一些反饋的優(yōu)化和小Bug之外,項目一切順利;前期是屬于推廣階段,可能使用人員沒那么多,當然對于項目部署肯定提前想到并發(fā)量了,所以早就把集群安排上,而且還在測試環(huán)境搞了一下壓測,絕對是沒得問題的;但是,就在兩個月后的一天,系統(tǒng)突然跑的比烏龜還慢,投訴開始就陸續(xù)反饋過來了。
經過排查,原來是頻繁執(zhí)行一條耗時100ms的SQL導致,100ms感覺不長,但就是把系統(tǒng)搞崩了,具體細節(jié)如下。
正文
1. 項目概況
項目采用ABP進行開發(fā),集成統(tǒng)一的認證中心(IDS4),部分數據對接第三方系統(tǒng),拆分后的這個項目架構相對簡單。
考慮并發(fā)量不高,就算是高峰期也不會超過1000,于是就搞了個單臺的數據庫服務器(MySQL),測試環(huán)境中經過壓測,完全能抗住。
上線時,由于線上資源的關系,DB服務器的配置沒有按測試環(huán)境的標準來分配,相關人員想著后續(xù)看情況進行補配。上線推的比較緊,簡單評估了配置風險,初步判斷沒啥大問題,于是就推上線了。
相關技術棧:ABP、IdentityServer4、Autofac、AutoMapper、Quartz.NET、EF Core、Redis、MySQL等,這都不重要,重要的是100ms的SQL把系統(tǒng)搞崩了。
由于系統(tǒng)相對不大,并沒有把分布式日志、調度監(jiān)控,性能監(jiān)控集成上去。
2. 問題排查
上線期間,前期處于使用推廣階段,一切正常。兩個月后的一天,系統(tǒng)處于使用高峰時段,突然陸續(xù)收到反饋:系統(tǒng)有點卡!!!于是趕緊進行排查。
由于系統(tǒng)已經是集群部署的,慢這個問題首先懷疑是數據庫服務器,于是讓DBA的同事排查了一下,沒有鎖,只是有大量事務等待提交(waiting for handler commit),通過如下命令可查的:
?#?查看正在執(zhí)行的腳本
?select?*??from?information_schema.PROCESSLIST?t?where?t.COMMAND?!=?'Sleep'??order?by?time?desc;
看到結果都是插入審計日志記錄導致,一看日志記錄頻率,差不多一秒500條記錄。DBA同事說可能是記錄插入頻繁導致,此時CPU已經爆到100%了,為了快速解決問題,于是就趕緊關掉了一些不必要的日志記錄。
這么一改,稍微降了一點,沒有事務提交的記錄,系統(tǒng)勉強可以撐著用,但是CPU還是在85%~97%波動;
看到這種情況,當然還是不放心,繼續(xù)排查。中間有對服務器的配置產生過懷疑,但非常肯定的是這不是主要原因,于是和DBA的同事繼續(xù)排查。
系統(tǒng)雖然可以正常使用,但時不時的也看看監(jiān)控屏,CPU一直處于高水位狀態(tài),還是有點慌的,因為一有問題,信息和電話都要爆。
突然DBA同事發(fā)現有一個單表查詢的SQL執(zhí)行比較頻繁,于是單獨拿出來試了一下,查詢時間150ms左右,這個表的數據量不大,8萬左右,但沒有加任何索引,因為想著數據量不大,查詢時長還可接受,所以當時就沒有加相關索引。
定位到這條SQL后,想到的第一步就是增加索引,在測試環(huán)境上試了一把,執(zhí)行效率直接飛速提高到1ms;效果如下:

所以和DBA同事達成一致意見,在生成環(huán)境上增加復合索引(創(chuàng)建索引一定要注意字段順序),在中午時候,系統(tǒng)使用頻率不太高,于是就在生成上快速加了索引,我去,CPU一下降到了20%以內,意不意外;就算在使用高峰期,也沒超過20%,通過zabbix工具監(jiān)控看到CPU的效果:

問題算是解決了,總算松了一口氣。
這里有個問題:CPU都爆了為什么沒有報警提醒,這塊DBA同事正在排查相關配置。這里發(fā)現CPU爆了,還是無意的遠程到服務器,發(fā)現很卡,一看CPU才知道爆了。
系統(tǒng)雖小,問題不大,但其實暴露的問題還是挺多。
總結
這次線上小事故暫時分享到這,因為項目不大,所以沒有做那么多監(jiān)控,但以下建議,小伙伴可以參考一下:
頻繁執(zhí)行的SQL語句,一定要保證其執(zhí)行效率,不要小看ms級的優(yōu)化,如果并發(fā)量上來也會是災難;
對應服務器要做好監(jiān)控,指定預警范圍提醒,避免打個措手不及;
盡量避免頻繁的自動刷新;引入實時通信的方式,會減少不必要的訪問壓力。
關于系統(tǒng)頻繁記錄的審計日志,盡量不要和業(yè)務數據庫存放在一起;大量的日志頻繁操作數據庫是很占用IO的。
對于拆分的項目,再加上集群部署,分布式日志管理必須安排上,不然分析日志排查問題是個費時費腦的事
