Lock:Relation - Amazon Aurora
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

Lock:Relation

当查询等待获取当前被另一个事务锁定的表或视图(关系)上的锁定时,会发生 Lock:Relation 事件。

支持的引擎版本

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

Context

大多数 PostgreSQL 命令隐式使用锁来控制对表中数据的并发访问。您还可以通过 LOCK 命令在应用程序代码中显式使用这些锁。许多锁定模式彼此不兼容,它们可以在尝试访问同一对象时阻止事务。发生这种情况时,Aurora PostgreSQL 会生成一个 Lock:Relation 事件。以下是一些常见的示例:

  • ACCESS EXCLUSIVE 之类的独占锁可以阻止所有并发访问。数据定义语言 (DDL) 操作(例如 DROP TABLETRUNCATEVACUUM FULLCLUSTER)隐式获取 ACCESS EXCLUSIVE 锁定。ACCESS EXCLUSIVE 也是用于未显式指定模式的 LOCK TABLE 语句的原定设置锁定模式。

  • 在表上使用 CREATE INDEX (without CONCURRENT) 与数据操作语言 (DML) 语句 UPDATEDELETEINSERT 有冲突,这些语句可获取 ROW EXCLUSIVE 锁定。

有关表级锁和冲突锁模式的更多信息,请参阅 PostgreSQL 文档中的显式锁定

阻止查询和事务通常通过以下方式之一解锁阻止:

  • 阻止查询 – 应用程序可以取消查询或者用户可以结束该过程。引擎还可以因会话的语句超时或死锁检测机制而强制结束查询。

  • 阻止事务 – 事务在运行 ROLLBACKCOMMIT 语句时停止阻止。当会话被客户端或网络问题断开连接或结束时,也会自动发生回滚。当数据库引擎关闭、系统内存不足等时,可以结束会话。

等待次数增加的可能原因

Lock:Relation 事件的发生率超过正常(可能表示性能问题)时,典型原因包括以下几点:

增加与表锁冲突的并发会话

用冲突锁定模式锁定相同表格的查询的并发会话数可能会增加。

维护操作

VACUUMANALYZE 之类的运行状况维护操作可以显著增加冲突锁的数量。VACUUM FULL 获取 ACCESS EXCLUSIVE 锁,ANALYSE 获取 SHARE UPDATE EXCLUSIVE锁。这两种类型的锁都可能导致 Lock:Relation 等待事件。应用程序数据维护操作(例如刷新具体化视图)也可以增加阻止的查询和事务。

读取器实例的锁定

在读取器实例上获得的锁定可能会增加。从锁定的角度来看,Aurora PostgreSQL 将写入器和读取器实例视为单个单元。因此,在读取器实例上获取的锁定可以阻止对写入器进行查询。同样,对写入器的锁定可以阻止读取器查询。

Actions

根据等待事件的原因,我们建议采取不同的操作。

减少阻止 SQL 语句的影响

为了减少阻止 SQL 语句的影响,请尽可能修改应用程序代码。以下是减少数据块的两种常见方法:

  • 使用 NOWAIT 选项 – 一些 SQL 命令,例如 SELECTLOCK 语句,支持此选项。如果无法立即获取锁定,则 NOWAIT 指令将取消请求锁定的查询。这种方法可以帮助防止阻止会话导致其后面堆积阻止的会话。

    例如:假设事务 A 正在等待事务 B 所持有的锁定。现在,如果 B 请求对被事务 C 锁定的表进行锁,那么事务 A 可能会被阻止,直到事务 C 完成。但是,如果事务 B 在请求对 C 进行锁定时使用 NOWAIT,它可能会很快失败,并确保事务 A 不必无限期等待。

  • 使用 SET lock_timeout – 设置 lock_timeout 值,以限制 SQL 语句等待获取关系锁的时间。如果锁未在指定的超时内获取,则请求锁定的事务将被取消。在会话级别设置此值。

尽量减少维护操作的影响

维护操作(例如 VACUUMANALYZE)非常重要。我们建议您不要将其关闭,因为您会找到与这些维护操作相关的 Lock:Relation 等待事件。以下方法可以最大限度地减少这些操作的影响:

  • 在非高峰时段手动运行维护操作。

  • 要减少由 autovacuum 任务导致的 Lock:Relation 等待,执行任何需要的 autovacuum 优化。有关优化 autovacuum 的信息,请参阅《Amazon RDS 用户指南》中的在 Amazon RDS 上使用 PostgreSQL autovacuum

检查读取器锁

您可以看到写入器和读取器的并发会话如何持有互相阻止的锁。执行这一操作的一种方式是运行返回锁定类型和关系的查询,如以下示例所示。

写入器会话 读取器会话 描述
export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com psql -h $WRITER psql (15devel, server 10.14) Type "help" for help.
export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com psql -h $READER psql (15devel, server 10.14) Type "help" for help.

此示例显示了两个并发会话。第一列显示写入器会话。第二列显示读取器会话。

postgres=> CREATE TABLE t1(b integer); CREATE TABLE

写入器会话在写入器实例上创建表 t1

postgres=> SET lock_timeout=100; SET

读取器会话将锁定超时间隔设置为 100 毫秒。

postgres=> SELECT * FROM t1; b --- (0 rows)

读取器会话尝试从读取器实例上的表 t1 中读取数据。

postgres=> BEGIN; BEGIN postgres=*> DROP TABLE t1; DROP TABLE postgres=*>

写入器会话会删除 t1

postgres=> SELECT * FROM t1; ERROR: canceling statement due to lock timeout LINE 1: SELECT * FROM t1; ^

查询超时并在读取器上被取消。

postgres=> SELECT locktype, relation, mode, backend_type postgres-> FROM pg_locks l, pg_stat_activity t1 postgres-> WHERE l.pid=t1.pid AND relation = 't1'::regclass::oid; locktype | relation | mode | backend_type ----------+----------+---------------------+------------------- relation | 68628525 | AccessExclusiveLock | aurora wal replay (1 row)

读取器会话查询 pg_lockspg_stat_activity 以确定错误的原因。结果表明,aurora wal replay进程对表 t1 持有 ACCESS EXCLUSIVE 锁。