标准答案

  1. statement_timeout 限制一条 SQL 从开始执行到结束的最长时间,包含执行和等待阶段;它不是整个事务的总时长限制,也可能中断合法的大查询、报表或迁移。
  2. lock_timeout 只在语句等待锁时生效。它可以让 DDL 或关键写入快速失败,但不能解决已经拿到锁后执行很慢的 SQL。
  3. idle_in_transaction_session_timeout 处理“事务已经打开,但客户端暂时不再发送 SQL”的会话,避免它长期保留快照、锁和连接池名额。
  4. 超时通常取消当前语句或终止空闲事务会话,不代表应用端已经完成状态清理;驱动必须确认事务已回滚,连接池要重置或丢弃不确定的连接。
  5. 应按角色和场景设置预算:在线请求、后台任务、迁移和运维会话不能共用一个过小的超时;迁移还应配合 lock_timeout 先探测锁,而不是无限等待。

题目解析

三个参数保护的是不同阶段:statement_timeout 保护整条语句,lock_timeout 保护锁等待,idle_in_transaction_session_timeout 保护已经打开但不再工作的事务。把它们混为一谈,会让排查和告警失去方向。

在线请求被取消后,事务可能处于 aborted 状态,后续 SQL 会继续失败,直到执行 ROLLBACK;如果连接池把它直接交给下一个请求,就会出现与原始超时无关的连锁报错。

超时值要和上游请求、重试策略、锁竞争和业务 SLA 一起设计。数据库快速失败后,应用应记录 SQL 类型、SQLSTATE、事务状态和重试结果,否则只会把数据库错误变成无上下文的 500。

常见误区

  • 误区:把 lock_timeout 当成整条 SQL 的超时。改正:它只限制等待锁的时间,仍需要 statement_timeout 或应用级截止时间。
  • 误区:所有连接统一设置极短的 statement_timeout。改正:在线请求和批处理的合法执行时间不同,应按角色、事务和任务类型分层配置。
  • 误区:语句超时后把连接直接归还连接池。改正:先回滚并重置会话状态;无法确认连接状态时应关闭连接,不能让下一个请求继承失败事务。

作者信息