LWLock:lock_manager (LWLock:lockmanager)
当 RDS for PostgreSQL 引擎维护共享锁的内存区域以便在无法使用快速路径锁时分配、检查和取消分配锁时,会发生此事件。
支持的引擎版本
此等待事件信息与 RDS for PostgreSQL 版本 9.6 及更高版本相关。对于早于版本 13 的 RDS for PostgreSQL 发行版,此等待事件的名称为 LWLock:lock_manager
。对于 RDS for PostgreSQL 版本 13 及更高版本,此等待事件的名称为 LWLock:lockmanager
。
上下文
发布 SQL 语句时,RDS for PostgreSQL 会记录锁,以在并发操作期间保护数据库的结构、数据和完整性。引擎可以使用快速路径锁或不快的路径锁来实现这个目标。不快的路径锁定更昂贵,并且比快速路径锁定造成的开销更大。
快速路径锁定
为了减少频繁获取和释放但很少发生冲突的锁的开销,后端进程可以使用快速路径锁定。数据库对满足以下条件的锁定使用此机制:
-
他们使用 DEFAULT 锁定方法。
-
它们代表数据库关系的锁,而不是共享关系。
-
它们是不太可能发生冲突的弱锁。
-
引擎可以快速确认不可能存在发生冲突的锁。
在以下任一条件为真时,引擎无法使用快速路径锁定:
-
锁不满足上述标准。
-
没有更多的插槽可用于后端进程。
要优化查询以实现快速路径锁,可以使用以下查询。
SELECT count(*), pid, mode, fastpath FROM pg_locks WHERE fastpath IS NOT NULL GROUP BY 4,3,2 ORDER BY pid, mode;
count | pid | mode | fastpath -------+------+-----------------+---------- 16 | 9185 | AccessShareLock | t 336 | 9185 | AccessShareLock | f 1 | 9185 | ExclusiveLock | t
以下查询仅显示数据库中的总数。
SELECT count(*), mode, fastpath FROM pg_locks WHERE fastpath IS NOT NULL GROUP BY 3,2 ORDER BY mode,1;
count | mode | fastpath -------+-----------------+---------- 16 | AccessShareLock | t 337 | AccessShareLock | f 1 | ExclusiveLock | t (3 rows)
有关快速路径锁定的更多信息,请参阅 PostgreSQL 锁管理器 README 中的快速路径
锁管理器的扩缩问题示例
在此示例中,名为 purchases
的表存储五年的数据,按天进行分区。每个分区有两个索引。将发生以下一系列事件:
-
您查询了许多天的数据,这需要数据库读取许多分区。
-
数据库为每个分区创建一个锁条目。如果分区索引是优化程序访问路径的一部分,则数据库也会为它们创建一个锁条目。
-
当同一后端进程请求的锁条目数大于 16 时(这是
FP_LOCK_SLOTS_PER_BACKEND
的值),锁管理器会使用非快速路径锁定方法。
现代应用程序可能有数百个会话。如果并发会话在没有适当的分区修剪的情况下查询父级数据库,则数据库可能会创建数百甚至数千个非快速路径锁。通常,当此并发性高于 vCPU 的数量时,会出现 LWLock:lock_manager
等待事件。
注意
LWLock:lock_manager
等待事件与数据库架构中的分区或索引数量无关。相反,它与数据库必须控制的非快速路径锁的数量有关。
等待次数增加的可能原因
当 LWLock:lock_manager
等待事件发生率超出正常(可能表明性能问题)时,突增的最可能原因如下:
-
并发活动会话正在运行不使用快速路径锁的查询。这些会话还超出了最大 vCPU。
-
大量并发活动会话正在访问严重分区的表。每个分区都有多个索引。
-
数据库正在经历连接风暴。预设情况下,当数据库缓慢时,某些应用程序和连接池软件会创建更多连接。这种做法使问题变得更糟。优化连接池软件,以免发生连接风暴。
-
大量会话在不修剪分区的情况下查询父级表。
-
数据定义语言 (DDL)、数据操作语言 (DML) 或维护命令专门锁定经常访问或修改的繁忙关系或元组。
操作
如果 CPU
等待事件发生,它不一定表示性能问题。仅当性能下降并且此等待事件主导了数据库负载时才响应此事件。
使用分区修剪
分区修剪是一种适用于声明性分区表的查询优化策略,它从表扫描中排除不需要的分区,从而提高性能。预设情况下,分区修剪处于开启状态。如果它已关闭,请按如下方式将其打开。
SET enable_partition_pruning = on;
查询可以在其 WHERE
子句包含用于分区的列时利用分区修建。有关更多信息,请参阅 PostgreSQL 文档中的分区修建
删除不必要的索引
数据库可能包含未使用或很少使用的索引。如果是,请考虑删除它们。请执行以下任一操作:
-
通过阅读 PostgreSQL wiki 中的未使用索引
了解如何查找不必要的索引。 -
运行 PG 收集器。此 SQL 脚本会收集数据库信息并将其显示在整合的 HTML 报告中。检查“未使用的索引”部分。有关更多信息,请参阅 AWS Labs GitHub 存储库中的 pg-collector
。
优化查询以实现快速路径锁定
要了解您的查询是否使用快速路径锁定,请查询 pg_locks
表中的 fastpath
列。如果您的查询没有使用快速路径锁定,请尝试将每个查询的关系数减少到 16 个以下。
优化其他等待事件
如果 LWLock:lock_manager
排在主要等待列表中的第一个或第二个,请检查列表中是否也显示了以下等待事件:
-
Lock:Relation
-
Lock:transactionid
-
Lock:tuple
如果前面的事件显示在列表的前面,请考虑首先优化这些等待事件。这些事件可以是 LWLock:lock_manager
的驱动因素。
减少硬件瓶颈
您可能存在硬件瓶颈,例如 CPU 匮乏或 Amazon EBS 带宽的最大使用率。在这样的情况下,需考虑减少硬件瓶颈。请考虑以下操作:
-
纵向扩展您的实例类。
-
优化占用大量 CPU 和内存的查询。
-
更改应用程序逻辑。
-
将您的数据存档。
有关 CPU、内存和 EBS 网络带宽的更多信息,请参阅 Amazon RDS 实例类型
使用连接池程序。
如果您的活动连接总数超过最大 vCPU,则需要 CPU 的操作系统进程超过实例类型所能支持的数量。在这种情况下,需考虑使用或优化连接池。有关您的实例类型 vCPU 数量的更多信息,请参阅 Amazon RDS 实例类型
有关为连接池的更多信息,请参阅以下资源:
-
PostgreSQL 文档中的连接池和数据源
升级您的 RDS for PostgreSQL 版本
如果您当前的 RDS for PostgreSQL 版本低于 12,请升级到版本 12 或更高版本。PostgreSQL 版本 12 及更高版本具有改进的分区机制。有关版本 12 的更多信息,请参阅 PostgreSQL 12.0 发布说明