在監控觀察 PostgreSQL 資料庫的 Logs 時,有時候會觀察到錯誤訊息 Connection to client lost ,這時候會有兩個問題,第一個是這錯誤訊息跟誰有關,第二個是這錯誤訊息代表什麼意思。
在一般沒有特定設定時,Logs 裡面只會顯示紀錄時間還有錯誤訊息,除非有明確的 SQL 語法能夠對應,不容易判斷實際上造成此異常的源頭,需要搭配 log_line_prefix 的設定來看。
可以設定如下,加入 PID 與 UserName 來輔助判斷,依實際需求可以再加上 Application Name 和來源 IP 等等。
log_line_prefix = '%t %p %u'
接下來討論這個錯誤訊息代表什麼意思,這訊息告訴我們,資料庫想要嘗試將 SQL 執行結果回傳給 Client ,但卻發現找不到 Client 。
看到此訊息一般最有可能的原因是 Client 端沒有做 Tcp Keep Alive 的設定,執行長 SQL 在等待資料庫執行完成前,會有一段時間資料庫與AP沒有做任何封包的溝通,在這段期間在中間網路層可能會判斷認為這連線死掉了,就把連線砍掉了,導致 AP 認為資料庫一直沒有回應,而資料庫要回應的時候找不到人。
在資料庫端主要是以下三個參數來控制
tcp_keepalives_interval
tcp_keepalives_idle
tcp_keepalives_count
預設沒有調整的時候會依照 OS 的設定值如下:
[root@EDB-Primary ~]# cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
[root@EDB-Primary ~]# cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
[root@EDB-Primary ~]# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
一般來說,通常遇到這類錯誤訊息基本上都不會等到那麼久,通常可能十幾分鐘就發現了,所以基本上與資料庫端的 Tcp Keepalive 設定無關,可能會是網路層 或 AP 的主機不確定是否有什麼設定。
理想的解法會是 AP 端自己做 Tcp Keepalive 的設定確認,可以的一個偷吃步方法是在資料庫端設定把 tcp_keepalives_idle 的時間設定很短,例如一分鐘檢查一次,這樣資料庫就會主動向 AP 端做 TCP Keep Alive 確認,就可以確保連線活著。