显式事务必须用 begin 或 start transaction 显式开启,不可靠 autocommit 配置触发;支持 savepoint 等精细控制,而隐式事务仅每条语句自动启停、不支持保存点且易导致长事务和锁堆积。

显式事务必须用 BEGIN 或 START TRANSACTION 显式开启
显式事务不是靠配置开关自动触发的,而是由 SQL 语句明确控制生命周期。你写 BEGIN,事务才开始;不写,哪怕 autocommit=1,也不会进入显式事务流程。常见错误是以为只要关了 autocommit 就等于在用显式事务——其实那只是进入了「隐式事务」模式。
关键点在于:显式事务中你可以用 SAVEPOINT、ROLLBACK TO SAVEPOINT、RELEASE SAVEPOINT 等精细控制回滚点;而隐式事务不支持这些,只能整段 ROLLBACK 或 COMMIT。
-
START TRANSACTION READ ONLY和START TRANSACTION WITH CONSISTENT SNAPSHOT只对显式事务生效 - DDL(如
CREATE TABLE)在显式事务中会隐式触发COMMIT,导致前面的 DML 提前提交,这点极易踩坑 - 如果连接池(如 DBCP)设置了
defaultAutoCommit=false,但应用层没写BEGIN,那每次 DML 都会走隐式事务——看似“手动控制”,实则失去事务边界意识
隐式事务依赖 autocommit 关闭,且每条语句自成事务单元
隐式事务的本质是:当 autocommit=0 时,MySQL 会为**每一条单独执行的 DML 语句**自动开启一个事务,并等待你后续发 COMMIT 或 ROLLBACK。它不感知语句之间的逻辑关系,也不维护跨语句的状态。
典型误用场景:在 autocommit=0 下连续执行两条 UPDATE,中间没 COMMIT,你以为它们在一个事务里——其实不是。第二条 UPDATE 执行时,第一条还没提交,但锁和隔离性已按事务规则生效;一旦连接断开或客户端异常退出,未提交的部分全丢,且无法局部回滚。
- 隐式事务下不能使用
SAVEPOINT,语法报错:ERROR 1305 (42000): SAVEPOINT does not exist -
SELECT语句在autocommit=0下也会开启事务(尤其是带FOR UPDATE或LOCK IN SHARE MODE时),容易意外持锁 - ORM 框架(如 MyBatis)若配置了
autoCommit=false但没配@Transactional,就可能掉进隐式事务陷阱,导致长事务、锁堆积
autocommit=0 不等于性能更好,反而常引发高开销
把 autocommit 设为 0 并不会自动提升性能,反而在多数简单操作场景下显著拖慢响应。DBCP 连接池实测显示:defaultAutoCommit=false 时,单条 SELECT 会产生额外 6 次数据库交互(含状态同步、事务上下文初始化等),而 true 时直通执行。
真正需要关 autocommit 的,只有两类情况:批量写入(如 1000 行 INSERT 合并一次 COMMIT)、或业务强依赖事务边界(如转账)。其他时候,让 MySQL 默认行为工作更轻量、更可靠。
- MySQL 默认
autocommit=1,与服务端行为一致;强行统一设为 0,需同步改所有客户端连接配置,维护成本陡增 -
SET autocommit=0是会话级变量,GLOBAL设置对SUPER用户无效,线上排查时容易漏看权限差异 - 某些云数据库(如阿里云 RDS)会限制
init_connect的使用,autocommit全局修改可能被静默忽略
混合使用时最容易忽略的是事务嵌套失效问题
MySQL 不支持真正的事务嵌套。你在显式事务中再执行 BEGIN,不会新建事务,而是被忽略或报错(取决于版本和 SQL mode)。更危险的是:在 autocommit=0 的会话里执行 START TRANSACTION,它不会“叠加”事务,而是重置当前事务状态——之前未提交的变更仍存在,但保存点、隔离级别等可能被覆盖。
这种混合场景下,ROLLBACK 的行为变得不可预测:它只回滚到最近一次 START TRANSACTION 之后的操作,而不是整个会话累积的变更。调试时看到数据没回滚干净,八成是这里出了问题。
- 避免在同一个连接中混用
SET autocommit=0和START TRANSACTION - 应用层若用连接池,务必确认连接获取后是否复位了
autocommit状态(有些池不自动 reset) - 监控慢查询时,留意
trx_state = 'LOCK WAIT'且trx_started时间异常早的事务,大概率是隐式事务长期未提交造成的











