mysql事务在什么时候开启_mysql执行流程解析

来源:这里教程网 时间:2026-02-28 20:43:57 作者:

事务默认什么时候开启?别被“自动提交”骗了

MySQL 中事务不是你一连上就自动“开着”的,而是由

autocommit
状态决定的。默认情况下,
autocommit=1
,这意味着每条
INSERT
UPDATE
DELETE
语句都会被当作一个独立事务——执行完立刻提交,根本没机会回滚。

所以严格来说:**没有显式开启事务时,事务是“瞬间开启又瞬间结束”的**,你感觉不到它的存在 只有当你关闭自动提交(
SET autocommit = 0
)或显式执行
BEGIN
/
START TRANSACTION
后,事务才真正“活”起来,进入可控制的生命周期
注意:
SELECT
不会触发事务(除非加了
FOR UPDATE
LOCK IN SHARE MODE
),它只是快照读,不改变事务状态

显式开启事务的两种写法,效果一样但习惯不同

BEGIN
START TRANSACTION
都能开启一个新事务,它们在 InnoDB 中完全等价,没有底层差异,选哪个纯看团队规范或个人偏好。

BEGIN
更简洁,适合快速交互式调试(比如 MySQL CLI 里随手测试)
START TRANSACTION
语义更清晰,明确表达“我要开始一个事务”,更适合生产 SQL 脚本或 ORM 日志中追踪
⚠️ 别用
BEGIN WORK
—— 虽然语法合法,但已过时,官方文档不推荐
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;
INSERT INTO log (msg) VALUES ('deducted 100');
COMMIT;

事务真正的“起点”不在 BEGIN,而在第一条修改语句执行时

InnoDB 的事务生命周期其实比 SQL 语句更底层:当你执行

START TRANSACTION
,MySQL 只是分配了事务 ID、初始化 undo log 空间;真正让事务“动起来”的,是第一条 DML(如
UPDATE
)执行时——此时才会生成第一个 undo log 记录,并锁定对应行/间隙。

如果
START TRANSACTION
后只执行
SELECT
,事务处于“空闲但活跃”状态,不产生 undo log,也不加锁(默认 RR 隔离级别下仍是快照读)
一旦执行首个
UPDATE
,InnoDB 才真正开始维护事务一致性,后续所有操作都受该事务上下文约束
这意味着:事务的“实际开启点”是数据变更动作,不是语法关键字——这对理解死锁和锁等待特别关键

容易被忽略的关键细节:BEGIN 之前的状态也影响事务行为

很多人以为

BEGIN
是事务一切的起点,其实不然。事务行为还取决于它之前的会话设置,尤其是隔离级别和 autocommit 状态。

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
必须在
BEGIN
之前执行才生效;如果写在
BEGIN
之后,会报错或被忽略(取决于 MySQL 版本)
如果当前会话
autocommit=1
,你执行
BEGIN
后没
COMMIT
就断开连接,MySQL 会自动回滚未提交的更改——但这个“自动回滚”不是事务本身的行为,而是连接终止时的清理机制
最隐蔽的坑:某些客户端(如 phpMyAdmin、DBeaver)会在每次执行 SQL 后自动加
COMMIT
,即使你写了
BEGIN
,也可能被悄悄提交掉,务必检查客户端配置里的“自动提交”开关

事务真正可控的起点,是你关掉

autocommit
或敲下
BEGIN
的那一刻;但它的“呼吸感”——何时加锁、何时记日志、何时影响并发——全藏在第一条 DML 执行的瞬间。别只盯着语法,得看 InnoDB 实际做了什么。

相关推荐