文章目录
利用视图 pg_stat_activity 查看连接会话
通过操作系统命令查看连接会话
利用 pg_cancel_backend() 终止正在运行的语句
通过操作系统命令终止正在运行的语句
利用 pg_terminate_backend() 终止连接会话
通过操作系统命令终止连接会话
今天给大家介绍一下如何如何查看和终止 PostgreSQL 的连接会话。
在 PostgreSQL 中,配置参数 max_connections 决定了数据库的并发连接上限,默认值为 100:
postgres=> show max_connections;
max_connections
-----------------
100
(1 row)
这个数值还包括了预留给 superuser 的一些连接,具体数量由参数 superuser_reserved_connections 决定:
postgres=> show superuser_reserved_connections;
superuser_reserved_connections
--------------------------------
3
(1 row)
也就是说,当连接数到达 max_connections - superuser_reserved_connections 时,只有超级用户才能建立新的数据库连接;普通用户连接时将会返回错误信息“FATAL: sorry, too many clients already.”或者“FATAL: remaining connection slots are reserved for non-replication superuser connections”。当我们遇到这种连接数过多的错误,或者由于其他原因需要找出目前存在哪些客户端的连接时,可以采用以下方法。
利用视图 pg_stat_activity 查看连接会话
PostgreSQL 动态统计视图 pg_stat_activity 中的每一行代表了一个后台进程,包含了该进程当前活动相关的信息。
postgres=> select pid,
datname as database_name,
usename as user_name,
application_name,
client_addr,
backend_start,
state,
state_change,
wait_event_type,
wait_event,
query,
backend_type
from pg_catalog.pg_stat_activity;
pid |database_name|user_name|application_name |client_addr |backend_start |state |state_change |wait_event_type|wait_event |query |backend_type |
-----|-------------|---------|-----------------------------------------|------------|-------------------|------|-------------------|---------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
1677| | | | |2020-07-06 09:29:33| | |Activity |AutoVacuumMain | |autovacuum launcher |
1679| |postgres | | |2020-07-06 09:29:33| | |Activity |LogicalLauncherMain| |logical replication launcher|
23483|hrdb |postgres |DBeaver 7.1.2 - Main <hrdb> |192.168.56.1|2020-07-08 08:09:58|idle |2020-07-08 08:09:58|Client |ClientRead |SHOW search_path |client backend |
23484|hrdb |postgres |DBeaver 7.1.2 - Metadata <hrdb> |192.168.56.1|2020-07-08 08:09:58|idle |2020-07-08 08:09:58|Client |ClientRead |SELECT t.oid,t.*,c.relkind,format_type(nullif(t.typbasetype, 0), t.typtypmod) as base_type_name¶FROM pg_catalog.pg_type t¶LEFT OUTER JOIN pg_class c ON c.oid=t.typrelid¶WHERE typnamespace=$1 ¶ORDER by t.oid |client backend |
23486|pagila |postgres |DBeaver 7.1.2 - SQLEditor <Script-13.sql>|192.168.56.1|2020-07-08 08:09:58|active|2020-07-08 08:10:30| | |select pid,¶ datname as database_name,¶ usename as user_name,¶ application_name,¶ client_addr,¶ backend_start,¶ state,¶ state_change,¶ wait_event_type,¶ wait_event,¶ query,¶ backend_type¶fr|client backend |
23487|pagila |postgres |DBeaver 7.1.2 - Main <pagila> |192.168.56.1|2020-07-08 08:09:58|idle |2020-07-08 08:09:58|Client |ClientRead |SHOW search_path |client backend |
23488|pagila |postgres |DBeaver 7.1.2 - Metadata <pagila> |192.168.56.1|2020-07-08 08:09:58|idle |2020-07-08 08:10:00|Client |ClientRead |SELECT t.oid,t.*,c.relkind,format_type(nullif(t.typbasetype, 0), t.typtypmod) as base_type_name FROM pg_catalog.pg_type t¶LEFT OUTER JOIN pg_class c ON c.oid=t.typrelid¶WHERE t.oid=$1 |client backend |
1675| | | | |2020-07-06 09:29:33| | |Activity |BgWriterHibernate | |background writer |
1674| | | | |2020-07-06 09:29:33| | |Activity |CheckpointerMain | |checkpointer |
1676| | | | |2020-07-06 09:29:33| | |Activity |WalWriterMain | |walwriter |
查询结果不仅返回了客户端连接对应的服务器进程,也包括 PostgreSQL 服务器的各种守护进程。其中,
pid 代表了后台进程的 id;
datname 是进程连接的数据库,对于后台守护进程显示为空;
usename 是连接数据库使用的用户名,对于后台守护进程显示为空;
application_name 是连接数据库的应用程序,对于后台守护进程显示为空;
client_addr 是客户端的 IP 地址,对于后台守护进程或者通过 Unix 套接字连接的进程显示为空;
backend_start 是进程启动的时间点,对于客户端的后台进程是连接服务器的时间点;
state 代表了进程当前的状态,可能的取值包括 active、idle、idle in transaction、idle in transaction (aborted)、fastpath function call 以及 disabled;
state_change 是最后一次状态的修改时间;
wait_event_type 表示进程正在等待的事件类型,如果没有等待显示为空;可能的取值包括 LWLock、Lock、BufferPin、Activity、Extension、Client、IPC、Timeout 以及 IO;
wait_event 表示进程正在等待的事件名称,如果没有等待显示为空;
query 是进程最后一次执行的查询语句。对于 active 状态,显示正在执行的查询;其他状态显示上一次执行的查询;
backend_type 是进程的类型。
📝等待事件 wait_event 和进程状态 state 是相互独立的。如果进程处于 active 状态,可能正在等待某个事件,也可能没有等待事件如果状态为 active 并且 wait_event 不为空,意味着正在执行的查询被其他进程阻塞。
视图 pg_stat_activity 中还包含了更多的字段,具体可以参考官方文档。
通过操作系统命令查看连接会话
对于 Linux 操作系统,我们也可以使用ps命令查看 PostgreSQL 后台进程:
ps -ef|grep 'postgres'|grep -v 'grep'
postgres 1258 1 0 Jul06 ? 00:00:09 /usr/pgsql-12/bin/postmaster -D /var/lib/pgsql/12/data/
postgres 1335 1258 0 Jul06 ? 00:00:00 postgres: logger
postgres 1674 1258 0 Jul06 ? 00:00:00 postgres: checkpointer
postgres 1675 1258 0 Jul06 ? 00:00:05 postgres: background writer
postgres 1676 1258 0 Jul06 ? 00:00:05 postgres: walwriter
postgres 1677 1258 0 Jul06 ? 00:00:05 postgres: autovacuum launcher
postgres 1678 1258 0 Jul06 ? 00:00:11 postgres: stats collector
postgres 1679 1258 0 Jul06 ? 00:00:00 postgres: logical replication launcher
postgres 23483 1258 0 08:09 ? 00:00:00 postgres: postgres hrdb 192.168.56.1(63614) idle
postgres 23484 1258 0 08:09 ? 00:00:00 postgres: postgres hrdb 192.168.56.1(63615) idle
postgres 23486 1258 0 08:09 ? 00:00:00 postgres: postgres pagila 192.168.56.1(63616) idle
postgres 23487 1258 0 08:09 ? 00:00:00 postgres: postgres pagila 192.168.56.1(63617) idle
postgres 23488 1258 0 08:09 ? 00:00:00 postgres: postgres pagila 192.168.56.1(63618) idle
其中,1258 是 postmaster 主进程;其他进程都是它的子进程。这种方式显示的进程信息相对简单一些。
利用 pg_cancel_backend() 终止正在运行的语句
函数 pg_cancel_backend(pid) 可以用于取消进程正在执行的查询,其中 pid 就是进程 id,可以通过上面的 pg_stat_activity 视图进行查看。
我们新建一个数据库连接,并且执行以下语句:
-- 新建数据库连接
postgres=> select pg_sleep(60);
pg_sleep 函数可以将当前会话的进程暂停指定时间,这里是 60 秒。
然后在另一个会话中终止该进程正在执行的查询:
-- 另一个连接会话
postgres=> select pid,
query
from pg_catalog.pg_stat_activity
where wait_event = 'PgSleep';
pid |query |
-----|--------------------|
28582|select pg_sleep(60);|
postgres=> select pg_cancel_backend(28582);
pg_cancel_backend|
-----------------|
true |
函数 pg_cancel_backend() 执行成功后返回 true,此时第一个连接会话将会返回以下错误:
ERROR: canceling statement due to user request
虽然当前查询被终止,但是连接会话仍然存在,可以继续执行其他查询。
通过操作系统命令终止正在运行的语句
pg_cancel_backend() 函数实际上是给进程发送了一个 SIGINT 信号。因此,对于 Linux 操作系统,我们也可以使用kill命令终止终止正在运行的语句:
kill -2 pid
其中,-2 代表了 SIGINT 信号;pid 是进程 id。
利用 pg_terminate_backend() 终止连接会话
有时候 pg_cancel_backend() 需要等待很长时间才能终止正在执行的查询,为此我们也可以使用 pg_terminate_backend(pid) 函数强制终止整个连接进程。
例如,我们可以使用以下语句终止连接进程(28582):
-- 另一个连接会话