

# LWLock:MultiXact
<a name="apg-waits.lwlockmultixact"></a>

`LWLock:MultiXactMemberBuffer`、`LWLock:MultiXactOffsetBuffer`、`LWLock:MultiXactMemberSLRU` 和 `LWLock:MultiXactOffsetSLRU` 等待事件表示会话正在等待检索修改给定表中同一行的事务列表。
+ `LWLock:MultiXactMemberBuffer` – 进程正在等待 multixact 成员的最近使用最少的（SLRU）简单缓冲区上的输入/输出。
+ `LWLock:MultiXactMemberSLRU` – 进程正在等待访问 multixact 成员的最近使用最少的（SLRU）简单缓存。
+ `LWLock:MultiXactOffsetBuffer` – 进程正在等待 multixact offset 的最近使用最少的（SLRU）简单缓冲区上的输入/输出。
+ `LWLock:MultiXactOffsetSLRU` – 进程正在等待访问 multixact offset 的最近使用最少的（SLRU）简单缓存。

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

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

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

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

*multixact* 是一种数据结构，用于存储修改同一表行的事务 ID（XID）列表。当单个事务引用表中的一行时，事务 ID 存储在表标题行中。当多个事务引用表中的同一行时，事务 ID 列表存储在 multixact 数据结构中。Multixact 等待事件表示会话正在从数据结构中检索引用表中给定行的事务列表。

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

使用 multixact 的三个常见原因如下所示：
+ **来自显式保存点的子事务**：在事务中显式创建保存点会为同一行生成新事务。例如，使用 `SELECT FOR UPDATE`，接着使用 `SAVEPOINT`，然后使用 `UPDATE`。

  某些驱动程序、对象关联映射器（ORM）和抽象层具有配置选项，可以使用保存点自动包装所有操作。这会在某些工作负载中生成许多 multixact 等待事件。PostgreSQL JDBC 驱动程序的 `autosave` 选项就是这样一个例子。有关更多信息，请参阅 PostgreSQL JDBC 文档中的 [pgJDBC](https://jdbc.postgresql.org/)。另一个例子是 PostgreSQL ODBC 驱动程序及其 `protocol` 选项。有关更多信息，请参阅 PostgreSQL ODBC 驱动程序文档中的 [psqlODBC 配置选项](https://odbc.postgresql.org/docs/config.html)。
+ **来自 PL/pgSQL EXCEPTION 子句的子事务**：您在 PL/pgSQL 函数或过程中编写的每个 `EXCEPTION` 子句都会在内部创建一个 `SAVEPOINT`。
+ **外键**：多个事务在父行上获取共享锁定。

当给定行包含在多事务操作中时，处理该行要求从 `multixact` 列表中检索事务 ID。如果查找无法从内存缓存中获取 multixact，则必须从 Aurora 存储层读取数据结构。存储中的这一输入/输出意味着 SQL 查询可能需要更长的时间。由于大量的多事务，可能会在使用量很大时开始发生内存缓存未命中。所有这些因素都导致这种等待事件的增加。

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

根据等待事件的原因，我们建议采取不同的操作。其中一些操作有助于立即减少等待事件。但是，其它一些操作可能需要进行调查和更正以扩展您的工作负载。

**Topics**
+ [使用此等待事件对表执行 vacuum 冻结](#apg-waits.lwlockmultixact.actions.vacuumfreeze)
+ [增加具有此等待事件的表上的 autovacuum 频率](#apg-waits.lwlockmultixact.actions.autovacuum)
+ [增加内存参数](#apg-waits.lwlockmultixact.actions.memoryparam)
+ [减少长时间运行的事务](#apg-waits.lwlockmultixact.actions.longtransactions)
+ [长期操作](#apg-waits.lwlockmultixact.actions.longactions)

### 使用此等待事件对表执行 vacuum 冻结
<a name="apg-waits.lwlockmultixact.actions.vacuumfreeze"></a>

如果此等待事件突然激增并影响您的生产环境，则可以使用以下任何临时方法减少其数量。
+ 在受影响的表或表分区上使用 *VACUUM FREEZE* 以立即解决问题。有关更多信息，请参阅 [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)。
+ 使用 VACUUM (FREEZE, INDEX\$1CLEANUP FALSE) 子句通过跳过索引来执行快速 vacuum 操作。有关更多信息，请参阅[尽快对表执行 vacuum 操作](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.Executing)。

### 增加具有此等待事件的表上的 autovacuum 频率
<a name="apg-waits.lwlockmultixact.actions.autovacuum"></a>

在扫描所有数据库中的所有表后，VACUUM 最终将删除 multixact，并前移其最旧的 multixact 值。有关更多信息，请参阅 [Multixacts and Wraparound](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-MULTIXACT-WRAPAROUND)。要将 LWLock:MultiXact 等待事件数降至其最低值，必须根据需要尽可能多运行 VACUUM。为此，请确保对 Aurora PostgreSQL 数据库集群中的 VACUUM 进行了最佳配置。

如果在受影响的表或表分区上使用 VACUUM FREEZE 可以解决等待事件问题，我们建议使用调度器（例如 `pg_cron`）来执行 VACUUM，而不是在实例级别调整 autovacuum 操作。

为了使 autovacuum 更频繁地发生，您可以减少受影响表中的存储参数 `autovacuum_multixact_freeze_max_age` 的值。有关更多信息，请参阅 [autovacuum\$1multixact\$1freeze\$1max\$1age](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MULTIXACT-FREEZE-MAX-AGE)。

### 增加内存参数
<a name="apg-waits.lwlockmultixact.actions.memoryparam"></a>

可以通过调整以下参数来优化 multixact 缓存的内存使用情况。这些设置控制为这些缓存预留多少内存，这有助于减少工作负载中的 multixact 等待事件。建议从以下值开始：

对于 Aurora PostgreSQL 17 和更高版本：  
+ `multixact_offset_buffers` = 128
+ `multixact_member_buffers` = 256

对于 Aurora PostgreSQL 16 及更早版本：  
+ `multixact_offsets_cache_size` = 128
+ `multixact_members_cache_size` = 256

**注意**  
在 Aurora PostgreSQL 17 中，为了与社区 PostgreSQL 17 保持一致，参数名称已从 `multixact_offsets_cache_size` 更改为 `multixact_offset_buffers` 和从 `multixact_members_cache_size` 更改为 `multixact_member_buffers`。

可以在集群级别设置这些参数，以使集群中的所有实例保持一致。建议您测试和调整这些值，使其最适合您的特定工作负载要求和实例类。必须重启写入器实例才能使参数更改生效。

这些参数以 multixact 缓存条目表示。每个缓存条目使用 `8 KB` 内存。要计算预留的总内存，请将每个参数值乘以 `8 KB`。例如，如果将参数设置为 128，则预留内存总量为 `128 * 8 KB = 1 MB`。

### 减少长时间运行的事务
<a name="apg-waits.lwlockmultixact.actions.longtransactions"></a>

长时间运行的事务会导致 vacuum 在事务提交或只读事务关闭之前保留其信息。建议您主动监视和管理长时间运行的事务。有关更多信息，请参阅 [数据库具有长时间运行的事务空闲连接](PostgreSQL.Tuning_proactive_insights.md#proactive-insights.idle-txn)。尝试修改您的应用程序，以避免或尽量减少使用长时间运行的事务。

### 长期操作
<a name="apg-waits.lwlockmultixact.actions.longactions"></a>

检查您的工作负载，以找出 multixact 溢出的原因。为了扩展工作负载并减少等待事件，您必须修复该问题。
+ 您必须分析用于创建表的 DDL（数据定义语言）。确保表结构和索引设计良好。
+ 当受影响的表有外键时，请确定是否需要外键，或者是否有其它方法可以强制执行引用完整性。
+ 当表有大量未使用的索引时，可能会导致 autovacuum 不适合您的工作负载，并可能阻止其运行。为避免这种情况，请检查是否有未使用的索引并将其完全删除。有关更多信息，请参阅[使用大型索引管理 autovacuum](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.html)。
+ 减少在事务中使用保存点。