PostgreSQL 是很是好的開源的數據庫,針對替換ORACLE數據庫的重任,基本上大部分中小型企業,能期望的也只有POSTGRESQL ,固然若是你願意花更多的前,更多的應用程序結構方面的改造,MYSQL 也不是不能夠, ORACLE 換成PG 就如同,你從一箇中單的一個房間 換到另外一個房間, 若是要是ORACLE 到MYSQL ,就如同你從北京,搬到上海. 因此若是不想大動干戈, 而且不想改變現有的總體架構, PG 必定是必然的選擇,沒有其餘.
數據庫
那在使用PG的時候,可能很快就會體會到PG之美, 與功能強大,這裏就不在多說,今天要說的是,POSTGRESQL 在高併發下,超高鏈接對PG的衝擊,以及爲何PG 在高併發鏈接中,須要使用pgbouncer或pgpool 來.
緩存
首先就要祭出原理, 到底鏈接分配的內存要從哪裏來出,大部分人包括我,認爲,致使PG 沒法接受大量鏈接的主要緣由,實際上是內存. 因爲大量的鏈接使用了大量的內存,致使,PG 在接受大量的connections 會致使, OOM, 或者性能低下.微信
但實際上咱們作一個測試,我對一個有用8G 內存的 PG ,加載3000個併發鏈接而且查詢一個表,同時將 shared_buffers 調整成20MB ,而後我就等待着PG崩潰.架構
實際上我並無如願, PG 仍是穩穩的運行, 但系統有一點緩慢,有點卡的感受
併發
內存方面數據庫設計
也並無像我與預期的會完全的用光.
高併發
那麼問題來了, 到底各類 大小廣而告之,中提到的PG 不適宜 多鏈接的緣由在哪裏.
post
那就的從 PG 的源碼中的 PGPROC 說了,
性能
其中上面的each backend has a PGPROC struct in shared memory , + 後面的那句, 應該代表 backend 和 shared memory 之間 存在一個pgproc的結構, 這個結構的主要做用就是 複用.
測試
後面的NOTE 的twophase.c 證實了PGPROC 結構的複用,由於當前的transaction 在隊列中 有兩個狀態, 真正運行和準備運行.
這個PGPROC 會在 PROC_HDR中被調用, allProcs 是一個指針,也就是全部的PGPROC 都會在這裏面.PGPROC 主要的做用是要在事務處理期間處理相關例如等待和處理等工做之間的切換,PROC 主要的做用進程間協同和通信以及postmaster的跟蹤
而爲了獲取這些信息的變化對share_buffer 和 backend 的臨時數據進行獲取,他會遍歷到其餘的process 中, 而若是咱們創建的backend越多, 也就是鏈接到PG的鏈接越多, 就會致使遍歷GetSnapshotData 的工做消耗更多的系統資源,例如CPU.
因爲查詢是最簡單的 select 語句,而且應該也應用到了緩存,IO性能基本上處於沒有使用的狀態
內存的使用也未佔滿.
多鏈接並非經過內存的消耗,將PG 帶入到OOM 和系統無響應的狀況中, 而是隨着backend變多後,內部溝通的成本過高,致使性能上的問題,因此PG的在多鏈接中,是須要使用PGPOOL 或者 pgbouncer 之類的緩衝池來保證系統的性能,另外還有一個問題就是爲何要有這麼多的鏈接, 這就是一個問題.
那既然知道了PG在處理超多的鏈接上會有性能的問題,那如何解決這個問題對大多數使用的人就有相關的意義,能夠帶着這個問題來問幾個問題
內存的使用也未佔滿.
多鏈接並非經過內存的消耗,將PG 帶入到OOM 和系統無響應的狀況中, 而是隨着backend變多後,內部溝通的成本過高,致使性能上的問題,因此PG的在多鏈接中,是須要使用PGPOOL 或者 pgbouncer 之類的緩衝池來保證系統的性能,另外還有一個問題就是爲何要有這麼多的鏈接, 這就是一個問題.
那既然知道了PG在處理超多的鏈接上會有性能的問題,那如何解決這個問題對大多數使用的人就有相關的意義,能夠帶着這個問題來問幾個問題。
1 爲何要有併發有那麼多的鏈接, 例如一個數據庫要承受3000+以上的鏈接數,即便是互聯網屬性,總體的架構設計是什麼,若是併發的鏈接不少的狀況下,數據庫自己可能已經分庫分表,或者已經經過業務繼續細分,將訪問分散了。因此過多的同一時間的訪問,這自己就是一個問題
2 對於數據庫的訪問,即便不使用PGbouncer 或者pgpool 程序自己也有鏈接池,對於鏈接的設計,在總體的程序設計之初就應該有考慮,而不是最後讓數據庫承接這一切
3 對於任何的數據庫鏈接,都不是百分之百在同一時刻達到最大的處理數,及時是MYSQL 3000 MAX CONNECTIONS鏈接,在很細分的時間刻度上,同時訪問數據庫的基本也就是幾十個。PG 的鏈接狀態分爲
1 active
2 idle
3 idle in transacton
4 aborted
這裏PGbouncer 和PGPOOL 到底在幫助PG connections 作了什麼
1 和 3,4 不是咱們要關心的,而是idle 這個狀態,這也是大部分浪費鏈接數的關鍵位置,由於程序的鏈接池要維護一個鏈接數據庫的狀態,這也就致使有些時刻PG 大部分的鏈接的狀態在idle,因此要更高的利用 鏈接,讓數據庫使用有限的鏈接,接入更多的要工做的鏈接就是解決,少鏈接和應用要多鏈接的矛盾,所謂的鏈接複用。。
2 另外若是你常常發現你的鏈接狀態在 idle in transaction 這也就說明常常有大事務長時間在等待什麼,這也是解決問題的一個點,爲何一個事務要長時間霸佔鏈接,並等待
另外還有一些鏈接,只鏈接不清理不關閉,多是程序設計有失誤,這樣的狀況咱們能夠設置對某個數據庫的鏈接的 statement_timeout ,在多長時間不工做咱們就關掉這個鏈接。(設置60秒)
alter database 數據庫名 set statement_timeout = 60000;
這裏最後總結一下
1 每一個數據庫有本身的特性,這和數據庫設計的之初,架構思路有關
2 數據庫的特性不是很好修改的,例如到目前MYSQL 也仍是比較適合作OLTP,也沒有人讓他去作OLAP的操做同樣, 過分將一個數據庫神話,樣樣都行這不現實。
3 掌握某個數據庫的特色,並展開,讓自己的缺點弱化,這纔是一個 DB 人員應該作的。
本文分享自微信公衆號 - AustinDatabases(AustinDatabases)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。