innodb_rollback_on_timeout控制锁等待超时(lock wait timeout exceeded)时是否自动回滚整个事务,默认off仅中断语句,on则回滚全部已执行变更;它不改变innodb_lock_wait_timeout值,也不影响死锁检测。

innodb_rollback_on_timeout 是什么,开了就自动回滚事务?
它控制的是:当一个语句因 Lock wait timeout exceeded 失败时,是否连带回滚整个当前事务。默认是 OFF,即只中断那条报错的语句,事务其余部分(之前已执行的 INSERT/UPDATE、未提交的变更)仍保持打开状态。
开启后(设为 ON),一旦触发锁等待超时,MySQL 会主动执行 ROLLBACK 整个事务,而不是留着半开状态等你处理——这能避免后续误提交或数据不一致,但代价是丢失所有已做的修改。
注意:它**不改变** innodb_lock_wait_timeout 的值,也不影响死锁检测行为;它只响应“锁等待超时”这一种错误类型。
怎么临时开启(会话级)?
适合测试或紧急修复,重启后失效:
- 先确认当前值:
SHOW VARIABLES LIKE 'innodb_rollback_on_timeout'; - 开启当前连接:
SET SESSION innodb_rollback_on_timeout = ON; - 验证生效:
SELECT @@session.innodb_rollback_on_timeout;应返回1
这个设置只对当前连接有效,不影响其他连接,也无需重启 MySQL。
怎么永久开启(全局级)?
需修改配置文件并重启,对所有新连接生效:
- 编辑
/etc/my.cnf或/etc/mysql/my.cnf - 在
[mysqld]段落下添加:innodb_rollback_on_timeout = ON - 保存后重启服务:
sudo systemctl restart mysql - 检查是否生效:
SHOW VARIABLES LIKE 'innodb_rollback_on_timeout';应显示ON
SET GLOBAL 方式虽可写,但某些 MySQL 版本(尤其 RDS 等托管服务)会拒绝该操作;配置文件方式更稳妥。
开了之后要注意什么?
它解决的是“事务半开”风险,但掩盖不了根本问题:
- 频繁触发
Lock wait timeout exceeded说明存在长事务、缺失索引、或业务逻辑锁竞争激烈——自动回滚只是兜底,不是优化 - 开启后,应用层仍需捕获错误并重试,否则用户看到的仍是失败,只是状态更干净
- 若事务中包含不可逆操作(如发消息、调外部 API),回滚无法撤回这些动作,需配合补偿逻辑
-
innodb_rollback_on_timeout = ON会让事务原子性更强,但也让调试更难:你再也看不到“卡在中间”的事务现场了
真正关键的,永远是定位谁在 hold 锁、为什么等不到——SHOW ENGINE INNODB STATUS\G 和 information_schema.innodb_trx 才是你该先打开的工具。











