Lock:transactionid - Amazon Aurora

Lock:transactionid

当事务正在等待行级锁定时,会发生 Lock:transactionid 事件。

支持的引擎版本

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

上下文

当事务试图获取已被授予同时运行的事务的行级锁时,会发生事件 Lock:transactionid。显示 Lock:transactionid 等待事件的会话因此锁定被阻止。当阻止事务在 COMMITROLLBACK 语句中结束后,被阻止的事务可以继续进行。

Aurora PostgreSQL 的多版本并发控制语义保证读取器不会阻止写入器,写入器也不会阻止读取器。为了发生行级冲突,正在阻止和已阻止的事务必须发出以下类型的冲突语句:

  • UPDATE

  • SELECT … FOR UPDATE

  • SELECT … FOR KEY SHARE

语句 SELECT … FOR KEY SHARE 是一种特殊情况。数据库使用子句 FOR KEY SHARE 以优化参照完整性的性能。一行上的行级锁定可以组织引用该行的其他表上的 INSERTUPDATEDELETE 命令。

等待次数增加的可能原因

当此事件出现频率超过正常时,原因通常是 UPDATESELECT … FOR UPDATESELECT … FOR KEY SHARE 语句结合以下条件。

高并发性

Aurora PostgreSQL 可以使用精细的行级锁定语义。满足以下条件时,行级冲突的可能性会增加:

  • 高度并发的工作负载争用相同的行。

  • 并发性增加。

空闲事务

有时,pg_stat_activity.state 列会显示值 idle in transaction。对于已开始事务但尚未发布 COMMITROLLBACK 的会话,会显示此值。如果 pg_stat_activity.state 值不为 activepg_stat_activity 中显示的查询是完成运行的最新版本。阻止会话没有主动处理查询,因为未完成的事务持有锁定。

如果空闲事务获得了行级锁,则可能会阻止其他会话获取它。这种情况导致等待事件 Lock:transactionid 频繁发生。要诊断问题,请检查来自的 pg_stat_activitypg_locks 的输出。

长时间运行的事务

长时间运行的事务会获得很长一段时间的锁定。这些长期保留的锁定可以阻止其他事务运行。

操作

行锁定是 UPDATESELECT … FOR UPDATESELECT … FOR KEY SHARE 语句之间发生的冲突。在尝试解决方案之前,请先了解这些语句何时在同一行上运行。使用此信息选择以下各部分所述的策略。

响应高并发

如果并发性是问题,请尝试以下方法之一:

  • 降低应用程序中的并发率。例如,减少活动会话的数量。

  • 实施连接池。要了解如何使用 RDS 代理进行池连接,请参阅 将 Amazon RDS 代理用于 Aurora

  • 设计应用程序或数据模型以避免争用 UPDATESELECT … FOR UPDATE 语句。您还可以减少 SELECT … FOR KEY SHARE 语句访问的外键的数量。

回应空闲事务

如果 pg_stat_activity.state 显示 idle in transaction,请使用以下策略:

  • 尽可能开启自动提交。这种方法可防止事务在等待 COMMITROLLBACK 时阻止其他事务。

  • 搜索缺失 COMMITROLLBACKEND 的代码路径。

  • 确保应用程序中的异常处理逻辑始终具有通向有效 end of transaction 的路径。

  • 确保您的应用程序在结束与COMMITROLLBACK 的事务后处理查询结果。

响应长期运行的事务

如果长时间运行的事务导致频繁发生 Lock:transactionid,请尝试以下策略:

  • 在长时间运行的事务中保持行锁定。

  • 尽可能通过实现自动提交来限制查询的长度。