PostgreSQL 教程: 检查阻塞的查询

一月 11, 2024

摘要:在本教程中,您将学习如何在 PostgreSQL 中检查阻塞的查询。

目录

介绍

PostgreSQL 数据库提供了对许多任务关键型应用程序的支持,应用程序总是期望查询性能能保持稳定。如果单个查询花费的时间比预期的要长,可能导致用户不满意,或者后台进程延迟。我们可以用EXPLAIN来调试一个慢查询,但还有另一个问题会减慢查询速度:阻塞查询。在其他类型的数据库系统中,您可能还会将其称为“阻塞会话”。这是当一个查询在表上持有锁,而另一个查询正在等待这些锁被释放时,发生的情况。

可用于检查阻塞查询的关键的表和函数包括:

  • pg_stat_activity:一个系统视图,其中每个服务器进程对应一条记录,显示每个进程正在运行的查询的详细信息。
  • pg_locks:有关打开的事务在数据库中持有的当前锁的信息,每个锁定对象对应一行。
  • pg_blocking_pids():一个系统函数,用于查找阻塞指定 PID 的服务器进程的会话的进程 ID。

查找阻塞的进程和阻塞查询

通过 pg_stat_activity 视图,您可以查看所有正在运行的查询,以及它们在 PostgreSQL 数据库上花费的时间。

pg_blocking_pids() 是一个很有用的系统函数,可用于查找阻塞另一个会话的数据库连接/会话。pg_blocking_pids() 函数会返回一个进程 PID 的 PostgreSQL 数组,这些进程阻塞了您传递给函数的指定 PID 的服务器进程。通常,如果服务器进程 A 持有另一个进程 B 所需的锁,则进程 A 会阻塞那个进程 B。

要查找数据库上被阻塞的进程,以及阻塞它们的实际查询,可以使用下面这个有用的 SQL 语句:

SELECT
    activity.pid,
    activity.usename,
    activity.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query
FROM pg_stat_activity AS activity
JOIN pg_stat_activity AS blocking
  ON blocking.pid = ANY(pg_blocking_pids(activity.pid));
ORDER BY activity.query_start;

查看关联到表和查询的锁信息

查看 pg_locks 会显示授予了哪些锁,以及哪些进程正在等待获取锁。如果对 pg_stat_activity 中的信息进行交叉引用,则更容易弄清楚哪些进程正在持有或等待锁。

pg_lock视图连接到pg_stat_activity用于查看 SQL 语句,再连接到pg_class用于查看表名,对于收集数据库中任何时间点锁定的对象的更多上下文信息,会非常有用:

SELECT
    relname AS relation_name,
    query,
    pg_locks.*
FROM pg_locks
JOIN pg_class ON pg_locks.relation = pg_class.oid
JOIN pg_stat_activity ON pg_locks.pid = pg_stat_activity.pid

了解更多

PostgreSQL 监控