從一個資料庫連線數計算公式談起

qing_yun發表於2023-01-13

昨天一個微信群裡在討論一個資料庫連線數的計算公式,截圖看不太清楚。我來描述一下。說是PG提供了一個連線數計算公式:連線數=核心數*2+有效磁碟數量。其中核心數不應該包含超執行緒數量,而是物理核的數量。

這是一個十分典型的極限測試估算連線數的公式,主要目的是規避CPU方面存在的瓶頸。這種設定思路往往不會使用在普通的生產系統上,因為不管是OLTP系統還是OLAP系統,作為資料庫伺服器來說,會話會有大量的工作會產生在IO上,包括網路IO和磁碟IO,真正使用CPU的比例實際上並不高。對於OLTP系統來說大量的CPU使用都是小於一個時間片(大部分UNIX系統都是一個釐秒)的,很少會把一個時間片用滿,因為資料庫應用中,會話大部分都在等待某些等待事件,比如IO,LWLOCK,LOCK,IPC等,一個會話ONCPU狀態的比例很低,因此使用CPU數量來作為會話數的設定基礎實際上並沒有任何科學依據。

從另外一個角度來說,CPU之間也是有差異的,哪怕核數相同的CPU,其處理能力也不能同日而語,三五年前的同樣核數的CPU,其處理能力可能不到現在的1/3,花費同樣CPU時間能夠完成的任務也會相差極大。簡單的用CPU作為設定連線數的依據顯然是不合理的。在現在的絕大多數OLTP系統中,資料庫伺服器的CPU資源都是十分充足的,大部分系統的主要問題並不出現在CPU資源不足上,這是這二十年來摩爾定律給我們帶來的紅利。

實際上資料庫中的存在排隊效應的地方很多,任何一個地方存在瓶頸都會影響極限測試的效能,也會影響到生產環境中的併發訪問效率。兩年前我寫過一篇文章《從疏通下水道聯想到的最佳化問題》,這篇文章中對此做了詳細的分析,有興趣的朋友可以在我的公眾號中查詢閱讀。

實際上決定資料庫連線數的最主要因素還是應用,對於絕大多數資料庫系統而言,max_connections引數一定要確保使用這個資料庫的所有模組不會因為連線池不足而導致應用報錯。現在的應用系統大多十分複雜,還有大量的模組使用併發量十分不穩定的微服務。我見過一套資料庫系統對接的應用連線池超過100個,哪怕一個連線池設定幾十個連線,max_connections也必須設定為幾千才能確保大多數情況下不會因為資料庫連線數限制而導致應用故障。

資料庫的最大連線數設定的過大有什麼壞處呢?最容易出問題的往往不是CPU,當然如果在雲環境中,我們給資料庫的CPU資源很少,那麼較大的連線可能會引發CPU資源的不足。關於雲環境資料庫伺服器的CPU資源問題,那是一個更大的話題-容量管理,今天我們暫不討論。資料庫應用對CPU的使用一般來說是不存在資源不足的問題的,當然如果某個併發量很大的SQL的執行計劃錯了,是很容易把CPU跑爆掉的,這個也不在我們今天探討的範圍內,因為這種情況出現,哪怕連線數設定的很低,也會出問題。

除此之外,實際上最容易出問題的是記憶體,資料庫會話數多了,因為ATTACH共享記憶體所佔用的TLB就會很大,特別是資料庫沒有使用大頁的情況下。前陣子我們在分析一個資料庫當機的案例中,就發現一臺128GB的資料庫伺服器上,TLB居然高達30GB。另外會話都會使用WORK_MEM來做排序、JOIN等操作。會話數多了,這些記憶體自然就會使用的更多。前兩年和一個國外的PGER交流的時候,他提出了一個PG記憶體估算的方法,悲觀的演算法是MAX_CONNECTIONS*WORK_MEM作為會話工作記憶體,樂觀的演算法是MAX_ACTIVE_SESSIONS*WORK_MEM作為會話的工作記憶體。根據這個,結合實體記憶體大小,計算SHARED_BUFFERS能夠使用記憶體的最大值。

實際上悲觀與樂觀演算法算出來的值相差甚大,基本上不具備參考意義。當時我和他說與其這麼精打細算,莫不如把SWAP設定大一點,哪怕實體記憶體偶爾用的多一些,系統產生一個小抖動,很快就能挺過去了。他想了一會兒,認同了我的觀點。

實際上我們今天討論的內容很多都屬於容量管理的範疇,這個問題也是困擾了我近20年的問題,這20年裡,參與過不少容量管理相關的專案,也幫使用者構建了一些模型,只不過,感覺還是在門外晃悠。等有時間,我也會寫幾篇這方面的文章,把我們這些年的一些成果分享給大家。

來自 “ 白鱔的洞穴 ”, 原文作者:白鱔;原文連結:https://mp.weixin.qq.com/s/2MqhuaS4uWycTqgbavCGPw,如有侵權,請聯絡管理員刪除。

相關文章