標籤:
來新公司前,領導就說了,線上生產環境Mysql庫經常會發生日間記憶體爆掉被killed的情況,結果來到這第一天,第一件事就是要根據線上伺服器配置最佳化配置,同時必須找出現在mysql記憶體持續增加爆掉的原因,雖然我主業已經不是資料庫更不是dba了。
這個業務上基本山算是OLTP,盤中都是很簡單的SQL,所以效能上雖然有些SQL有些慢,但看過slow-log和performance_schema,可以忽略不計。
初步瞭解,應用是java開發的,但是應用端沒有出現過OOM的情況,也不見卡死或者越來越慢的情況。
從周一開始查到今天下午,尼瑪mysql跟memory leak有關的幾乎任何能夠查到的buglist都被一個個review驗證了,差不多能遇到的各種可能性都測試過,包括但不限於concat可能存在記憶體配置泄露,google版jemalloc可能導致記憶體增長,2.6.32版本vm.swappiness=0行為發生變化可能導致記憶體bug,mysql memory暫存資料表釋放可能存在問題,大量表的drop/create會導致dict_mem無限增長,幾乎驗證了mariadb/percona/mysql社區版本5.5,5.6,5.7各個版本,分析了各種mysql記憶體組成情況的指令碼以及驗證工具,尼瑪都沒找到問題。。。
嘗試過將mysql 暫存資料表從memory改到innodb,又改到myisam已驗證可能存在問題,均沒有發現明顯問題。
有文章又提及LOB可能會釋放存在問題,仔細檢查發現,業務表沒有LOB類型,但似乎有定時任務不停在查詢mysql.proc,需要跟開發確認原因。
某個文章又提及5.0版本中client_statisitics中host超過16導致/tmp空間持續增長導致記憶體持續增長,我們用的percona server 5.6,經驗證後,不是該問題所致。。不過順帶發現一個營運用python寫的指令碼不停地create/drop串連,要求整改了。。
線上環境基本上所有業務編寫在預存程序中,一個過程套用其他五六個預存程序,各種奇葩邏輯。。。無奈只能做到營運旁邊守著控制台盯著,已經排除了各種mysql伺服器自身導致的問題,且驗證了肯定不可能是innodb和其他伺服器端可見的記憶體的問題之後,開始從應用程式入手,基本上串連就50個不到,有差不多一半的串連都是兩個定時任務在即時更新風控相關的值,有資料更新程式就整個過程跑,不然就基本上跳過,裡面使用了mysql暫存資料表。沒資料更新時雖然一直跑,但是mysql記憶體沒有增長,到了盤中有資料之後,記憶體就每隔幾秒nM到一二十M的增長,然後增長到了mysqld的記憶體占整個OS記憶體的90%左右,然後top RES維持在該值,VIRT開始繼續增長,直到盤後的備份時因為OOM被os killed。盯著看了兩天之後,本來昨天就打算在記憶體90%時逐台應用程式掐掉看下是不是用戶端串連導致的,只是營運後來走了。。今天收市後讓營運把接入機重啟了下,瞬間mysqld記憶體佔用回到了50%。問題的現狀總算是可以重現了。
查看了下應用配置並跟架構確認了下,目前用的c3p0。
現在剩下的就是明天繼續盯盤檢查時c3p0串連配置問題所致,還是mysql暫存資料表問題(在測試環境各個版本都類比了,都沒重現線上問題,估計不是這個問題所致是大機率),要是還不是這兩個問題所致, 只能代碼慢慢debug最佳化下去,然後再找到根本原因。
。。。嚴重吐槽。。。
mysql查看innodb/myisam之外記憶體使用量情況的工具基本上沒有。網上的各種什麼mysqltuner.pl,my_memory,包括mysql 5.7的memory performance_schema,各種的瞎猜測。。
唯一可靠的估計就是valgrind,可惜沒法attach到線上進程。。
線上mysql記憶體持續增長直至記憶體溢出被killed分析