You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL事务中为SELECT FOR UPDATE设置超时时间?

在PostgreSQL中为SELECT FOR UPDATE设置3秒超时的方法

首先,我们有一个product表,结构如下:

idnamestock
1Apple10
2Orange20

默认情况下,SELECT FOR UPDATE没有超时机制,当T1持有行锁时,T2会一直等待直到T1释放锁,流程如下:

流程事务1(T1)事务2(T2)说明
步骤1BEGIN;T1启动。
步骤2BEGIN;T2启动。
步骤3SELECT stock FROM product WHERE id = 2 FOR UPDATE;

返回结果:20
T1通过SELECT FOR UPDATE读取到stock值,并持有该行的排他锁。
步骤4SELECT stock FROM product WHERE id = 2 FOR UPDATE;T2尝试获取行锁,进入等待状态。
步骤5-97等待中...T2持续等待T1释放锁。
步骤98COMMIT;等待中...T1提交事务,释放行锁。
步骤99SELECT stock FROM product WHERE id = 2 FOR UPDATE;

返回结果:20
T2获取到行锁,成功读取数据。
步骤100COMMIT;T2提交事务。

要实现T2等待3秒后自动回滚,可通过以下方法:

设置lock_timeout参数

lock_timeout是PostgreSQL提供的会话级参数,用于控制等待锁的最长时间,超时后会抛出lock timeout错误,此时事务会终止,需执行回滚操作。

修改后的T2执行流程:

流程事务1(T1)事务2(T2)说明
步骤1BEGIN;T1启动。
步骤2BEGIN;T2启动。
步骤3SELECT stock FROM product WHERE id = 2 FOR UPDATE;

返回结果:20
T1获取行锁并读取数据。
步骤4SET lock_timeout = '3s';T2设置锁等待超时为3秒。
步骤5SELECT stock FROM product WHERE id = 2 FOR UPDATE;T2尝试获取行锁,进入等待状态。
步骤6等待中...等待时间未超过3秒。
步骤7抛出错误:ERROR: lock timeout等待时间超过3秒,触发锁超时错误。
步骤8ROLLBACK;T2执行回滚,结束事务。
步骤100COMMIT;T1提交事务,释放行锁。

注意事项:

  • lock_timeout是会话级设置,仅影响当前会话的后续操作,若需全局生效可在postgresql.conf中配置,通常建议在事务内按需设置。
  • 另外还有SELECT FOR UPDATE NOWAIT(无法立即获取锁时直接报错)、SELECT FOR UPDATE SKIP LOCKED(跳过已锁定行)两种方式,但不符合等待3秒再回滚的需求。

内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:01:00