锁等待超时参数是什么
锁等待不是无限期的,超时参数决定语句等多久,超时后报错放弃。MySQL 的分行锁等待用 innodb_lock_wait_timeout(默认 50 秒,超时报 1205),元数据锁等待由 lock_wait_timeout 控制(默认值极长);PostgreSQL 用 lock_timeout(默认 0 表示不限制)、statement_timeout(整条语句上限)与 deadlock_timeout(启动死锁检测前的等待)。这些参数是止损手段:把「无限期挂住」变成可观测的失败,便于重试或降级。
基本信息
| MySQL 行锁参数 | innodb_lock_wait_timeout,默认 50 秒,可会话级调整,超时报 1205 |
|---|---|
| MySQL 元数据锁参数 | lock_wait_timeout,默认值极长,DDL 排队时最常踩 |
| PostgreSQL 参数 | lock_timeout(默认 0 不限制)、statement_timeout、deadlock_timeout(默认 1s) |
| PG 错误码 | 55P03 表示拿不到锁,57014 表示语句被超时取消 |
| 设置方式 | MySQL SET SESSION innodb_lock_wait_timeout = 10;PG SET lock_timeout = '5s' |
典型使用场景
- 防止应用线程被锁等待无限期挂住,把阻塞变成可重试的失败
- 监控超时次数,判断锁竞争是否在恶化
- 批处理任务设置短超时,快速失败而不是长时间占着连接
- 迁移与 DDL 脚本设置 lock_timeout,避免把线上查询排成长队
- 排查 1205 与 55P03 报错背后的长事务
MySQL 参数调整
MySQL 参数调整
-- 查看当前设置
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; # 默认 50 秒
SHOW VARIABLES LIKE 'lock_wait_timeout'; # 元数据锁等待,默认时间极长
-- 会话级调整:批处理与迁移脚本建议设短一些
SET SESSION innodb_lock_wait_timeout = 10; # 10 秒拿不到锁就报 1205
-- 全局调整需谨慎,影响所有新连接
SET GLOBAL innodb_lock_wait_timeout = 20;PostgreSQL 参数调整
PostgreSQL 参数调整
SHOW lock_timeout; -- 0 表示不限制
SHOW statement_timeout; -- 整条语句的执行上限
SET lock_timeout = '5s'; -- 5 秒拿不到锁就中止
SET statement_timeout = '30s'; -- 语句最长执行 30 秒
SET deadlock_timeout = '1s'; -- 等这么久仍拿不到锁才启动死锁检测
-- 迁移场景:短超时快速失败,避免阻塞线上查询
SET lock_timeout = '2s';
ALTER TABLE big_table ADD COLUMN note text; -- 拿不到锁立即失败,稍后重试参数速查
| 参数 | 默认值 | 作用 |
|---|---|---|
| innodb_lock_wait_timeout(MySQL) | 50 秒 | 行锁等待上限,超时报 1205 |
| lock_wait_timeout(MySQL) | 约一年 | 元数据锁等待上限,DDL 排队时最常踩 |
| lock_timeout(PG) | 0(不限制) | 获取锁的等待上限 |
| statement_timeout(PG) | 0(不限制) | 语句整体执行上限 |
| deadlock_timeout(PG) | 1 秒 | 启动死锁检测前愿意等待的时间 |
超时参数大多可以按会话设置(SET SESSION / SET),批处理与迁移脚本临时调短、快速失败最合适;全局值要根据业务容忍度谨慎调整,设得过短会让正常的长事务开始报错。
超时只是止损不是解决方案:频繁出现 1205 或锁超时说明存在长事务、缺索引或热点行竞争,应回到锁等待排查找根因,而不是继续把超时时间调大。