Lock - tuple
在后端进程等待获取元组锁定时,会发生 tuple
事件。
事件 tuple
表示一个后端正在等待获取元组上的锁定,而另一个后端在同一个元组上保持冲突锁定。下表说明了会话生成 tuple
事件的场景。
Time | 会话 1 | 会话 2 | 会话 3 |
---|---|---|---|
t1 | 开始事务。 | ||
t2 | 更新第 1 行。 | ||
t3 | 更新第 1 行。会话获取元组上的独占锁定,然后等待会话 1 通过提交或回滚来释放锁。 | ||
t4 | 更新第 1 行。会话等待会话 2 才能释放元组上的独占锁定。 |
或者您可以使用基准测试工具 pgbench
来模拟此等待事件。配置大量并发会话以使用自定义 SQL 文件更新表中的同一行。
要了解冲突锁模式的更多信息,请参阅 PostgreSQL 文档中的显式锁定。要了解有关 pgbench
的更多信息,请参阅 PostgreSQL 文档中的 pgbench。
当此事件的发生率超过正常(可能表示性能问题)时,典型原因包括以下几点:
- 大量并发会话试图通过运行
UPDATE
或DELETE
语句获取相同元组的冲突锁定。 - 高度并发的会话正在使用
FOR UPDATE
或FOR NO KEY UPDATE
锁定模式运行SELECT
语句。 - 各种因素促使应用程序或连接池打开更多会话以执行相同的操作。由于新会话正在尝试修改相同的行,数据库负载可能会激增,
tuple
可以出现。
有关更多信息,请参阅 PostgreSQL 文档中的行级锁定。
根据等待事件的原因,我们建议采取不同的操作。
了解阻止器会话是否已经处于 idle in transaction
状态很长一段时间。如果是这样,请考虑结束阻止器会话,作为短期解决方案。您可以使用 pg_terminate_backend
函数。有关此函数的更多信息,请参阅 PostgreSQL 文档中的服务器信号函数。
要获得长期解决方案,请执行以下操作:
- 调整应用程序逻辑。
- 使用
idle_in_transaction_session_timeout
参数。此参数可结束空闲时间超过指定时间的已打开事务的任何会话。有关更多信息,请参阅 PostgreSQL 文档中的客户端连接原定设置。 - 尽可能多地使用自动提交。有关更多信息,请参阅 PostgreSQL 文档中的 SET AUTOCOMMIT。
tuple
事件可能会不断发生,特别是在繁忙的工作负载时间。在这种情况下,考虑降低非常繁忙的行的高并发率。通常,只有几个行控制队列或布尔逻辑,这使得这些行非常繁忙。
您可以根据业务需求、应用程序逻辑和工作负载类型使用不同的方法来降低并发性。例如,您可以执行以下操作:
- 重新设计表和数据逻辑以降低高并发性。
- 更改应用程序逻辑以降低行级别的高并发性。
- 使用行级锁定利用和重新设计查询。
- 使用具有重试操作的
NOWAIT
子句。 - 考虑使用乐观和混合锁定逻辑并发控制。
- 考虑更改数据库隔离级别。