1. 程式人生 > 其它 >pg9.6 超時空閒事務自動查殺功能

pg9.6 超時空閒事務自動查殺功能

熟悉 PostgreSQL 的朋友應該知道 “idle in transaction” 程序,引發 idle in transaction 的原因很多,例如應用程式碼中忘記關閉已開啟的事務,或者系統中存在僵死程序等,曾經看到過某個庫中的 idle in transaction 程序存在一年有餘,這類程序嚴重危害了資料庫的安全,例如它會阻止 VACUUM 程序回收記錄,造成表資料膨脹,同時它有可能引起整個 PostgreSQL 資料庫 Transaction ID Wraparound 的風險。

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.

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

--修改 postgresql.conf 以下引數

idle_in_transaction_session_timeout = 20000
 

備註:引數單位為毫秒,這裡設定 idle in transaction 超時空閒事務時間為 20 秒。

--過載配置檔案

  1.   [pg96@db1 pg_root]$ pg_ctl reload
  2.   server signaled

備註:此引數修改後對當前連線依然生效,應用不需要重連即能生效。

--開啟會話一:模擬一個事務

  1.   [pg96@db1 ~]$ psql francs francs
  2.   psql (9.6beta1)
  3.   Type "help" for help.
  4.    
  5.   francs=> begin;
  6.   BEGIN
  7.    
  8.   francs=> select 1;
  9.   ?column?
  10.   ----------
  11.   1
  12.   (1 row)

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

--開啟會話二:監控

  1.   postgres=# select * from pg_stat_activity where
    pid<>pg_backend_pid();
  2.   -[ RECORD 1 ]----+------------------------------
  3.   datid | 16386
  4.   datname | francs
  5.   pid | 7776
  6.   usesysid | 16384
  7.   usename | francs
  8.   application_name | psql
  9.   client_addr |
  10.   client_hostname |
  11.   client_port | -1
  12.   backend_start | 2016-06-01 16:03:12.557328+08
  13.   xact_start | 2016-06-01 16:03:16.921353+08
  14.   query_start | 2016-06-01 16:03:18.754706+08
  15.   state_change | 2016-06-01 16:03:18.755422+08
  16.   wait_event_type |
  17.   wait_event |
  18.   state | idle in transaction
  19.   backend_xid |
  20.   backend_xmin |
  21.   query | select 1;
  22.    
  23.   postgres=# select * from pg_stat_activity where pid<>pg_backend_pid();
  24.   (0 rows)

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

--再回到會話一

  1.   francs=> select 1;
  2.   ?column?
  3.   ----------
  4.   1
  5.    
  6.   FATAL: terminating connection due to idle-in-transaction timeout
  7.   server closed the connection unexpectedly
  8.   This probably means the server terminated abnormally
  9.   before or while processing the request.
  10.   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