PostgreSQL9.6:新增長「idle in transaction」超時空閒事務自動查殺功能

熟悉 PostgreSQL 的朋友應該知道 「idle in transaction」 進程,引起 idle in transaction 的緣由不少,例如應用代碼中忘記關閉已開啓的事務,或者系統中存在僵死進程等,曾經看到過某個庫中的 idle in transaction 進程存在一年有餘,這類進程嚴重危害了數據庫的安全,例如它會阻止 VACUUM 進程回收記錄,形成表數據膨脹,同時它有可能引發整個 PostgreSQL 數據庫 Transaction ID Wraparound 的風險。html

Allow sessions to be terminated automatically if they sit too long in
an idle-in-transaction state (Vik Fearing) This behavior is enabled
and controlled by the new configuration parameter
idle_in_transaction_session_timeout. It can be useful to prevent
forgotten transactions from holding onto locks or preventing vacuum
cleanup for very long periods.sql

以上出自 PostgreSQL9.6 Beta1 發行說明,這段指出9.6版本 PostgreSQL 支持自動查殺超過指定時間的 idle in transaction 空閒事務鏈接,下面演示下。數據庫

--修改 postgresql.conf 如下參數安全

idle_in_transaction_session_timeout = 20000

備註:參數單位爲毫秒,這裏設置 idle in transaction 超時空閒事務時間爲 20 秒。session

--重載配置文件app

[pg96@db1 pg_root]$ pg_ctl reload
server signaled

備註:此參數修改後對當前鏈接依然生效,應用不須要重連即能生效。post

--開啓會話一:模擬一個事務測試

[pg96@db1 ~]$ psql francs francs
psql (9.6beta1)
Type "help" for help.

francs=> begin;
BEGIN

francs=> select 1;
 ?column? 
----------
        1
(1 row)

事務中,不提交也不回滾。日誌

--開啓會話二:監控postgresql

postgres=# select * from pg_stat_activity where pid<>pg_backend_pid();
-[ RECORD 1 ]----+------------------------------
datid            | 16386
datname          | francs
pid              | 7776
usesysid         | 16384
usename          | francs
application_name | psql
client_addr      | 
client_hostname  | 
client_port      | -1
backend_start    | 2016-06-01 16:03:12.557328+08
xact_start       | 2016-06-01 16:03:16.921353+08
query_start      | 2016-06-01 16:03:18.754706+08
state_change     | 2016-06-01 16:03:18.755422+08
wait_event_type  | 
wait_event       | 
state            | idle in transaction
backend_xid      | 
backend_xmin     | 
query            | select 1;

postgres=# select * from pg_stat_activity where pid<>pg_backend_pid();
(0 rows)

備註:開始還能監控到這個 "idle in transaction" 的事務,大概過了 20秒後,這個事務查詢不到了。

--再回到會話一

francs=> select 1;
 ?column? 
----------
        1
        
FATAL:  terminating connection due to idle-in-transaction timeout
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

備註:回到會話一執行 select 1 測試命令,發現鏈接被斷開了,報錯代碼很明顯,idle-in-transaction 超時了。

--數據庫日誌

2016-06-01 16:03:38.756
CST,"francs","francs",7776,"[local]",574e96c0.1e60,1,"idle in
transaction",2016-06-01 16:03:12 CST,2/5887,0,FATAL,25P03,"terminating
connection due to idle-in-transaction timeout",,,,,,,,,"psql"

備註:數據庫日誌裏清晰地記錄了 7796 進程的鏈接因爲空閒事務超時被斷開鏈接。

--參考
idle_in_transaction_session_timeout (integer)
Preventing Transaction ID Wraparound Failures

相關文章
相關標籤/搜索