会,但仅当连接异常终止且autocommit=0时MySQL服务端主动回滚未提交事务;正常断开或autocommit=1下不适用,SQL执行中中断回滚语句级更改,执行完未提交则事务与锁持续存在直至超时或人工清理。

MySQL 在客户端断开时如何处理未完成的 SQL
客户端突然断开(比如进程 kill、网络中断、机器宕机),MySQL 不会立刻感知到连接已失效,未执行完的 SQL 也不会自动回滚或终止——它取决于 SQL 执行所处的阶段和事务状态。
SQL 正在执行中被中断:通常会回滚语句级事务
如果客户端在一条 UPDATE、DELETE 或带 SELECT ... FOR UPDATE 的语句执行中途断开,MySQL 服务端在尝试写回结果包时发现 socket 不可写(例如 send() 返回 EPIPE 或 ECONNRESET),会触发错误路径:trans_rollback_stmt(thd)。此时该语句的更改会被回滚,但整个事务不一定结束。
- 仅适用于语句正在执行、尚未返回结果的场景
- 回滚的是当前语句影响的行,不是整个事务(除非是 autocommit=1)
- 如果语句已完成执行但客户端没收到响应(比如大结果集传输一半断开),服务端可能仍认为执行成功,不会回滚
SQL 已执行完但事务未提交:锁和事务持续存在
这是最危险的情况:客户端执行完 UPDATE t1 SET x=1 WHERE id=1,还没发 COMMIT 就断了。此时:
- 事务状态在
INFORMATION_SCHEMA.INNODB_TRX中仍为running -
SELECT ... FOR UPDATE或 DML 持有的行锁不会释放,阻塞其他会话 - 服务端无法主动检测这种“静默断连”,因为 TCP 连接状态仍是
ESTABLISHED(缺少保活机制) - 直到
wait_timeout或interactive_timeout超时后,连接才被关闭,事务才被回滚
如何避免残留事务和锁堆积
关键不是等超时,而是从客户端和服务端两个方向设防:
- 客户端务必设置合理的 socket 超时:
connectTimeout、socketTimeout(JDBC),或read_timeout/write_timeout(Python mysql-connector) - 服务端调低
wait_timeout(建议 60–300 秒),避免空闲事务长期占锁;注意它不影响活跃查询中的等待 - 应用层捕获
Communications link failure或MySQL server has gone away后,主动丢弃当前连接并重建,不要复用 - 监控
SHOW PROCESSLIST中Command为Sleep且Time超过阈值的连接,配合KILL清理
真正容易被忽略的是:事务是否“已执行完”和“是否已提交”在断连场景下完全不等价;一个卡在 COMMIT 前的连接,既不会释放锁,也不会被自动清理,只能靠超时或人工干预。











