Postgresql MVCC架構對從庫長查詢的影響

公司有一臺pg從數據庫,鏈接的是位於上海的主庫,最近使用過程當中遇到了一個報錯:數據庫

ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
複製代碼

緣由分析

Google一番後,總結緣由以下:bash

Pg屬於經典的MVCC(multi version concurrency control)架構,在這種模式下,更新一行不是直接修改那一行的內容,而是會建立一個新的行,對應的這兩行屬於不一樣的版本,這也就是MVCC中multi version的含義。顯然,若是這麼一直建立新的行,磁盤早晚會被撐爆,因此pg內部會有一個 vacuum進程,專門用來清理老數據。微信

Pg每一個row都有兩個特殊的字段xmin,xmax架構

  • xmin表示row建立時的transaction id
  • xmax表示row刪除時的transaction id,若是尚未被刪除,就是NULL 在一個事務裏面,只能看到一部分數據,還有一部分是不可見的。那麼 pg是如何判斷對一個事務,哪些數據是可見的,哪些數據是不可見的呢? 簡單來講,能夠經過下面這個僞函數來判斷:

簡單來講,也就是若是該row建立時的transaction id大於當前事務的transaction id,那麼將不可見;若是該row刪除時的transaction id小於當前事務的transaction id,也不可見。併發

MVCC目的是提升併發度,讀操做不會阻塞寫操做,寫操做也不會阻止讀操做。函數

這一特性和從數據庫放在一塊兒的時候,會遇到一些問題: 好比在從數據庫上有一個耗時很長的查詢操做,在查詢的過程當中,一些須要的row在主數據庫上面已經被更新或者刪除了。主數據庫並不知道當前在從數據庫在進行一個查詢,它以爲本身能夠vacuum掉那些比較老的數據行。對於從數據,他必須replay這個vacuum操做,因此他必須取消全部結果包含這些數據行的查詢。高併發

解決方案

方案1: hot_standby_feedback = on

默認狀況下,主數據庫是看不到從數據庫上的查詢操做的,設置hot_standby_feedback爲on,能夠防止主數據庫的vacuum操做把從數據庫查詢須要的數據行給清除掉。性能

可是這個方案可能會影響主數據庫的性能,由於主數據庫如今得考慮從數據庫的查詢,勢必會是一種負擔,如在pg官方文檔中寫道:ui

Well, the disadvantage of it is that the standby can bloat the master, which might be surprising to some people, too
複製代碼

方案2:max_standby_streaming_delay

pg中有一個max_standby_streaming_delay參數,意思是從數據庫replay主數據庫操做能夠等待的最長時間。默認是30s,將其設置爲一個相對比較大的數,或者-1,也就是能夠無限等待,能夠在全部查詢完成以後再replay主數據庫的操做,這樣長查詢就不會被取消了。spa

這個參數相比hot_standby_feedback,只會影響從服務區,對主服務區沒影響,可是有可能會加大主從數據不一致。

可見,從數據庫長耗時查詢並無一個十全十美的方案,這也算是一個困擾社區已久的難題。

關注個人微信公衆號

相關文章
相關標籤/搜索