MySQL預編譯語句過多告警排查及解決方案
業(yè)務背景
在使用Spring Cloud Alibaba搭建的微服務架構中,項目采用ShardingSphere進行分庫分表,MyBatis-Plus作為持久層。線上環(huán)境突發(fā)大量預編譯語句過多的數(shù)據(jù)庫告警,導致系統(tǒng)性能下降。
排查過程
1. 初步排查:聯(lián)系云數(shù)據(jù)庫廠商
首先,聯(lián)系云數(shù)據(jù)庫服務廠商協(xié)助排查,確認問題是由于預編譯緩存未被釋放,導致占用過多數(shù)據(jù)庫資源。
2. 排查連接池配置
懷疑問題與連接池有關,特別是考慮到線上負載較高的高峰時段。經(jīng)過檢查,項目使用的是HikariCP連接池,相關配置如下:

特別關注兩個參數(shù):
maxLifetime: 連接池最大生命周期idleTimeout: 連接池空閑超時時間
在進行斷點調試后,由于項目使用了Sharding-JDBC,某些參數(shù)并未按照Hikari的默認值生效,而是被Sharding進行初始化配置。Sharding的相關代碼如下:

此時可以初步排除連接池配置問題,因為Sharding已將idleTimeout配置為60秒。
3. 分析HikariCP源碼與Statement Cache問題
深入分析HikariCP源碼,查找與PreparedStatement緩存相關的內(nèi)容,發(fā)現(xiàn)README.md關鍵描述:
Statement Cache
HikariCP與其他連接池(如Apache DBCP、Vibur、c3p0等)在處理PreparedStatement緩存時的區(qū)別:
- HikariCP: 不提供
PreparedStatement緩存,原因是連接池層級緩存PreparedStatement只能按連接緩存,導致內(nèi)存占用過大。 - 其他連接池: 許多連接池提供
PreparedStatement緩存,但這會導致大量PreparedStatement對象及相關執(zhí)行計劃在內(nèi)存中存儲,影響性能。
HikariCP并不緩存PreparedStatement,因為多數(shù)數(shù)據(jù)庫JDBC驅動已經(jīng)內(nèi)置緩存機制,可以跨連接共享執(zhí)行計劃,避免重復占用內(nèi)存。
要點:
- 連接池層級的
PreparedStatement緩存問題:在連接池層緩存會導致大量內(nèi)存占用,且不支持跨連接共享。 - 數(shù)據(jù)庫驅動緩存的優(yōu)勢:數(shù)據(jù)庫驅動層提供的緩存更高效,能夠共享執(zhí)行計劃,減少內(nèi)存占用。
- 反模式:在連接池層進行緩存
PreparedStatement是性能反模式。
4. MySQL驅動配置分析
進一步排查MySQL驅動,發(fā)現(xiàn)項目使用的mysql-connector-j:8.3.0驅動,關鍵配置useServerPrepStmts默認為true,即開啟服務端的預編譯緩存。而在同一項目中,其他服務使用的是mysql-connector-java:8.0.16,該版本的默認配置為false。
核心代碼:

通過對比,確認開啟服務端預編譯緩存是導致告警的根本原因。
解決方案
通過排查,最終確定問題原因是服務端的預編譯緩存未關閉。由于項目采用分庫分表,并且在同一數(shù)據(jù)庫實例中創(chuàng)建了多個Schema,默認開啟的服務端預編譯緩存容易導致資源占用過高。
解決步驟:
在JDBC連接字符串中添加配置&useServerPrepStmts=false,關閉MySQL的服務端預編譯緩存。
例如,JDBC連接URL修改如下:
jdbc:mysql://localhost:3306/dbname?useServerPrepStmts=false
配置完成后,重新啟動服務,觀察效果。關閉服務端預編譯緩存后,數(shù)據(jù)庫告警明顯減少,系統(tǒng)性能得到提升。

總結
通過排查,我們確認了預編譯語句過多告警的根本原因是MySQL服務端開啟了預編譯緩存,導致過多的執(zhí)行計劃占用資源。解決方案是關閉服務端的PreparedStatement緩存,減少系統(tǒng)負載并提升性能。
到此這篇關于MySQL預編譯語句過多告警排查及解決方案的文章就介紹到這了,更多相關MySQL預編譯語句過多告警內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
windows7下啟動mysql服務出現(xiàn)服務名無效的原因及解決方法
這篇文章主要介紹了windows7下啟動mysql服務出現(xiàn)服務名無效的原因及解決方法,需要的朋友可以參考下2014-06-06
網(wǎng)上提供的最簡便的MySql數(shù)據(jù)庫備份的方法
網(wǎng)上提供的最簡便的MySql數(shù)據(jù)庫備份的方法...2007-02-02
mysql使用left?join連接出現(xiàn)重復問題的記錄
這篇文章主要介紹了mysql使用left?join連接出現(xiàn)重復問題的記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

