如何设置 wait_timeout 与 idle_in_transaction_session_timeout?

解读

在国内互联网面试中,这道题常被用来区分“只会用控制台点按钮”与“能把参数揉进 DevOps 流水线”的候选人。
面试官真正想听的是:

  1. 你能否准确说出两个参数的业务含义与风险
  2. 你能否在不重启实例的前提下完成变更
  3. 你能否把变更固化到 IaC 与灰度流程,而不是“改一次忘一次”。
    答不到这三层,基本会被追问“如果凌晨 3 点连接暴涨,你怎么回滚?”

知识点

  • wait_timeout:服务端非交互式连接的空闲存活秒数,MySQL 默认 28800 s(8 h),PostgreSQL 无直接同名参数,需用 idle_in_transaction_session_timeoutstatement_timeout 组合治理。
  • idle_in_transaction_session_timeout:PostgreSQL 9.6+ 专属,事务开启后未提交也未回滚的空闲上限,单位毫秒;MySQL 无直接对应,需靠 innodb_lock_wait_timeoutwait_timeout 间接缓解长事务。
  • Cloud SQL 参数层级:实例级数据库标志(flags) > 用户会话 SET > 全局 SET(仅当前生命周期有效);面试必须强调“实例级 flags 才能持久化”。
  • 变更路径:
    – 控制台 UI:实例 → 修改 → 标志 → 添加 wait_timeoutidle_in_transaction_session_timeout → 保存 → 滚动重启(30 s~90 s 闪断)。
    – gcloud CLI:
    gcloud sql instances patch <实例ID> \
      --database-version=POSTGRES_15 \
      --flags=idle_in_transaction_session_timeout=300000,wait_timeout=600
    
    该命令自动触发滚动重启,国内网络下需加 --verbosity=info 观察进度,防止因 VPN 中断误判。
  • 风险兜底:
    – 改前克隆实例做影子验证;
    – 改后Cloud Monitoring 仪表盘database/mysql/connectionsdatabase/postgresql/num_backends 曲线;
    – 若业务突现“MySQL server has gone away”,10 秒内可回滚
    gcloud sql instances patch <实例ID> --flags=wait_timeout=28800
    
  • IaC 固化:Terraform 模板片段
    resource "google_sql_database_instance" "default" {
      settings {
        database_flags {
          name  = "wait_timeout"
          value = "600"
        }
        database_flags {
          name  = "idle_in_transaction_session_timeout"
          value = "300000"
        }
      }
    }
    
    面试时补充“我们把 tf 文件放在 GitLab,MR 触发 Atlantis 自动 plan,只有 DBA 与 SRE 双 Code Review 通过才能 apply”,可瞬间拉高印象分。
  • 国内合规:若数据库属于等保三级系统,参数变更需走 4A 平台工单,Terraform 需对接 云堡垒机 API 留痕,否则年审会被扣分。

答案

“以 PostgreSQL 15 为例,我会按四步落地:

  1. 评估:业务代码最长事务 3 min,因此把 idle_in_transaction_session_timeout5 min(300000 ms)wait_timeout10 min(600 s),既防连接泄漏,又避免秒杀场景频繁重连。
  2. 灰度:先用 gcloud 克隆出 canary 实例,patch 新参数,跑 24 h 压测;同时用 Cloud SQL Auth Proxy 的 -max_connections 模拟 5000 并发,确认 QPS 不掉。
  3. 上线:通过 Terraform MR 修改正式实例 flags,Atlantis 自动 apply;滚动重启期间前端 Jetty 连接池开启 testOnBorrow=true,屏蔽闪断。
  4. 观测与回滚:Cloud Monitoring 配置 idle_in_transaction_session_timeout 触发告警,若 pg_stat_activity 中 idle in transaction > 4 min 的会话数 > 10 立即通知;一旦误杀长事务,30 秒内 terraform rollback 到上一版本
    MySQL 同理,只需把 wait_timeoutinteractive_timeout 同时写入 flags,并验证 innodb_rollback_on_timeout 为 OFF,防止大事务被意外回滚。”

拓展思考

  • 如果业务是 Spring Batch 夜间跑批,单事务可能持续 20 min,你会如何仅对批处理账号豁免
    提示:利用 ALTER USER batch_user SET idle_in_transaction_session_timeout = 0,但 Cloud SQL 目前不支持用户级设置,需改用 proxy 级连接池把批处理路由到 只读实例,并关闭超时。
  • 国内 双 11 流量洪峰场景,wait_timeout 从 600 s 降到 60 s 后,连接池出现 “MySQLNonTransientConnectionException: No operations allowed after connection closed”,如何不停机修复
    提示:在 HikariCP 侧把 maxLifetime 设为 55 s,确保连接池主动淘汰比服务端提前 5 s,规避 race condition;同时把 gcloud sql instances patch 放进 Ansible Rolling Update分 10 批梯度重启,每批间隔 2 min,用 SLB 小流量观察错误率。