

# LWLock:pg\$1stat\$1statements


当 `pg_stat_statements` 扩展对跟踪 SQL 语句的哈希表进行独占锁定时，就会发生 LWLock:pg\$1stat\$1statements 等待事件。如果存在以下情形，可能会发生这种情况：
+ 当跟踪的语句数量达到配置的 `pg_stat_statements.max` 参数值，并且需要为更多条目腾出空间时，此扩展会对调用次数执行排序，移除 5% 的执行次数最少的语句，然后用剩余的条目重新填充哈希表。
+ 当 `pg_stat_statements` 对磁盘上的 `pgss_query_texts.stat` 文件执行 `garbage collection` 操作并重新写入该文件时。

**Topics**
+ [

## 支持的引擎版本
](#apg-rpg-lwlockpgstat.supported)
+ [

## 上下文
](#apg-rpg-lwlockpgstat.context)
+ [

## 等待次数增加的可能原因
](#apg-rpg-lwlockpgstat.causes)
+ [

## 操作
](#apg-rpg-lwlockpgstat.actions)

## 支持的引擎版本


 RDS for PostgreSQL 的所有版本均支持此等待事件信息。

## 上下文


**了解 pg\$1stat\$1statements 扩展**：pg\$1stat\$1statements 扩展在哈希表中跟踪 SQL 语句执行统计数据。该扩展可跟踪 SQL 语句，直至达到由 `pg_stat_statements.max` 参数定义的限制。此参数确定可以跟踪的最大语句数，该数量对应于 pg\$1stat\$1statements 视图中的最大行数。

**语句统计数据持久性**：该扩展通过以下方式，在实例重新启动时持久保留语句统计数据：
+ 将数据写入名为 pg\$1stat\$1statements.stat 的文件
+ 使用 pg\$1stat\$1statements.save 参数来控制持久行为

当 pg\$1stat\$1statements.save 设为以下设置时：
+ 开启（默认）：关闭时保存统计数据，并在服务器启动时重新加载它们
+ 关闭：既不会在服务器关闭时保存统计数据，也不会在服务器启动时重新加载它们

**查询文本存储**：该扩展将所跟踪的查询的文本存储在一个名为 `pgss_query_texts.stat` 的文件中。在进行垃圾回收之前，该文件可以增长到所有跟踪的 SQL 语句平均大小的两倍。该扩展需要在清理操作和重新写入 `pgss_query_texts.stat` 文件期间对哈希表实施独占锁定。

**语句取消分配流程**：当所跟踪语句的数量达到 `pg_stat_statements.max` 限制并且需要跟踪新的语句时，此扩展会：
+ 对哈希表实施独占锁定（LWLock:pg\$1stat\$1statements）。
+ 将现有数据加载到本地内存中。
+ 根据调用次数执行快速排序。
+ 移除调用次数最少的语句（底部 5%）。
+ 用剩余的条目重新填充哈希表。

**监控语句取消分配**：在 PostgreSQL 14 及更高版本中，可以使用 pg\$1stat\$1statements\$1info 视图来监控语句取消分配。此视图包括一个 dealloc 列，该列显示对语句取消分配来为新语句腾出空间的次数

如果频繁地对语句取消分配，则会导致更频繁地对磁盘上的 `pgss_query_texts.stat` 文件进行垃圾回收。

## 等待次数增加的可能原因


`LWLock:pg_stat_statements` 等待次数增加的典型原因包括：
+ 应用程序使用的唯一查询的数量有所增加。
+ 与正在使用的唯一查询的数量相比，`pg_stat_statements.max` 参数值较小。

## 操作


根据等待事件的原因，我们建议采取不同的操作。可以通过使用 Amazon RDS 性能详情或查询视图 `pg_stat_activity` 来识别 `LWLock:pg_stat_statements` 事件。

调整以下 `pg_stat_statements` 参数，以控制跟踪行为并减少 LWLock:pg\$1stat\$1 statements 等待事件。

**Topics**
+ [

### 禁用 pg\$1stat\$1statements.track 参数
](#apg-rpg-lwlockpgstat.actions.disabletrack)
+ [

### 提高 pg\$1stat\$1statements.max 参数的值
](#apg-rpg-lwlockpgstat.actions.increasemax)
+ [

### 禁用 pg\$1stat\$1statements.track\$1utility 参数
](#apg-rpg-lwlockpgstat.actions.disableutility)

### 禁用 pg\$1stat\$1statements.track 参数


如果 LWLock:pg\$1stat\$1statements 等待事件对数据库性能产生不利影响，并且在进一步分析 `pg_stat_statements` 视图以确定根本原因之前需要快速的解决方案，则可以通过将 `pg_stat_statements.track` 参数设置为 `none` 来禁用该参数。这将禁用对语句统计数据的回收。

### 提高 pg\$1stat\$1statements.max 参数的值


要减少取消分配并最大限度地减少磁盘上 `pgss_query_texts.stat` 文件的垃圾回收，请提高 `pg_stat_statements.max` 参数的值。默认值为 `5,000`。

**注意**  
`pg_stat_statements.max` 参数为静态参数。必须重新启动数据库实例，才能应用对此参数的任何更改。

### 禁用 pg\$1stat\$1statements.track\$1utility 参数


您可以分析 pg\$1stat\$1statements 视图，以确定哪些实用程序命令正在消耗由 `pg_stat_statements` 跟踪的大部分资源。

`pg_stat_statements.track_utility` 参数控制模块是否跟踪实用程序命令，包括除 SELECT、INSERT、UPDATE、DELETE 和 MERGE 之外的所有命令。默认情况下，此参数设置为 `on`。

例如，当应用程序使用许多本质上为唯一的保存点查询时，它可能会增加语句取消分配。要解决此问题，您可以禁用 `pg_stat_statements.track_utility` 参数以停止 `pg_stat_statements` 跟踪保存点查询。

**注意**  
`pg_stat_statements.track_utility` 参数是一个动态参数。无需重新启动数据库实例即可更改其值。

**Example pg\$1stat\$1statements 中的唯一保存点查询示例**  <a name="savepoint-queries"></a>

```
                     query                       |       queryid       
-------------------------------------------------+---------------------
 SAVEPOINT JDBC_SAVEPOINT_495701                 | -7249565344517699703
 SAVEPOINT JDBC_SAVEPOINT_1320                   | -1572997038849006629
 SAVEPOINT JDBC_SAVEPOINT_26739                  |  54791337410474486
 SAVEPOINT JDBC_SAVEPOINT_1294466                |  8170064357463507593
 ROLLBACK TO SAVEPOINT JDBC_SAVEPOINT_65016      | -33608214779996400
 SAVEPOINT JDBC_SAVEPOINT_14185                  | -2175035613806809562
 SAVEPOINT JDBC_SAVEPOINT_45837                  | -6201592986750645383
 SAVEPOINT JDBC_SAVEPOINT_1324                   |  6388797791882029332
```

PostgreSQL 17 引入了多项增强功能来进行实用程序命令跟踪：
+ 保存点名称现在显示为常量。
+ 现在，两阶段提交命令的全局事务 ID（GID）显示为常量。
+ DEALLOCATE 语句的名称显示为常量。
+ CALL 参数现在显示为常量。