mysql不支持事务总执行时长硬性超时,所谓“事务超时”实为防连接池耗尽的组合策略:innodb_lock_wait_timeout(默认50秒,建议调至15~25秒)控制行锁等待超时并回滚当前语句;wait_timeout(建议300秒)防空闲连接挂起;max_execution_time(仅select,单位毫秒)与客户端hikaricp的connection-timeout、sockettimeout、leak-detection-threshold协同兜底;存储过程需手动时间检查,dml超时须依赖客户端setquerytimeout或kill query。

MySQL 本身不支持事务总执行时长的硬性超时,所谓“设置事务超时”其实是防止连接池耗尽的一整套防御组合,核心是切断长事务对连接的持续占用。
innodb_lock_wait_timeout 不是事务超时,但它是第一道止损线
这个参数控制事务在等待行锁时最多忍多久,超时后报 Lock wait timeout exceeded 并自动回滚当前语句(不是整个事务)。它不终止已拿到锁的长执行,但能快速暴露锁争抢问题。
- 默认值 50 秒太高,高并发下建议设为
15~25(单位:秒) - 会话级生效最快:
SET SESSION innodb_lock_wait_timeout = 15; - 全局修改需写进
my.cnf的[mysqld]段,并重启或用SET GLOBAL(需权限) - 它对表锁、MDL 锁、空闲事务完全无效——别指望靠它拦住
SLEEP(60)或卡在 HTTP 回调里的存储过程
wait_timeout 和 max_execution_time 要配对用,缺一不可
wait_timeout 控制空闲连接存活时间,max_execution_time 控制 SELECT 执行上限,二者作用对象不同,但共同防止连接被“无声占用”。
-
wait_timeout建议设为300(5 分钟),避免应用异常退出后连接长期挂起;注意它只在无任何语句执行时倒计时,一旦事务里执行了 SQL,计时就重置 -
max_execution_time仅对SELECT生效(MySQL 5.7.8+),单位毫秒:SET GLOBAL max_execution_time = 30000; -
max_execution_time必须写在[mysqld]段才持久化,写错段落(如[client])会静默失效 - DML(
INSERT/UPDATE/DELETE)不响应max_execution_time,这类语句超时必须靠客户端setQueryTimeout()或监控 +KILL QUERY
HikariCP 连接池必须配齐 connection-timeout、socketTimeout 和 leak-detection-threshold
服务端参数再严,也挡不住客户端连接不归还。HikariCP 是实际管连接生命周期的一方,它的三个 timeout 参数缺一不可。
-
connection-timeout:获取连接的等待上限,建议30000(30 秒),避免线程卡死在“拿连接”这步 -
socketTimeout:JDBC URL 里加socketTimeout=10000,中断挂住的查询读写,单位毫秒 -
leak-detection-threshold:设为60000(60 秒),一旦连接被借出后 60 秒未归还,HikariCP 会打印堆栈,精准定位哪段代码漏关CallableStatement或没消费完多结果集 - 别漏掉
max-lifetime(建议1800000,即 30 分钟)和idle-timeout(建议600000,即 10 分钟),防止 MySQL 主动断连后连接还在池里残留
存储过程内部必须手动加时间兜底,不能依赖 MySQL 自动机制
MySQL 存储过程没有 SET TRANSACTION TIMEOUT 语法,SLEEP()、GET_LOCK()、外部 HTTP 调用等操作完全绕过所有服务端超时机制。
- 开头记录起点:
SELECT NOW() INTO @start_time; - 关键节点检查:
IF TIMESTAMPDIFF(SECOND, @start_time, NOW()) > 30 THEN ROLLBACK; LEAVE proc_label; END IF; - 所有
START TRANSACTION必须包裹DECLARE EXIT HANDLER FOR SQLEXCEPTION,否则异常跳出时事务悬空 - Java 调用时必须用
try-with-resources关闭CallableStatement,且要消费全部结果集(getMoreResults()),否则连接卡在 “Sleep” 状态但实际被占用
真正容易被忽略的是:innodb_lock_wait_timeout 只对行锁有效,而长事务阻塞往往来自未提交事务持有的间隙锁、MDL 锁或 purge 线程被拖慢——这些都得靠定期查 information_schema.INNODB_TRX 和 PROCESSLIST 配合应用层事务边界控制来解决。











