公司有一臺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架構
簡單來講,也就是若是該row建立時的transaction id大於當前事務的transaction id,那麼將不可見;若是該row刪除時的transaction id小於當前事務的transaction id,也不可見。併發
MVCC目的是提升併發度,讀操做不會阻塞寫操做,寫操做也不會阻止讀操做。函數
這一特性和從數據庫放在一塊兒的時候,會遇到一些問題: 好比在從數據庫上有一個耗時很長的查詢操做,在查詢的過程當中,一些須要的row在主數據庫上面已經被更新或者刪除了。主數據庫並不知道當前在從數據庫在進行一個查詢,它以爲本身能夠vacuum掉那些比較老的數據行。對於從數據,他必須replay這個vacuum操做,因此他必須取消全部結果包含這些數據行的查詢。高併發
默認狀況下,主數據庫是看不到從數據庫上的查詢操做的,設置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
複製代碼
pg中有一個max_standby_streaming_delay參數,意思是從數據庫replay主數據庫操做能夠等待的最長時間。默認是30s,將其設置爲一個相對比較大的數,或者-1,也就是能夠無限等待,能夠在全部查詢完成以後再replay主數據庫的操做,這樣長查詢就不會被取消了。spa
這個參數相比hot_standby_feedback,只會影響從服務區,對主服務區沒影響,可是有可能會加大主從數據不一致。
可見,從數據庫長耗時查詢並無一個十全十美的方案,這也算是一個困擾社區已久的難題。
關注個人微信公衆號