

# LWLock:buffer\$1content (BufferContent)
<a name="apg-waits.lockbuffercontent"></a>

当某个会话等待读取或写入内存中的某个数据页面，而另一个会话正锁定该页面以进行写入时，会发生 `LWLock:buffer_content` 事件。在 Aurora PostgreSQL 13 及更高版本中，此等待事件被称为 `BufferContent`。

**Topics**
+ [支持的引擎版本](#apg-waits.lockbuffercontent.context.supported)
+ [上下文](#apg-waits.lockbuffercontent.context)
+ [等待次数增加的可能原因](#apg-waits.lockbuffercontent.causes)
+ [操作](#apg-waits.lockbuffercontent.actions)

## 支持的引擎版本
<a name="apg-waits.lockbuffercontent.context.supported"></a>

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

## 上下文
<a name="apg-waits.lockbuffercontent.context"></a>

要读取或操作数据，PostgreSQL 会通过共享内存缓冲区访问数据。要从缓冲区读取，进程会在共享模式下获取缓冲区内容的轻量级锁 (LWLock)。要写入缓冲区，它会在独占模式下获得该锁。共享锁允许其他进程同时获取对该内容的共享锁。独占锁可防止其他进程获取对该内容的任何类型的锁定。

`LWLock:buffer_content` (`BufferContent`) 事件表示多个进程正试图获取对特定缓冲区的内容的轻量级锁定（LWLock）。

## 等待次数增加的可能原因
<a name="apg-waits.lockbuffercontent.causes"></a>

当 `LWLock:buffer_content` (`BufferContent`) 事件的发生率超过正常（可能表示性能问题）时，典型原因包括以下几点：

**增加了对同一数据的并发更新**  
更新相同缓冲区内容的查询的并发会话数可能会增加。在具有大量索引的表中，这种争用可能更加明显。

**工作负载数据不在内存中**  
当活动工作负载正在处理的数据不在内存中时，这些等待事件可能会增加。这种影响是因为持有锁的进程可以在执行磁盘输入/输出操作时保持更长时间。

**过度使用外键约束**  
外键约束可能会增加进程在缓冲区内容锁上保留的时间。这种影响是因为读取操作需要在更新引用的键时对该键进行共享缓冲区内容锁定。

## 操作
<a name="apg-waits.lockbuffercontent.actions"></a>

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

**Topics**
+ [提高内存中的效率](#apg-waits.lockbuffercontent.actions.in-memory)
+ [减少对外键约束的使用](#apg-waits.lockbuffercontent.actions.foreignkey)
+ [删除未使用的索引](#apg-waits.lockbuffercontent.actions.indexes)
+ [移除重复的索引](#apg-waits.lockbuffercontent.actions.duplicate-indexes)
+ [删除或重新索引无效的索引](#apg-waits.lockbuffercontent.actions.invalid-indexes)
+ [使用部分索引](#apg-waits.lockbuffercontent.actions.partial-indexes)
+ [移除表和索引膨胀](#apg-waits.lockbuffercontent.actions.bloat)

### 提高内存中的效率
<a name="apg-waits.lockbuffercontent.actions.in-memory"></a>

为了增加活动工作负载数据在内存中的可能性，请对表进行分区或纵向扩展您的实例类。有关数据库实例类的信息，请参阅 [Amazon Aurora数据库实例类](Concepts.DBInstanceClass.md)。

监控 `BufferCacheHitRatio` 指标，该指标衡量由数据库集群中数据库实例的缓冲区缓存处理的请求百分比。通过该指标，可以深入了解从内存中处理的数据量。命中率高表示数据库实例有足够的内存可用于工作数据集，而命中率低表示查询经常访问存储空间中的数据。

借助 [PG Collector](https://github.com/awslabs/pg-collector) 报告的“内存设置”部分下每个表的缓存读取命中率和每个索引的缓存读取命中率，可以深入了解表和索引的缓存命中率。

### 减少对外键约束的使用
<a name="apg-waits.lockbuffercontent.actions.foreignkey"></a>

调查在使用外键约束时遇到大量`LWLock:buffer_content` (`BufferContent`) 等待事件的工作负载。删除不必要的外键约束。

### 删除未使用的索引
<a name="apg-waits.lockbuffercontent.actions.indexes"></a>

对于遇到大量 `LWLock:buffer_content`(`BufferContent`) 等待事件的工作负载，识别未使用的索引并删除它们。

借助 [PG Collector](https://github.com/awslabs/pg-collector) 报告的未使用索引部分，可以深入了解数据库中的未使用索引。

### 移除重复的索引
<a name="apg-waits.lockbuffercontent.actions.duplicate-indexes"></a>

识别重复的索引并将其移除。

借助 [PG Collector](https://github.com/awslabs/pg-collector) 报告的重复索引部分，可以深入了解数据库中的重复索引。

### 删除或重新索引无效的索引
<a name="apg-waits.lockbuffercontent.actions.invalid-indexes"></a>

使用 `CREATE INDEX CONCURRENTLY` 或 `REINDEX CONCURRENTLY` 但命令失败或中止时，通常会出现无效索引。

无效索引不能用于查询，但它们仍会被更新并占用磁盘空间。

借助 [PG Collector](https://github.com/awslabs/pg-collector) 报告的“无效索引”部分，可以深入了解数据库中的无效索引。

### 使用部分索引
<a name="apg-waits.lockbuffercontent.actions.partial-indexes"></a>

可以利用部分索引来增强查询性能和减小索引大小。部分索引是对表的子集构建的索引，子集由条件表达式定义。正如 [partial index](https://www.postgresql.org/docs/current/indexes-partial.html) 文档中所详述的那样，部分索引可以减少维护索引的开销，因为 PostgreSQL 并不需要在所有情况下都更新索引。

### 移除表和索引膨胀
<a name="apg-waits.lockbuffercontent.actions.bloat"></a>

过多的表和索引膨胀可能会对数据库性能产生负面影响。膨胀的表和索引会增加活动工作集的大小，从而降低内存效率。此外，膨胀还会增加存储成本并减慢查询执行速度。要诊断膨胀问题，请参阅[诊断表和索引膨胀](AuroraPostgreSQL.diag-table-ind-bloat.md)。此外，借助 [PG Collector](https://github.com/awslabs/pg-collector) 报告的“碎片化（膨胀）”部分，可以深入了解表和索引膨胀。

要解决表和索引膨胀问题，有以下几个选项：

**VACUUM FULL**  
`VACUUM FULL` 创建表的新副本，仅复制活动的元组，然后在持有 `ACCESS EXCLUSIVE` 锁的同时用新表替换旧表。这样可以防止对表进行任何读取或写入（这可能导致中断）。此外，如果表较大，则 `VACUUM FULL` 需要更长的时间。

** pg\$1repack **  
在 `VACUUM FULL` 可能不适用的情况下，`pg_repack` 会很有帮助。它会创建一个包含膨胀表数据的新表，跟踪原始表中的更改，然后用新表替换原始表。在构建新表时，它不会锁定原始表来防止读取或写入操作。有关如何使用 `pg_repack` 的更多信息，请参阅 [Removing bloat with pg\$1repack](https://docs.aws.amazon.com/prescriptive-guidance/latest/postgresql-maintenance-rds-aurora/pg-repack.html) 和 [pg\$1repack](https://reorg.github.io/pg_repack/)。

**REINDEX**  
可以利用 `REINDEX` 命令来解决索引膨胀问题。`REINDEX` 编写一个新版本的索引，没有死页或空页或几乎为空的页，从而减少索引的空间消耗。有关 [https://www.postgresql.org/docs/current/sql-reindex.html](https://www.postgresql.org/docs/current/sql-reindex.html) 命令的详细信息，请参阅 REINDEX 文档。

从表和索引中移除膨胀后，可能需要增加这些表的 autovacuum 频率。在表级别实施积极的 autovacuum 设置有助于防止将来发生膨胀。有关更多信息，请参阅有关 [https://docs.aws.amazon.com/prescriptive-guidance/latest/postgresql-maintenance-rds-aurora/autovacuum.html](https://docs.aws.amazon.com/prescriptive-guidance/latest/postgresql-maintenance-rds-aurora/autovacuum.html) 的文档。