暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

理解 pg_stat_activity

原创 谭磊Terry 恩墨学院 2022-08-20
6048

pg_stat_activity是系统视图,显示数据库中当前正在发生的事情。

对于较新的 pgs,它相当宽(我写这篇文章时有 22 列)。而且,这一切意味着什么并不总是很明显。所以让我们试着弄清楚。

使用用户测试连接到数据库depesz并获得:

$ select * from pg_stat_activity ;
 datid  │ datname  │  pid   │ leader_pid │ usesysid │ usename │ application_name │ client_addr │ client_hostname │ client_port │         backend_start         │          xact_start           │          query_start          │        state_change         │ wait_event_type │ wait_event │ state  │ backend_xid │ backend_xmin │      query_id       │              query               │  backend_type  
────────┼──────────┼────────┼────────────┼──────────┼─────────┼──────────────────┼─────────────┼─────────────────┼─────────────┼───────────────────────────────┼───────────────────────────────┼───────────────────────────────┼─────────────────────────────┼─────────────────┼────────────┼────────┼─────────────┼──────────────┼─────────────────────┼──────────────────────────────────┼────────────────
 [null] │ [null]   │  87714 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 [null] │ [null]   │  87716 │     [null] │       10 │ pgdba   │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 325115 │ depesz   │ 849586 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 325115 │ depesz   │ 848113 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │       16596 │       [null] │              [null] │ <insufficient privilege>         │ [null]
 325115 │ depesz   │ 848261 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │        16593 │              [null] │ <insufficient privilege>         │ [null]
      5 │ postgres │ 848535 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │       16593 │       [null] │              [null] │ <insufficient privilege>         │ [null]
      5 │ postgres │ 848405 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │        16593 │              [null] │ <insufficient privilege>         │ [null]
 325115 │ depesz   │ 848805 │     [null] │    16390 │ test    │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:43:41.338899+02 │ 2022-07-04 16:47:16.559599+02 │ 2022-07-04 16:47:16.559599+02 │ 2022-07-04 16:47:16.5596+02 │ [null]          │ [null]     │ active │      [null] │        16593 │ -907669364431849768 │ select * from pg_stat_activity ; │ client backend
 [null] │ [null]   │  87711 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 [null] │ [null]   │  87715 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 [null] │ [null]   │  87710 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
 [null] │ [null]   │  87713 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ [null]                        │ [null]                        │ [null]                        │ [null]                      │ [null]          │ [null]     │ [null] │      [null] │       [null] │              [null] │ <insufficient privilege>         │ [null]
(12 rows)

我注意到的第一件事是查询列中的值:。这是因为用户 test 不是超级用户,因此看不到其他用户在做什么。但是,它可以看到自己的查询,我们可以在与 pid 848805 连接的数据中看到:

$ select * from pg_stat_activity where pid = 848805 \gx
─[ RECORD 1 ]────┬───────────────────────────────────────────────────
datid            │ 325115
datname          │ depesz
pid              │ 848805
leader_pid       │ [null]
usesysid         │ 16390
usename          │ test
application_name │ psql
client_addr      │ [null]
client_hostname  │ [null]
client_port      │ -1
backend_start    │ 2022-07-04 16:43:41.338899+02
xact_start       │ 2022-07-04 16:49:18.495575+02
query_start      │ 2022-07-04 16:49:18.495575+02
state_change     │ 2022-07-04 16:49:18.495577+02
wait_event_type  │ [null]
wait_event       │ [null]
state            │ active
backend_xid      │ [null]
backend_xmin     │ 16593
query_id         │ 8210364456846404087
query            │ select * from pg_stat_activity where pid = 848805 
backend_type     │ client backend

切换到超级用户后,我可以看到:

$ select * from pg_stat_activity;
 datid  │ datname  │  pid   │ leader_pid │ usesysid │ usename │ application_name │ client_addr │ client_hostname │ client_port │         backend_start         │          xact_start           │          query_start          │         state_change          │ wait_event_type │     wait_event      │        state        │ backend_xid │ backend_xmin │      query_id       │                                 query                                 │         backend_type         
────────┼──────────┼────────┼────────────┼──────────┼─────────┼──────────────────┼─────────────┼─────────────────┼─────────────┼───────────────────────────────┼───────────────────────────────┼───────────────────────────────┼───────────────────────────────┼─────────────────┼─────────────────────┼─────────────────────┼─────────────┼──────────────┼─────────────────────┼───────────────────────────────────────────────────────────────────────┼──────────────────────────────
 [null] │ [null]   │  87714 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737082+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ AutoVacuumMain      │ [null]              │      [null] │       [null] │              [null] │                                                                       │ autovacuum launcher
 [null] │ [null]   │  87716 │     [null] │       10 │ pgdba   │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737313+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ LogicalLauncherMain │ [null]              │      [null] │       [null] │              [null] │                                                                       │ logical replication launcher
 325115 │ depesz   │ 849586 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:45:03.983256+02 │ [null]                        │ 2022-07-04 16:45:54.774817+02 │ 2022-07-04 16:45:54.775426+02 │ Client          │ ClientRead          │ idle                │      [null] │       [null] │  328096568509443406 │ SELECT n.nspname AS "Name",                                          ↵│ client backend
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │   pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner",                 ↵│ 
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │   pg_catalog.array_to_string(n.nspacl, E'\n') AS "Access privileges",↵│ 
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │   pg_catalog.obj_description(n.oid, 'pg_namespace') AS "Description" ↵│ 
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │ FROM pg_catalog.pg_namespace n                                       ↵│ 
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │ WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'      ↵│ 
        │          │        │            │          │         │                  │             │                 │             │                               │                               │                               │                               │                 │                     │                     │             │              │                     │ ORDER BY 1;                                                           │ 
 325115 │ depesz   │ 848113 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:42:47.613258+02 │ 2022-07-04 16:43:32.90074+02  │ 2022-07-04 16:43:35.176834+02 │ 2022-07-04 16:43:35.177334+02 │ Client          │ ClientRead          │ idle in transaction │       16596 │       [null] │  -58199854079439753 │ drop table q;                                                         │ client backend
 325115 │ depesz   │ 848261 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:42:54.562032+02 │ 2022-07-04 16:43:37.768588+02 │ 2022-07-04 16:43:37.768588+02 │ 2022-07-04 16:43:37.76859+02  │ Lock            │ relation            │ active              │      [null] │        16593 │              [null] │ select * from q;                                                      │ client backend
      5 │ postgres │ 848535 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:43:03.427086+02 │ 2022-07-04 16:43:10.942546+02 │ 2022-07-04 16:43:12.494412+02 │ 2022-07-04 16:43:12.497506+02 │ Client          │ ClientRead          │ idle in transaction │       16593 │       [null] │  389562163604003053 │ drop table z;                                                         │ client backend
      5 │ postgres │ 848405 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:42:59.671318+02 │ 2022-07-04 16:43:15.250683+02 │ 2022-07-04 16:43:15.250683+02 │ 2022-07-04 16:43:15.250685+02 │ Lock            │ relation            │ active              │      [null] │        16593 │              [null] │ select * from z;                                                      │ client backend
 325115 │ depesz   │ 852004 │     [null] │       10 │ pgdba   │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:50:25.426408+02 │ 2022-07-04 16:50:45.614384+02 │ 2022-07-04 16:50:45.614384+02 │ 2022-07-04 16:50:45.614385+02 │ [null]          │ [null]              │ active              │      [null] │        16593 │ -907669364431849768 │ select * from pg_stat_activity                                        │ client backend
 [null] │ [null]   │  87711 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.731409+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ BgWriterHibernate   │ [null]              │      [null] │       [null] │              [null] │                                                                       │ background writer
 [null] │ [null]   │  87715 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737179+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ ArchiverMain        │ [null]              │      [null] │       [null] │              [null] │                                                                       │ archiver
 [null] │ [null]   │  87710 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.731313+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ CheckpointerMain    │ [null]              │      [null] │       [null] │              [null] │                                                                       │ checkpointer
 [null] │ [null]   │  87713 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.736982+02 │ [null]                        │ [null]                        │ [null]                        │ Activity        │ WalWriterMain       │ [null]              │      [null] │       [null] │              [null] │                                                                       │ walwriter
(12 rows)

好的。所有的列。但对他们真的意味着什么?

首先——这个视图为每个后端进程显示一行。大多数这些,在普通系统中(这只是我桌面上的测试数据库)将是来自应用程序的连接。但不是所有的。

每个进程都有它的 PID(进程号),您始终可以使用以下方法从 DB 连接中检查您自己的 PID:

$ select pg_backend_pid();
 pg_backend_pid 
────────────────
         852004
(1 row)

这与系统可见的 PID 相同,例如,在使用ps命令时:

=$ ps uw -p 852004
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
pgdba     852004  0.0  0.0 216984 19516 ?        Ss   16:50   0:00 postgres: pgdba depesz [local] idle

所以,让我们深入挖掘。我们将从……从头开始。最后一列是 backend_type:

$ select pid, backend_type from pg_stat_activity order by backend_type, pid;
  pid   │         backend_type         
────────┼──────────────────────────────
  87715 │ archiver
  87714 │ autovacuum launcher
  87711 │ background writer
  87710 │ checkpointer
 848261 │ client backend
 848405 │ client backend
 848535 │ client backend
 849586 │ client backend
 852004 │ client backend
 853274 │ client backend
  87716 │ logical replication launcher
  87713 │ walwriter
(12 rows)

“客户端后端”基本上是您与应用程序的正常连接。所有其他连接都是“做事”的特殊进程:

  • archiver – 运行 archive_command(或在较新的 pgs 中等效)
  • autovacuum 启动器——当需要对某些东西进行 vacuum /分析时,启动 autovacuum workers
  • 后台写入器——在后台将数据写入表/索引
  • checkpointer 处理检查点——基本上是不时地将所有修改的数据写入表/索引文件
  • 逻辑复制启动器——管理与逻辑复制相关的进程
  • walwriter – 将数据更改写入 WAL

除了这些,您还可以看到:

  • autovacuum worker – 实际上为 autovacuum 做一些 vacuum /分析工作
  • 逻辑复制工作者——处理逻辑复制
  • 并行工作者 - 由客户端后端启动的特殊后端,其中查询正在并行处理
  • 启动 - 从某个地方应用 WAL,这是负责恢复和流/wal 复制的过程
  • walreceiver – 在流复制设置中从源接收 wal 流
  • walsender – 通过流将 wal 发送到某个副本

如果您使用专门的扩展,您还可以看到一些其他类型。

知道了这一点,让我们回顾一下我们的数据,它的另一个子集:

$ select * from pg_stat_activity where backend_type <> 'client backend';
 datid  │ datname │  pid  │ leader_pid │ usesysid │ usename │ application_name │ client_addr │ client_hostname │ client_port │         backend_start         │ xact_start │ query_start │ state_change │ wait_event_type │     wait_event      │ state  │ backend_xid │ backend_xmin │ query_id │ query │         backend_type         
────────┼─────────┼───────┼────────────┼──────────┼─────────┼──────────────────┼─────────────┼─────────────────┼─────────────┼───────────────────────────────┼────────────┼─────────────┼──────────────┼─────────────────┼─────────────────────┼────────┼─────────────┼──────────────┼──────────┼───────┼──────────────────────────────
 [null] │ [null]  │ 87714 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737082+02 │ [null]     │ [null]      │ [null]       │ Activity        │ AutoVacuumMain      │ [null] │      [null] │       [null] │   [null] │       │ autovacuum launcher
 [null] │ [null]  │ 87716 │     [null] │       10 │ pgdba   │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737313+02 │ [null]     │ [null]      │ [null]       │ Activity        │ LogicalLauncherMain │ [null] │      [null] │       [null] │   [null] │       │ logical replication launcher
 [null] │ [null]  │ 87711 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.731409+02 │ [null]     │ [null]      │ [null]       │ Activity        │ BgWriterHibernate   │ [null] │      [null] │       [null] │   [null] │       │ background writer
 [null] │ [null]  │ 87715 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.737179+02 │ [null]     │ [null]      │ [null]       │ Activity        │ ArchiverMain        │ [null] │      [null] │       [null] │   [null] │       │ archiver
 [null] │ [null]  │ 87710 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.731313+02 │ [null]     │ [null]      │ [null]       │ Activity        │ CheckpointerMain    │ [null] │      [null] │       [null] │   [null] │       │ checkpointer
 [null] │ [null]  │ 87713 │     [null] │   [null] │ [null]  │                  │ [null]      │ [null]          │      [null] │ 2022-07-01 10:55:08.736982+02 │ [null]     │ [null]      │ [null]       │ Activity        │ WalWriterMain       │ [null] │      [null] │       [null] │   [null] │       │ walwriter
(6 rows)

请注意,大多数列都是空的,因为——嗯,这些是没有连接到任何特定数据库的进程,也没有使用任何特定用户(除了逻辑复制启动器)。通常你并不真正关心他们。

对于其他后端(在我的情况下,只有普通的客户端后端):

$ select * from pg_stat_activity where backend_type = 'client backend';
 datid  │ datname  │  pid   │ leader_pid │ usesysid │ usename │ application_name │ client_addr │ client_hostname │ client_port │         backend_start         │          xact_start           │          query_start          │         state_change          │ wait_event_type │ wait_event │        state        │ backend_xid │ backend_xmin │       query_id       │                                 query                                 │  backend_type  
────────┼──────────┼────────┼────────────┼──────────┼─────────┼──────────────────┼─────────────┼─────────────────┼─────────────┼───────────────────────────────┼───────────────────────────────┼───────────────────────────────┼───────────────────────────────┼─────────────────┼────────────┼─────────────────────┼─────────────┼──────────────┼──────────────────────┼───────────────────────────────────────────────────────────────────────┼────────────────
      5 │ postgres │ 848405 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:42:59.671318+02 │ 2022-07-04 16:43:15.250683+02 │ 2022-07-04 16:43:15.250683+02 │ 2022-07-04 16:43:15.250685+02 │ Lock            │ relation   │ active              │      [null] │        16593 │               [null] │ select * from z;                                                      │ client backend
      5 │ postgres │ 848535 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:43:03.427086+02 │ 2022-07-04 16:43:10.942546+02 │ 2022-07-04 16:43:12.494412+02 │ 2022-07-04 16:43:12.497506+02 │ Client          │ ClientRead │ idle in transaction │       16593 │       [null] │   389562163604003053 │ drop table z;                                                         │ client backend
 325115 │ depesz   │ 848261 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:42:54.562032+02 │ 2022-07-04 16:53:24.693972+02 │ 2022-07-04 16:53:24.693972+02 │ 2022-07-04 16:53:24.693974+02 │ Lock            │ relation   │ active              │      [null] │        16593 │               [null] │ select * from q;                                                      │ client backend
 325115 │ depesz   │ 853274 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:53:19.46231+02  │ 2022-07-04 16:53:21.765739+02 │ 2022-07-04 16:53:23.106893+02 │ 2022-07-04 16:53:23.107714+02 │ Client          │ ClientRead │ idle in transaction │       16597 │       [null] │   -58199854079439753 │ drop table q;                                                         │ client backend
 325115 │ depesz   │ 864116 │     [null] │    16384 │ depesz  │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 17:10:43.001571+02 │ [null]                        │ 2022-07-04 17:10:44.682067+02 │ 2022-07-04 17:10:44.682396+02 │ Client          │ ClientRead │ idle                │      [null] │       [null] │ -2698492627503961632 │ select 1;                                                             │ client backend
 325115 │ depesz   │ 852004 │     [null] │       10 │ pgdba   │ psql             │ [null]      │ [null]          │          -1 │ 2022-07-04 16:50:25.426408+02 │ 2022-07-04 17:10:54.757781+02 │ 2022-07-04 17:10:54.757781+02 │ 2022-07-04 17:10:54.757783+02 │ [null]          │ [null]     │ active              │      [null] │        16593 │ -2404663320170207359 │ select * from pg_stat_activity where backend_type = 'client backend'  │ client backend
(6 rows)

datid 和 datname 基本上只是这个后端连接到哪个数据库的信息。您可以看到这些值在 pg_database 表中显示为 oid 和 datname:

$ select oid, datname from pg_database where datname in ('postgres', 'depesz');
  oid   │ datname  
────────┼──────────
      5 │ postgres
 325115 │ depesz
(2 rows)

这向我们展示了一件重要的事情——pg_stat_activity 包含有关所有数据库的信息。不仅是您连接的那个。如果您在某些数据库中寻找问题的根源,并且您不断看到与其他数据库的连接使信息变得模糊,这有时可能会出现问题。

因此,您可能希望将where datname = current_database()添加到您的查询中。

接下来是pid,我解释过,然后是leader_pid。这通常是NULL。如果您有并行化查询,则它不为空,在这种情况下,并行工作者后端将在启动它们的后端的leader_pid列 pid 中(真实的原始数据库连接),如下所示:

 pid   │ leader_pid │  backend_type   │                   query                   
────────┼────────────┼─────────────────┼───────────────────────────────────────────
 867808 │     [null] │ client backend  │ select sum(length(p::text)) from plans p;
 868383 │     867808 │ parallel worker │ select sum(length(p::text)) from plans p;
 868384 │     867808 │ parallel worker │ select sum(length(p::text)) from plans p;
(3 rows)

这表明与 pid 867808 的连接启动了一个查询,Pg 决定启动两个额外的工作程序以更快地计算它。一旦此查询结束,这些后端 worker 就会消失。

接下来在 pg_stat_activity 我们有用户信息:usesysid 和 usename。就像数据库名称/ID 一样,这些是关于用户的相同信息,您可以在select usesysid, usename from pg_user中看到这些信息。

接下来是application_name。这是应用程序提供的名称,您可以随时更改它:

$ select application_name from pg_stat_activity where pid = pg_backend_pid();
 application_name 
──────────────────
 psql
(1 row)
 
$ set application_name = 'magic';
SET
 
$ select application_name from pg_stat_activity where pid = pg_backend_pid();
 application_name 
──────────────────
 magic
(1 row)

我假设在大多数语言中,您可以使用数据库连接参数设置应用程序名称,或者,如果您的应用程序使用标准 libpq,您可以使用环境变量 PGAPPNAME:

=$ psql -c 'select application_name from pg_stat_activity where pid = pg_backend_pid()'
 application_name 
------------------
 psql
(1 row)
 
=$ PGAPPNAME=testing psql -c 'select application_name from pg_stat_activity where pid = pg_backend_pid()'
 application_name 
------------------
 testing
(1 row)

当涉及到调试问题时,这个东西(application_name)绝对是惊人的。如果您不使用它 - 开始。

pg_stat_activity 中的下一件事是 3 列,它们告诉我们用户从哪里连接:
1、client_addr – 客户端机器的 ip
2、client_hostname – 客户端机器的主机名
3、client_port – 连接的源端口

问题是 PostgreSQL 可以使用两种方式连接:

  • TCP/IP 连接——基本上是通过网络,来自另一台服务器,或者,有时,来自使用localhost作为服务器的同一台机器
  • UNIX 套接字 - 可用于连接的特殊神奇“文件”,仅在本地。运行 psql 或其他 CLI 应用程序时的默认设置。

对于 UNIX 套接字——client_addr 和 client_hostname 为 NULL,端口设置为 -1,但如果我使用 TCP/IP 连接:

=$ psql -h localhost -c 'select client_addr, client_hostname, client_port from pg_stat_activity where pid = pg_backend_pid()'
 client_addr │ client_hostname │ client_port 
─────────────┼─────────────────┼─────────────
 127.0.0.1   │ [null]          │       43574
(1 row)

client_hostname 为空,因为要使其可见,我必须打开log_hostname配置变量,我不这样做,因为它不是必需的(对我来说)。

接下来是 4 列,其中之一是最常被误解的:

  • backend_start – 当这个后端启动时 – 基本上,在客户端后端的情况下 – 当客户端连接时。
  • xact_start – 当前活动事务何时开始。应该理解的是,即使您没有执行BEGIN – 每个查询本身都在事务中,所以只有当您不在事务中并且您当前没有处理任何事情时,它才会为空。
  • query_start – 上次开始的查询是什么时候开始的。此查询可能已经结束。但是 query_start 仍然存在——这是经常被误解的一件事。
  • state_change – 后端状态最后一次更改是什么时候。这可能是在后端空闲的情况下——最后一个查询何时结束——因为状态从活动变为空闲。

query_start 的问题在于人们似乎认为now() – query_start的意思是:查询运行了多长时间(到目前为止)。如果后端当前正在处理某些事情(状态 = ‘活动’),它有点像。但是如果它是空闲的,那么这个计算就没有任何意义了,因为它现在什么都做不了。让我们看一个例子:

$ select pid, now() - query_start as duration, query_start, state_change, state, query from pg_stat_activity where backend_type = 'client backend';
  pid   │    duration     │          query_start          │         state_change          │        state        │                                                                       query                                                                       
────────┼─────────────────┼───────────────────────────────┼───────────────────────────────┼─────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 864116 │ 00:26:46.690661 │ 2022-07-04 17:10:44.682067+02 │ 2022-07-04 17:10:44.682396+02 │ idle                │ select 1;
 853274 │ 00:44:08.265835 │ 2022-07-04 16:53:23.106893+02 │ 2022-07-04 16:53:23.107714+02 │ idle in transaction │ drop table q;
 848261 │ 00:44:06.678756 │ 2022-07-04 16:53:24.693972+02 │ 2022-07-04 16:53:24.693974+02 │ active              │ select * from q;
 848535 │ 00:54:18.878316 │ 2022-07-04 16:43:12.494412+02 │ 2022-07-04 16:43:12.497506+02 │ idle in transaction │ drop table z;
 848405 │ 00:54:16.122045 │ 2022-07-04 16:43:15.250683+02 │ 2022-07-04 16:43:15.250685+02 │ active              │ select * from z;
 868019 │ 00:00:00.709748 │ 2022-07-04 17:37:30.66298+02  │ 2022-07-04 17:37:30.663767+02 │ idle                │ select pid, leader_pid, backend_type, query from pg_stat_activity  where datname = 'depesz_explain' and pid <> pg_backend_pid() 
 852004 │ 00:00:00        │ 2022-07-04 17:37:31.372728+02 │ 2022-07-04 17:37:31.372729+02 │ active              │ select pid, now() - query_start as duration, query_start, state_change, state, query from pg_stat_activity where backend_type = 'client backend';
 867808 │ 00:18:16.976686 │ 2022-07-04 17:19:14.396042+02 │ 2022-07-04 17:19:37.187507+02 │ idle                │ select sum(length(p::text)) from plans p;
(8 rows)

请注意,只有 3 个后端在做某事(pids 848261、848405、852004)。对他们来说,持续时间栏是有意义的。对于所有其他人 - 它没有。

那么为什么’查询’列中有东西?答案很简单——这是此后端中最后处理的查询。它可能是当前的(在 state = ‘active’ 的情况下),但对于 idle/idle-in-transaction - 这只是从query_start 开始并在state_change完成的最后一个查询。

这个问题被报告为“长时间运行的琐碎查询,例如’select 1’或’commit’,经常如此,这就是我写这篇博文的基本原因。

因此,虽然还有其他状态,但最常见的 3 个状态是:

  • active - 后端正在积极处理查询(它可能被锁定,但它正在尝试这样做)
  • idle - 后端完成了所有之前给定的工作,并且没有做任何事情。它不在事务中,它不持有任何锁,它只是存在。
  • idle in transaction —— 至少从2008 年开始就是我存在的祸根。这意味着后端已经开始事务,可能有一些查询在其中运行,但目前它没有做任何事情。空转。但是在事务中,这意味着在该事务中的所有查询期间获得的所有锁仍然被持有,并且可以锁定其他后端进行生产性工作

这给我们留下了中间的五列来解释:

  pid   │ wait_event_type │ wait_event │ backend_xid │ backend_xmin │       query_id       │                                                                      query                                                                       
────────┼─────────────────┼────────────┼─────────────┼──────────────┼──────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 864116 │ Client          │ ClientRead │      [null] │       [null] │ -2698492627503961632 │ select 1;
 853274 │ Client          │ ClientRead │       16597 │       [null] │   -58199854079439753 │ drop table q;
 848261 │ Lock            │ relation   │      [null] │        16593 │               [null] │ select * from q;
 848535 │ Client          │ ClientRead │       16593 │       [null] │   389562163604003053 │ drop table z;
 848405 │ Lock            │ relation   │      [null] │        16593 │               [null] │ select * from z;
 868019 │ Client          │ ClientRead │      [null] │       [null] │  1114137780797701598 │ select pid, leader_pid, backend_type, query from pg_stat_activity  where datname = 'depesz_explain' and pid <> pg_backend_pid() 
 852004 │ [null]          │ [null]     │      [null] │        16593 │  7635051274713358230 │ select pid, wait_event_type, wait_event, backend_xid, backend_xmin, query_id, query from pg_stat_activity where backend_type = 'client backend';
 867808 │ Client          │ ClientRead │      [null] │       [null] │ -2698492627503961632 │ select 2;
(8 rows)

意思是:

  • wait_event_type - 基本上是后端当前正在等待的事件类别。它可能是许多事情之一,但最有趣/最常见的是:
    • 客户端 - 后端正在等待客户端接收数据或发送新查询,它没有被锁定 —— 客户端必须做一些事情
    • 锁定 - 后端实际上被锁定在某些东西上(很可能被另一个后端锁定)
    • NULL - 后端没有等待 - 它正在处理某些事情(当前查询)
    • IO - 后端正在等待磁盘做任何需要做的事情(读/写的东西)
  • wait_event – 有关它可能是什么的更详细信息。例如,在 wait_event_type = ‘Lock’ 的情况下,您可以有11 个不同的 wait_events,每个都是不同类型的锁。
  • backend_xid – 后端当前处理的事务的事务 ID,如果它在内部事务中
  • backend_xmin – 与“此后端可以看到哪些数据更改”相关的内部数据
  • query_id – 查询的数字哈希,删除所有参数。请注意 pids 864116 和 867808 的 query_id 是相同的,尽管查询是不同的——这是因为参数无关紧要,所以“选择 1”可以像“选择 2”一样对待

我希望这将有助于消除关于阅读 pg_stat_activity 并将 query_start 理解为当前处理的查询的无条件开始的困惑。

原文标题:Understanding pg_stat_activity
原文地址:https://www.depesz.com/2022/07/05/understanding-pg_stat_activity/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论