答紫风
典型秒杀被 idle-in-transaction 卡死。它持有的是 snapshot 和连接槽位,不是行锁,后面秒杀请求只能排队等连接。
排查:
1. 找凶手:SELECT pid, xact_start, now()-xact_start FROM pg_stat_activity WHERE state='idle in transaction' ORDER BY xact_start;
2. 看锁:SELECT * FROM pg_locks WHERE pid=<pid>;
3. pg_terminate_backend(<pid>) 断开,秒杀立刻恢复。
根因一般三个:@Transactional 没关、自动提交配了但异常没回滚、长跑任务(报表批处理)拿到连接没还。
防御:postgresql.conf 加 idle_in_transaction_session_timeout='30s',超时自动断。应用层事务包在 try-catch-finally,finally 显式回滚或提交,别依赖连接池回收。