[ PROMPT_NODE_25114 ]
lock-short-transactions
[ SKILL_DOCUMENTATION ]
## 保持事务简短以减少锁竞争
长时间运行的事务会持有锁,从而阻塞其他查询。请尽可能缩短事务的执行时间。
**错误做法(包含外部调用的长事务):**
sql
begin;
select * from orders where id = 1 for update; -- 获取锁
-- 应用程序发起 HTTP 调用到支付 API (2-5 秒)
-- 该行上的其他查询被阻塞!
update orders set status = 'paid' where id = 1;
commit; -- 锁在整个过程中被持有
**正确做法(最小化事务范围):**
sql
-- 在事务外验证数据并调用 API
-- 应用程序: response = await paymentAPI.charge(...)
-- 仅在实际更新时持有锁
begin;
update orders
set status = 'paid', payment_id = $1
where id = $2 and status = 'pending'
returning *;
commit; -- 锁仅持有几毫秒
使用 `statement_timeout` 来防止失控的事务:
sql
-- 中止运行时间超过 30 秒的查询
set statement_timeout = '30s';
-- 或针对当前会话设置
set local statement_timeout = '5s';
参考:[事务管理](https://www.postgresql.org/docs/current/tutorial-transactions.html)