標籤:
在資料庫postgresql中,一個用戶端到伺服器串連實際上是一個tcp socket串連,tcp串連是虛串連,一方非正常退出(如斷電),另一方會繼續維持這個串連。 舉個例子,一個用戶端電腦正常連上伺服器後,強行拔掉電源造成人為斷電,重新啟動電腦,再此連上伺服器。用SQL語句select * from pg_stat_activily 查看伺服器的所有串連,會發現本用戶端的串連除了本次外,斷電前的串連還在。因為伺服器根本不知道用戶端的斷電行為,還以為那串連正在空閑狀態。 然而這個死串連不會永遠存在,2個小時後,伺服器上的這個串連會自動切掉,因為postgresql支援TCP_KEEPLIVE機制。有三個 系統變數tcp_keepalives_idle,tcp_keepalives_interval ,tcp_keepalives_count 來設 置postgresql如何處理死串連。 對於每個串連,postgresql會對這個串連空閑tcp_keepalives_idle秒後,主動發送tcp_keeplive包給客戶 端,以偵探用戶端是否還活著 ,當發送tcp_keepalives_count個偵探包,每個偵探包在tcp_keepalives_interval 秒內沒有回應,postgresql就認為這個串連是死的。於是切斷這個死串連。 在postgresql, 這三個參數都設為0將使用作業系統的預設值,在linux下,tcp_keepalives_idle一般是2個小時,也就是2個小時後,伺服器才可以自動關掉死串連。在實際應運中,可以自行調整以上參數。 然而,單單依靠伺服器以此方法來切掉死串連,是永遠不夠。假設有一個串連,在運行以下互動式命令中突然斷電begin transaction;lock table xxx in exclusive mode;-- 突然斷電,這種可能很小,但肯定存在。。。commit 由於這個串連還保留著,且這個transaction還沒結束(本來上1秒之內的事務,現在變成至少要2個小時),所以這個表的鎖一直存在著,導致系統的並發性嚴重降低。 所以必需有手工殺掉串連的語句來切掉此串連,以釋放鎖。不幸的是,直到8.3,postgresql還沒有此語句,原始碼是有pg_terminate_query函數,因為有bug, 被屏蔽掉,必須到8.4才有。 所以只能用作業系統的命令殺掉此串連,或者重啟伺服器。 在linux下,殺掉此串連的命令是:kill -s SIGTERM 進程號。 這個內容有點老,但是思想是一一致的,詳細可參見:http://blog.163.com/[email protected]/blog/static/163877040201331041830502/
postgresql是如何處理死串連(轉)