在資料庫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 *** in exclusive mode;
-- 突然斷電,這種可能很小,但肯定存在
。。。commit
由於這個連線還保留著,且這個transaction還沒結束(本來上1秒之內的事務,現在變成至少要2個小時),所以這個表的鎖一直存在著,導致系統的併發性嚴重降低。
所以必需有手工殺掉連線的語句來切掉此連線,以釋放鎖。不幸的是,直到8.3,postgresql還沒有此語句,源**是有pg_terminate_query函式,因為有bug, 被遮蔽掉,必須到8.4才有。
所以只能用作業系統的命令殺掉此連線,或者重啟伺服器。 在linux下,殺掉此連線的命令是:
kill -s sigterm 程序號。
apue 8 5呼叫fork兩次以避免僵死程序
呼叫fork兩次以避免僵死程序 include apue.h include int main void else if pid 0 sleep 20 printf second child,parent pid d n getpid exit 0 第二個子程式退出 if waitpid pid,n...
linux僵死程序
乙個程序在呼叫exit命令結束自己的生命的時候,其實它並沒有真正的被銷毀,而是留下乙個稱為僵死程序 zombie 的資料結構 系統呼叫exit,它的作用是使程序退出,但也僅僅限於將乙個正常的程序變成乙個僵死程序,並不能將其完全銷毀 一 僵死程序的產生 在每個程序退出的時候,核心釋放該程序所有的資源,...
linux僵死程序
乙個程序在呼叫exit命令結束自己的生命的時候,其實它並沒有真正的被銷毀,而是留下乙個稱為僵死程序 zombie 的資料結構 系統呼叫exit,它的作用是使程序退出,但也僅僅限於將乙個正常的程序變成乙個僵死程序,並不能將其完全銷毀 一 僵死程序的產生 在每個程序退出的時候,核心釋放該程序所有的資源,...