簡介: 針對數據庫鏈接池到DRDS鏈接探活的優化
========數據庫
近期在給某專有云客戶進⾏雲產品應⽤性能優化分析時,發現了⼀個有趣的關於DRDS使⽤層⾯的問題,這⾥給⼤家分享⼀下。
使⽤過DRDS產品的同窗都知道在DRDS中,未分庫分表的數據表會存儲在「0號庫」上,對於這些表操做的SQL會被分發到「0號庫」上執⾏。因此⼀般狀況下,0號庫所在實例的壓⼒會⽐其它實例的壓⼒稍⼤⼀些。近期分析該客戶的數據庫性能時,發現客戶使⽤的DRDS下0號庫所在的RDS實例的壓⼒明顯⽐其它RDS實例⾼出許多。後端
圖1:SQL語句平均每秒執行次數及事務數性能優化
========性能
經過查看0號庫所在的RDS實例的執⾏SQL發現,有⼤量的 SELECT 'x' 的查詢語句。檢查應⽤側代碼後發現,這個查詢語句是應⽤側鏈接池配置的鏈接探活SQL,全部的鏈接池實現⼏乎都有這個功能,能夠經過探活SQL檢測鏈接當前是否可⽤。
那麼問題來了:優化
答案⼀定是有⽤的,由於若是因⽹絡閃斷或其它緣由致使的鏈接狀態不可⽤,即便獲取到了鏈接對象,也不能進⾏數據訪問操做。因此這個檢測是有必要的,但對於使⽤DRDS做爲數據源的場景來講,⽬前配置的檢測⽅式是存在問題的。
對於傳統的數據庫使⽤⽅式,客戶端是直接鏈接到底層數據庫的,以下圖。探活SQL是直接發到鏈接的數據庫執⾏,這種場景下使⽤ SELECT 'x' 檢測客戶端到數據庫的鏈接是沒有問題的。ui
圖2:客戶端鏈接到數據庫阿里雲
⽽對於使⽤DRDS做爲數據源的場景來講,探活語句在發送到DRDS服務後,會被轉發到0號庫執⾏,這就意味着這個探活SQL實際上檢測的是客戶端-->DRDS-->0號庫的鏈路是否正常。spa
圖3:客戶端經過DRDS鏈接到數據庫線程
這⼀點能夠從DRDS上看 SELECT 'x' 的執⾏計劃獲得證明,以下:對象
圖4:執⾏結果1
實際上,這樣的數據源鏈接檢測是沒有意義的。由於:
========
明⽩以上內容後,咱們解決問題的⽅案就⽐較清楚了,實際上咱們只須要讓客戶端鏈接池檢測客戶端到DRDS的鏈接狀態便可。那有沒有這樣的檢測⽅法呢?
答案固然是有的,通過與DRDS研發同窗確認,將探活SQL修改成 SELECT 'x' FROM dual 便可。
修改後,再次在DRDS查看執⾏計劃,以下:
圖5:執⾏結果2
在應⽤側修改鏈接池的探活SQL配置後,從0號庫所在實例上看,已經看不到探活SQL的執⾏記錄,⽽且從修改前和修改後0號庫所在實例的壓⼒來看,效果也⽐較明顯,0號庫的壓⼒相⽐以前降低了⼤概80%左右。
圖6:SQL語句平均每秒執行次數及事務數2
⾄此,0號庫壓⼒過⾼的問題解決了,下⾯咱們聊聊爲何會有⼤量的探活語句出現。
探活機制其實是數據源鏈接池通⽤的⼀種檢測機制,能夠檢測鏈接池內的鏈接對象是否真的可⽤。拿Druid鏈接池舉例,探活SQL是經過數據源的 validationQuery 屬性配置的。與之相關的配置屬性還有:testOnBorrow testWhileIdle testOnReturn timeBetweenEvictionRunsMillis minEvictableIdleTimeMillis。
官⽅解釋以下:
⽂章前⾯描述的出現⼤量探活SQL的狀況是由於應⽤將鏈接池的testOnBorrow設置成了true,因此在每次應⽤獲取鏈接時,都會執⾏ validationQuery 配置的探活語句檢測鏈接是否有效。雖然經過前⾯的優化步驟,已經下降了0號庫的壓⼒,使探活語句不下發到0號庫執⾏。
但探活語句仍會在DRDS實例上執⾏,DRDS實例的壓⼒並未減輕。經過上⾯對Druid數據源屬性配置的說明能夠了解到,若是將 testOnBorrow 或 testOnReturn 打開,會對系統性能有⼀定的影響,由於每次都會在獲取鏈接時多執⾏⼀次查詢來檢測鏈接是否可⽤。所以推薦使⽤以下的配置:
這樣設置完成後,只有在獲取到「空閒鏈接」時,纔會進⾏探活檢測,⼤⼤下降了業務⾼峯時段的探活頻率。同時,也可經過適當縮短minEvictableIdleTimeMillis 的值,兼顧因爲⽹絡閃斷或其它緣由致使的鏈接不可⽤的狀況,減小業務出錯的機率,在系統性能和可⽤性之間找到⼀個平衡點。
做者:劉維
原文連接 本文爲阿里雲原創內容,未經容許不得轉載