1. 程式人生 > 其它 >KingbaseES V8R6在解決複製衝突中hot_standby_feedback引數的重要性

KingbaseES V8R6在解決複製衝突中hot_standby_feedback引數的重要性

背景

如果我們看到這樣的類似報錯:那說明可能遇到了複製衝突。

複製衝突的理解:當備庫正在應用主庫傳輸過來的wal日誌與備庫正在進行的查詢產生衝突就會有此報錯。比如說備庫正在執行基於某個表的查詢,這時主庫執行了drop table操作,該操作寫入wal日誌落盤後傳至備庫進行應用,為了保證資料一致性,備庫會迅速回放資料,這時主庫的操作和備庫的查詢形成衝突。尤其備庫執行長查詢時候,查詢被取消了就會看到下面的報錯。

ERROR:canceling statement due to confilct with recovery。

避免查詢衝突的發生

hot_standby_feedback:

這個引數是查詢衝突中最重要的引數,下面我們詳細探討一下。我們假設在沒有備庫的情況下,在主從架構中。設定hot_standby_feedback引數之後備庫會定期向主庫通知其最小活躍事務id(xmin)值,這就使得主庫vacuum時不會清理大於xmin值的事務。

這樣就有利於減少衝突的發生,但並不能完全避免衝突,請注意,這個引數只是減少了由於主庫vacuum死亡元組造成的衝突,換句話說,並不能解決排他鎖造成的衝突。同時還有第三種情況:由於網路中斷造成的衝突,假如主備之間的網路中斷後,備庫就無法向主庫正常傳送xmin值,如果時間很長,主庫在這段時間內還是會清理無用元組,這樣網路恢復後就很可能繼續發生上面的vacuum和備庫造成的衝突。

任何事情都是有利有弊,要根據實際情況,有所取捨,好處就是減少了衝突,缺點就是由於主庫的清理需要等待備庫的事務結束,那麼在頻繁更新的場景下,可能造成主庫資料膨脹和age的激增。然而,當積累足夠多的死亡元組或表age,當備庫查詢結束,主庫集中vacuum時會給I\O帶來極致負擔。所以我們在生產中設定hot_standby_feedback需要輔助下面引數一起使用,能夠有效的降低衝突發生概率。

需要注意的是hot_standby_feedback引數並不會覆蓋主庫上old_snapshot_threshold引數限定的值,old_snapshot_threshold引數限制了死亡元組的無限膨脹,換句話說當事務資訊超過old_snapshot_threshold的限制時,依然會進行清理。所以old_snapshot_threshold是給查詢留出的最大限度時間。

max_standby_streaming_delay:
備機由於接收wal流日誌產生查詢衝突而取消查詢之前的等待時間,設定該引數會在發生衝突時,備庫查詢不會馬上取消查詢,而是等待一段時間後如果還沒結束再丟擲報錯。這個值的大小可以參考備庫可能產生的長事務執行時間。這個引數指startup最多等多久

max_standby_archive_delay:

備機由於應用傳輸過來的歸檔日誌產生查詢衝突而取消查詢之前的等待時間,和上面的引數類似,這個引數指startup最多等多久。(restore command 會遇到)
請注意這個引數設定的不合理會造成備庫需要更長時間追平主庫的資料,這就不能保證主備資料實時一致性。

vacuum_defer_cleanup_age:
指定vacuum延遲清理死亡元組的事務數,延遲的事務個數通過該引數進行設定。(不常用,因為不夠具體明確,容易造成膨脹)

我們可以根據pg_stat_database和pg_stat_database_conflicts檢視檢視衝突的情況。

總結

仔細想一想,流複製本身並沒有多大問題,也就是vacuum相關死亡元組必然會應用到備庫,甚至我們希望流複製做的速度更快,延遲越小越好,以保證主備最大一致性。那麼以上論述最應該避免的是長事務查詢,然而主備往往配置了讀寫分離,在備庫讀的壓力很大時候,加上一些不合理的sql和業務,以此產生了長查詢,在oracle中長查詢也是不可取的,因為同樣可能造成undo表空間中的資料庫被覆蓋,其實undo中的retention時間就相當於上面提到的old_snapshot_threshold引數,只是undo中多保護了一個guarantee,沒有客戶不在意成本去無線擴充undo表空間,所以undo表空間往往被設定成非自動擴充套件,換句話說不允許很長的大查詢發生。當然如果是OLTP系統另當別論,而且這也容易造成一致性讀相關的效能問題。