診斷子事務的瑞士軍刀

資料庫工作筆記發表於2023-12-20

來源:PostgreSQL學徒

前言

今天中午在網上衝浪的時候,偶然發現了兩個關於子事務的擴充套件,立馬來了興趣,關於子事務的篇章我寫了很多,其危害數不勝數,但是對於子事務的可觀測性,PG 又一直做得很爛,甚至都沒有一個像樣的檢視、表或者函式用於觀測子事務,一個典型場景就是 OGG 同步到 PG,那麼會在 PG 這一側開啟大量子事務,對於效能衝擊很大,每次碰到這類問題,除了觀測可能的等待事件 SubtransSLRU 、SubtransControlLock 之外,別無他法。所以,當我看到這兩個外掛時,立馬眼前一亮。讓我們小試牛刀一下!

pg_subtrans_infos

第一個擴充套件是 pg_subtrans_infos,允許觀測子事務的狀態 (另一款好用的 AWR 工具 pgsentinel 也是出自同一位作者)。

Allow to get subtransaction information thanks to a pg_subtrans_infos function.

讓我們看個例子:

postgres=# begin;
BEGIN
postgres=*# insert into test values(1,'hello');
INSERT 0 1
postgres=*# savepoint a;
SAVEPOINT
postgres=*# insert into test values(2,'world');
INSERT 0 1
postgres=*# savepoint b;
SAVEPOINT
postgres=*# insert into test values(3,'xiongcc');
INSERT 0 1
postgres=*# select xmin,* from test;
 xmin | id |  info   
------+----+---------
  866 |  1 | hello
  867 |  2 | world
  868 |  3 | xiongcc
(3 rows)

新開一個會話觀察:

postgres=# select * from pg_subtrans_infos(866);
 xid |   status    | parent_xid | top_parent_xid | sub_level | commit_timestamp 
-----+-------------+------------+----------------+-----------+------------------
 866 | in progress |            |                |           | 
(1 row)

postgres=# select * from pg_subtrans_infos(867);
 xid |   status    | parent_xid | top_parent_xid | sub_level | commit_timestamp 
-----+-------------+------------+----------------+-----------+------------------
 867 | in progress |        866 |            866 |         1 | 
(1 row)

postgres=# select * from pg_subtrans_infos(868);
 xid |   status    | parent_xid | top_parent_xid | sub_level | commit_timestamp 
-----+-------------+------------+----------------+-----------+------------------
 868 | in progress |        867 |            866 |         2 | 
(1 row)

866 是最頂層父事務,當出現了 overflow ,就需要遍歷 pg_subtrans SLRU 中的子事務樹,以獲取頂層事務 ID,訪問 SLRU 的過程中就會競爭 LWLock,如果更糟的話,SLRU 中找不到就會去磁碟上找,如果再出現長事務,那酸爽。

診斷子事務的瑞士軍刀

可以看到,pg_subtrans_infos 會將最底層父事務找出來,我們就可以找到該事務的直接元兇。其次,可以透過 SQL 更好地觀察子事務了,以官方提供的 SQL 為例

postgres=# select                               
        pid,
        locktype,
        mode,
        (select xid from pg_subtrans_infos(pgl.transactionid::text::bigint)),
        (select status from pg_subtrans_infos(pgl.transactionid::text::bigint)) as "xid status",
        (select parent_xid from pg_subtrans_infos(pgl.transactionid::text::bigint)),
        (select top_parent_xid from pg_subtrans_infos(pgl.transactionid::text::bigint)),
        (select sub_level from pg_subtrans_infos(pgl.transactionid::text::bigint)) sub_level,
        (select commit_timestamp from pg_subtrans_infos(pgl.transactionid::text::bigint))
from
(select * from pg_locks where transactionid is not null) pgl
order by 4;
  pid  |   locktype    |     mode      | xid | xid status  | parent_xid | top_parent_xid | sub_level | commit_timestamp 
-------+---------------+---------------+-----+-------------+------------+----------------+-----------+------------------
 26868 | transactionid | ExclusiveLock | 866 | in progress |            |                |           | 
 26868 | transactionid | ExclusiveLock | 867 | in progress |        866 |            866 |         1 | 
 26868 | transactionid | ExclusiveLock | 868 | in progress |        867 |            866 |         2 | 
(3 rows)

一目瞭然,父事務、子事務巢狀深度等等,可以大大方便我們排查子事務的效能問題。另外,我看官方例子支援檢視歷史事務的狀態,但是測試下來始終會報錯:ERROR:  transaction ID 3254 is in the future

另外好像缺了 overflow 的統計資料?莫急,pg_subxact_counters 擴充套件來幫忙。

pg_subxact_counters

此擴充套件用於獲取全域性子事務計數,記錄例項中所有資料庫的活動,比如子事務增長速度,是否 overflow (即單個會話超過 64 個) 等等。

Get global subtransactions counters.

The purpose of this extension is to provide counters to monitor the subtransactions (generation rate, overflow, state).

該擴充套件提供了四個函式

  • subxact_start: number of substransactions that started
  • subxact_commit: number of substransactions that committed
  • subxact_abort: number of substransactions that aborted (rolled back)
  • subxact_overflow: number of times a top level XID have had substransactions overflowed

subxact_overflow 指標至關重要。還是以官方提供樣例為例 (尷尬的是,我本地測了一下,發現會 segment fault,目前已經提了 issue) 雖然目前版本還有 BUG,畢竟剛剛 PR 幾個月,但是還是值得讓各位知曉此擴充套件。

postgres=# \dx+ pg_subxact_counters
Objects in extension "pg_subxact_counters"
       Object description
--------------------------------
 function pg_subxact_counters()
 view pg_subxact_counters
(2 rows)

postgres=# select * from pg_subxact_counters;
 subxact_start | subxact_commit | subxact_abort | subxact_overflow
---------------+----------------+---------------+------------------
             0 |              0 |             0 |                0
(1 row)

postgres=# begin;
BEGIN
postgres=*# savepoint a;
SAVEPOINT
postgres=*# savepoint b;
SAVEPOINT
postgres=*# commit;
COMMIT
postgres=# select * from pg_subxact_counters;
 subxact_start | subxact_commit | subxact_abort | subxact_overflow
---------------+----------------+---------------+------------------
             2 |              2 |             0 |                0
(1 row)

小結

這兩個擴充套件雖然目前版本還有些瑕疵,Anyway,能讓我們在碰到子事務相關問題的時候,會更加方便,有據可依。相信隨著迭代,這兩個擴充套件會更加成熟穩定。

參考


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70027826/viewspace-3000696/,如需轉載,請註明出處,否則將追究法律責任。

相關文章