PostgreSQL物理”備庫”的哪些操作或配置,可能影響”主庫”的效能、垃圾回收、IO波動
標籤
PostgreSQL , 物理複製 , 垃圾回收 , vacuum_defer_cleanup_age , hot_standby_feedback , max_standby_archive_delay , max_standby_streaming_delay
背景
PostgreSQL 物理備庫的哪些配置,或者哪些操作,可能影響到主庫呢?
首先,簡單介紹一下PostgreSQL的物理備庫,物理備庫就是基於PostgreSQL WAL流式複製,實時恢復的備庫。物理備庫在物理層面與主庫完全一致,每一個資料塊都一樣。物理備庫允許在實時恢復的同時,對外提供只讀的功能。
問題來了,只讀操作可能和恢復會發生衝突,比如使用者正在備庫讀某個資料塊的資料,與此同時,實時恢復程式讀取到WAL的記錄,發現需要修改這個資料塊的資料。此時恢復就與只讀發生了衝突。
為了避免衝突,資料庫有哪些手段呢?
1. 主庫配置
1.1 vacuum_defer_cleanup_age
設定主庫垃圾回收的延遲,例如配置為1000,表示垃圾版本將延遲1000個事務再被回收。
2. 備庫配置
2.1 hot_standby_feedback
如果設定為ON,備庫在執行QUERY時會通知主庫,哪些版本需要被保留。
2.2 max_standby_archive_delay, max_standby_streaming_delay
表示當備庫的QUERY與恢復程式發生衝突時,恢復程式最長的等待時間,當恢復程式從被衝突堵塞開始等待時間超過以上設定時,會主動KILL與之發生衝突的QUERY,然後開始恢復,直到catch up,才允許QUERY與恢復程式再次發生衝突。
問題分析
以上配置,要麼會傷害主庫,要麼會傷害備庫。都是有一定代價的。
1. vacuum_defer_cleanup_age > 0
代價1,主庫膨脹,因為垃圾版本要延遲若干個事務後才能被回收。
代價2,重複掃描垃圾版本,重複耗費垃圾回收程式的CPU資源。(n_dead_tup會一直處於超過垃圾回收閾值的狀態,從而autovacuum 不斷喚醒worker進行回收動作)。
當主庫的 autovacuum_naptime=很小的值,同時autovacuum_vacuum_scale_factor=很小的值時,尤為明顯。
代價3,如果期間發生大量垃圾,垃圾版本可能會在事務到達並解禁後,爆炸性的被回收,產生大量的WAL日誌,從而造成WAL的寫IO尖刺。
2. hot_standby_feedback=on
如果備庫出現了LONG QUERY,或者Repeatable Read的長事務,並且主庫對備庫還需要或正查詢的資料執行了更新併產生了垃圾時,主庫會保留這部分垃圾版本(與vacuum_defer_cleanup_age效果類似)。
代價,與vacuum_defer_cleanup_age > 0 一樣。
3. max_standby_archive_delay, max_standby_streaming_delay
代價,如果備庫的QUERY與APPLY(恢復程式)衝突,那麼備庫的apply會出現延遲,也許從備庫讀到的是N秒以前的資料。
影響主庫的問題復現
前面分析了,當主庫設定了vacuum_defer_cleanup_age > 0或者備庫設定了hot_standby_feedback=on同時有LONG QUERY時,都可能造成主庫的3個問題。
這個問題很容易復現。
復現方法1 備庫hot_standby_feedback=on
開啟主庫的自動垃圾回收,同時設定為很小的喚醒時間,以及很小的垃圾回收閾值。
這樣設定是為了防止膨脹,但是也使得本文提到的問題更加的明顯。
postgres=# show autovacuum_naptime ;
-[ RECORD 1 ]------+---
autovacuum_naptime | 1s
postgres=# show autovacuum_vacuum_scale_factor ;
-[ RECORD 1 ]------------------+-------
autovacuum_vacuum_scale_factor | 0.0002
1. 建立測試表
postgres=# create table test(id int , info text, crt_time timestamp);
2. 插入1000萬測試資料
postgres=# insert into test select 1,md5(random()::text),now() from generate_series(1,10000000);
3. 在hot standby上開啟一個repeatable read事務,執行一筆QUERY,查詢test的全表
postgres=# begin transaction isolation level repeatable read;
BEGIN
postgres=# select count(*) from test ;
count
----------
10000000
(1 row)
4. 在主庫更新test全表
postgres=# update test set info=info;
5. 查詢test表當前的統計資訊,有1000萬條dead tuple
postgres=# select * from pg_stat_all_tables where relname =`test`;
-[ RECORD 1 ]-------+------------------------------
relid | 17621
schemaname | public
relname | test
seq_scan | 1
seq_tup_read | 10000000
idx_scan |
idx_tup_fetch |
n_tup_ins | 10000000
n_tup_upd | 10000000
n_tup_del | 0
n_tup_hot_upd | 0
n_live_tup | 10000000
n_dead_tup | 10000000
n_mod_since_analyze | 0
last_vacuum | 2017-04-10 17:35:02.670226+08
last_autovacuum | 2017-04-10 17:42:03.81277+08
last_analyze |
last_autoanalyze | 2017-04-10 17:34:22.947725+08
vacuum_count | 1
autovacuum_count | 211
analyze_count | 0
autoanalyze_count | 2
6. 造成的影響,讀IO巨大(掃描test表,試圖回收垃圾,但是回收未遂),以及autovacuum worker的CPU開銷很大。
autovacuum worker process 不停被喚醒,掃描垃圾資料,但是不能對其進行回收,所以n_dead_tup一直不會下降,迴圈往復,autovacuum worker不斷被喚醒。
程式CPU 100%
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
45213 dege.zzz 20 0 8570m 1.2g 1.2g R 100.0 0.2 0:01.18 postgres: autovacuum worker process postgres
問題處理
1. 備庫設定引數hot_standby_feedback=off
hot_standby_feedback = off
reload
pg_ctl reload -D .
server signaled
問題馬上解除,垃圾被回收掉了。
postgres=# select * from pg_stat_all_tables where relname =`test`;
-[ RECORD 1 ]-------+------------------------------
relid | 17621
schemaname | public
relname | test
seq_scan | 1
seq_tup_read | 10000000
idx_scan |
idx_tup_fetch |
n_tup_ins | 10000000
n_tup_upd | 10000000
n_tup_del | 0
n_tup_hot_upd | 0
n_live_tup | 10000000
n_dead_tup | 0
n_mod_since_analyze | 0
last_vacuum | 2017-04-10 17:35:02.670226+08
last_autovacuum | 2017-04-10 17:42:52.455949+08
last_analyze |
last_autoanalyze | 2017-04-10 17:34:22.947725+08
vacuum_count | 1
autovacuum_count | 233
analyze_count | 0
autoanalyze_count | 2
autovacuum worker不會再被喚醒,所以主庫的CPU馬上下降。
同時垃圾回收會帶來一次很大的WAL寫IO。造成尖刺。
2. max_standby_archive_delay, max_standby_streaming_delay起作用,備庫的事務在apply衝突超時後,被強制kill
postgres=# show hot_standby_feedback;
hot_standby_feedback
----------------------
off
(1 row)
postgres=# select count(*) from test ;
count
----------
10000000
(1 row)
postgres=# select * from test limit 10;
FATAL: terminating connection due to conflict with recovery
DETAIL: User query might have needed to see row versions that must be removed.
HINT: In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
復現方法2 主庫vacuum_defer_cleanup_age > 0
略,復現方法一樣。
小結與優化
為了儘量的避免物理備庫的QUERY與apply的衝突,PostgreSQL提供了幾種方法,但是這些方法要麼會傷害主庫,要麼會傷害備庫。都有一定代價。
1. vacuum_defer_cleanup_age > 0
代價1,主庫膨脹,因為垃圾版本要延遲若干個事務後才能被回收。
代價2,重複掃描垃圾版本,重複耗費垃圾回收程式的CPU資源。(n_dead_tup會一直處於超過垃圾回收閾值的狀態,從而autovacuum 不斷喚醒worker進行回收動作)。
當主庫的 autovacuum_naptime=很小的值,同時autovacuum_vacuum_scale_factor=很小的值時,尤為明顯。
代價3,如果期間發生大量垃圾,垃圾版本可能會在事務到達並解禁後,爆炸性的被回收,產生大量的WAL日誌,從而造成WAL的寫IO尖刺。
2. hot_standby_feedback=on
如果備庫出現了LONG QUERY,或者Repeatable Read的長事務,並且主庫對備庫還需要或正查詢的資料執行了更新併產生了垃圾時,主庫會保留這部分垃圾版本(與vacuum_defer_cleanup_age效果類似)。
代價,與vacuum_defer_cleanup_age > 0 一樣。
3. max_standby_archive_delay, max_standby_streaming_delay
代價,如果備庫的QUERY與APPLY(恢復程式)衝突,那麼備庫的apply會出現延遲,也許從備庫讀到的是N秒以前的資料。
優化
1. 不建議設定 vacuum_defer_cleanup_age > 0
2. 如果備庫有LONG query,同時需要實時性,可以設定hot_standby_feedback=on,同時建議將主庫的autovacuum_naptime,autovacuum_vacuum_scale_factor設定為較大值(例如60秒,0.1),主庫的垃圾回收喚醒間隔會長一點,如果突然產生很多垃圾,可能會造成一定的膨脹。
3. 如果備庫有LONG QUERY,並且沒有很高的實時性要求,建議設定設定hot_standby_feedback=off, 同時設定較大的max_standby_archive_delay, max_standby_streaming_delay。
參考
https://www.postgresql.org/docs/9.6/static/runtime-config-replication.html
相關文章
- 主庫resetlogs對備庫的影響
- 【DATAGUARD 學習】管理影響備庫的主庫事件事件
- 配置物理備庫+邏輯備庫
- 用物理備庫的檔案來恢復主庫
- PHP中什麼是垃圾回收?對效能有什麼影響PHP
- Oracle10G Dataguard 多個備庫 - 主庫和物理備庫的切換Oracle
- nologging對備庫的影響
- 哪些方面會影響伺服器資料庫效能伺服器資料庫
- 【Postgresql】VACUUM 垃圾回收SQL
- oracle 之dataguard主庫系統崩潰之物理備庫切主庫Oracle
- 影響mysql效能的因素都有哪些MySql
- 磁碟排序對Oracle資料庫效能的影響排序Oracle資料庫
- 單節點主庫、邏輯備庫升級為RAC、物理備庫、邏輯備庫(1)
- 單節點主庫、邏輯備庫升級為RAC、物理備庫、邏輯備庫(2)
- 單節點主庫、邏輯備庫升級為RAC、物理備庫、邏輯備庫(3)
- 單節點主庫、邏輯備庫升級為RAC、物理備庫、邏輯備庫(4)
- 單節點主庫、邏輯備庫升級為RAC、物理備庫、邏輯備庫(5)
- Postgresql MVCC架構對從庫長查詢的影響SQLMVC架構
- 1個主庫配置多個備庫的問題
- 哪些因素影響Java呼叫的效能?Java
- 物理備庫互轉快照備庫
- 【DataGuard】使用GC建立的物理DataGuard主備庫pfile比較GC
- MySQL資料庫的效能的影響分析及其優化MySql資料庫優化
- Data guard 配置之搭建物理備庫
- 物理備庫的搭建過程
- 磁碟排序對Oracle資料庫效能的影響PT排序Oracle資料庫
- 容器化對資料庫的效能有影響嗎?資料庫
- 伺服器IO瓶頸對MySQL效能的影響伺服器MySql
- 【DataGuard】主庫是否為OMF管理方式對使用Grid Control部署物理DataGuard的影響
- Mysql 資料庫主庫,備庫實時同步配置MySql資料庫
- 【知識分享】哪些方面會影響伺服器資料庫效能伺服器資料庫
- [V8]找出可能影響效能的程式碼(模式)模式
- 【DATAGUARD】 基於同一個主機建立物理備庫和邏輯備庫(二)
- 【DATAGUARD】 基於同一個主機建立物理備庫和邏輯備庫(一)
- 【DATAGUARD】 基於同一個主機建立物理備庫和邏輯備庫 (三)
- 搭建物理備庫
- 批操作效能影響診斷
- 影響儲存網路效能的因素有哪些?