mysql如何使用事务_mysql事务控制语法解析

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

事务必须显式开启,
BEGIN
或
START TRANSACTION
缺一不可

MySQL 默认是自动提交模式(

autocommit=1
),每条 DML 语句单独成事务,执行完立刻生效。想把多条语句打包进一个事务,必须先显式开启——只写
COMMIT
或
ROLLBACK
没用,它们不会触发隐式开始。

常见错误:直接写

UPDATE t1 SET x=1; UPDATE t2 SET y=2; COMMIT;
,结果两条更新各自提交,无法回滚。

BEGIN
和
START TRANSACTION
完全等价,任选其一即可
不推荐用
BEGIN WORK
,虽兼容但冗余
开启后,后续所有 DML(
INSERT
/
UPDATE
/
DELETE
)都暂存在当前事务中,直到
COMMIT
或
ROLLBACK

SAVEPOINT
不是必需的,但能解决部分回滚需求

标准事务只有全提交或全回滚两种结局。如果中间某步出错,又不想放弃前面已成功的操作,就得靠

SAVEPOINT
设立标记点。

例如:插入主表、插入从表、更新统计表 —— 若第三步失败,只回滚到第二步之后的状态,保留前两步。

定义:
SAVEPOINT sp1;
,名字可自定义,同一事务内可设多个
回滚到某点:
ROLLBACK TO SAVEPOINT sp1;
(注意不是
ROLLBACK TO sp1
)
释放某个保存点:
RELEASE SAVEPOINT sp1;
,不影响事务本身
事务结束(
COMMIT
或
ROLLBACK
)会自动清除所有保存点

隐式提交语句会让事务意外终止

有些 SQL 语句执行时会强制提交当前事务,哪怕你没写

COMMIT
,事务也立刻结束。这是最容易踩坑的地方,尤其在存储过程或混合 DDL/DML 场景中。

典型触发隐式提交的语句包括:

CREATE TABLE
、
DROP TABLE
、
ALTER TABLE
、
TRUNCATE TABLE
、
LOCK TABLES
、
FLUSH LOGS
等。

示例:
BEGIN; INSERT INTO t VALUES(1); CREATE TABLE tmp(id INT); INSERT INTO t VALUES(2); COMMIT;
→ 实际只有最后一条
INSERT
受事务保护
SELECT
不会隐式提交,但
SELECT ... FOR UPDATE
或
SELECT ... LOCK IN SHARE MODE
属于事务内加锁操作,仍需在事务中使用
DDL 类操作尽量放在事务外,或确认是否真需要与 DML 绑定

事务隔离级别影响可见性,
SET TRANSACTION ISOLATION LEVEL
必须在
BEGIN
前设置

MySQL 的默认隔离级别是

REPEATABLE READ
,但如果你需要读已提交(
READ COMMITTED
)来避免间隙锁或适配其他数据库行为,得手动改——而且时机很关键。

错误写法:

BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
→ 此时事务已开启,该语句无效,级别仍是启动时的默认值。

正确方式:在
BEGIN
前执行,如
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN;
也可用会话级设置:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
,之后所有新事务都生效
READ UNCOMMITTED
和
SERIALIZABLE
同理,不能在事务中动态切换
事务的边界比看起来更“脆”:一条 DDL、一个连接中断、甚至某些客户端自动重连行为,都可能让
BEGIN
形同虚设。实际写业务逻辑时,别只盯着
COMMIT
写在哪,先确认事务是不是真的从你想的位置开始了。

相关推荐