從一個數(shù)據(jù)庫連接數(shù)計算公式談起
?昨天一個微信群里在討論一個數(shù)據(jù)庫連接數(shù)?的計算公式,截圖看不太清楚。我來描述一下。說是PG提供了一個連接數(shù)計算公式:連接數(shù)=核心數(shù)*2+有效磁盤數(shù)量。其中核心數(shù)不應(yīng)該包含超線程數(shù)量,而是物理核的數(shù)量。
這是一個十分典型的極限測試估算連接數(shù)的公式,主要目的是規(guī)避CPU方面存在的瓶頸。這種設(shè)置思路往往不會使用在普通的生產(chǎn)系統(tǒng)上,因為不管是OLTP系統(tǒng)還是OLAP系統(tǒng),作為數(shù)據(jù)庫服務(wù)器來說,會話會有大量的工作會產(chǎn)生在IO上,包括網(wǎng)絡(luò)IO和磁盤IO,真正使用CPU的比例實際上并不高。對于OLTP系統(tǒng)來說大量的CPU使用都是小于一個時間片(大部分UNIX系統(tǒng)都是一個厘秒)的,很少會把一個時間片用滿,因為數(shù)據(jù)庫應(yīng)用中,會話大部分都在等待某些等待事件,比如IO,LWLOCK,LOCK,IPC等,一個會話ONCPU狀態(tài)的比例很低,因此使用CPU數(shù)量來作為會話數(shù)的設(shè)置基礎(chǔ)實際上并沒有任何科學(xué)依據(jù)。
從另外一個角度來說,CPU之間也是有差異的,哪怕核數(shù)相同的CPU,其處理能力也不能同日而語,三五年前的同樣核數(shù)的CPU,其處理能力可能不到現(xiàn)在的1/3,花費同樣CPU時間能夠完成的任務(wù)也會相差極大。簡單的用CPU作為設(shè)置連接數(shù)的依據(jù)顯然是不合理的。在現(xiàn)在的絕大多數(shù)OLTP系統(tǒng)中,數(shù)據(jù)庫服務(wù)器的CPU資源都是十分充足的,大部分系統(tǒng)的主要問題并不出現(xiàn)在CPU資源不足上,這是這二十年來摩爾定律給我們帶來的紅利。
實際上數(shù)據(jù)庫中的存在排隊效應(yīng)的地方很多,任何一個地方存在瓶頸都會影響極限測試的性能,也會影響到生產(chǎn)環(huán)境中的并發(fā)訪問效率。兩年前我寫過一篇文章《從疏通下水道聯(lián)想到的優(yōu)化問題》,這篇文章中對此做了詳細(xì)的分析,有興趣的朋友可以在我的公眾號中查找閱讀。
實際上決定數(shù)據(jù)庫連接數(shù)的最主要因素還是應(yīng)用,對于絕大多數(shù)數(shù)據(jù)庫系統(tǒng)而言,max_connections參數(shù)一定要確保使用這個數(shù)據(jù)庫的所有模塊不會因為連接池不足而導(dǎo)致應(yīng)用報錯。現(xiàn)在的應(yīng)用系統(tǒng)大多十分復(fù)雜,還有大量的模塊使用并發(fā)量十分不穩(wěn)定的微服務(wù)。我見過一套數(shù)據(jù)庫系統(tǒng)對接的應(yīng)用連接池超過100個,哪怕一個連接池設(shè)置幾十個連接,max_connections也必須設(shè)置為幾千才能確保大多數(shù)情況下不會因為數(shù)據(jù)庫連接數(shù)限制而導(dǎo)致應(yīng)用故障。
數(shù)據(jù)庫的最大連接數(shù)設(shè)置的過大有什么壞處呢?最容易出問題的往往不是CPU,當(dāng)然如果在云環(huán)境中,我們給數(shù)據(jù)庫的CPU資源很少,那么較大的連接可能會引發(fā)CPU資源的不足。關(guān)于云環(huán)境數(shù)據(jù)庫服務(wù)器的CPU資源問題,那是一個更大的話題-容量管理,今天我們暫不討論。數(shù)據(jù)庫應(yīng)用對CPU的使用一般來說是不存在資源不足的問題的,當(dāng)然如果某個并發(fā)量很大的SQL的執(zhí)行計劃錯了,是很容易把CPU跑爆掉的,這個也不在我們今天探討的范圍內(nèi),因為這種情況出現(xiàn),哪怕連接數(shù)設(shè)置的很低,也會出問題。
除此之外,實際上最容易出問題的是內(nèi)存,數(shù)據(jù)庫會話數(shù)多了,因為ATTACH共享內(nèi)存所占用的TLB就會很大,特別是數(shù)據(jù)庫沒有使用大頁的情況下。前陣子我們在分析一個數(shù)據(jù)庫宕機的案例中,就發(fā)現(xiàn)一臺128GB的數(shù)據(jù)庫服務(wù)器上,TLB居然高達(dá)30GB。另外會話都會使用WORK_MEM來做排序、JOIN等操作。會話數(shù)多了,這些內(nèi)存自然就會使用的更多。前兩年和一個國外的PGER交流的時候,他提出了一個PG內(nèi)存估算的方法,悲觀的算法是MAX_CONNECTIONS*WORK_MEM作為會話工作內(nèi)存,樂觀的算法是MAX_ACTIVE_SESSIONS*WORK_MEM作為會話的工作內(nèi)存。根據(jù)這個,結(jié)合物理內(nèi)存大小,計算SHARED_BUFFERS能夠使用內(nèi)存的最大值。
實際上悲觀與樂觀算法算出來的值相差甚大,基本上不具備參考意義。當(dāng)時我和他說與其這么精打細(xì)算,莫不如把SWAP設(shè)置大一點,哪怕物理內(nèi)存偶爾用的多一些,系統(tǒng)產(chǎn)生一個小抖動,很快就能挺過去了。他想了一會兒,認(rèn)同了我的觀點。
實際上我們今天討論的內(nèi)容很多都屬于容量管理的范疇,這個問題也是困擾了我近20年的問題,這20年里,參與過不少容量管理相關(guān)的項目,也幫用戶構(gòu)建了一些模型,只不過,感覺還是在門外晃悠。等有時間,我也會寫幾篇這方面的文章,把我們這些年的一些成果分享給大家。