mysql中的事务控制语句:BEGIN、COMMIT与ROLLBACK

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

MySQL 事务开始用
BEGIN
还是
START TRANSACTION

两者在功能上完全等价,

BEGIN
START TRANSACTION
的别名,但官方文档明确建议优先用
START TRANSACTION
。原因在于
BEGIN
容易和存储过程中的
BEGIN...END
块混淆,尤其在动态拼接 SQL 或 ORM 自动注入场景下可能引发歧义。

START TRANSACTION
更语义清晰,明确表示“开启一个新事务”
BEGIN
在某些旧版客户端(如早期 phpMyAdmin)中可能被误解析为语句块起始
不支持嵌套事务:即使写两次
START TRANSACTION
,MySQL 也只认最外层,内部的会被忽略

什么情况下
COMMIT
不会真正提交?

COMMIT
失效通常不是语句本身的问题,而是事务上下文已丢失或被隐式结束。常见于以下场景:

执行了非事务性语句(如
CREATE TABLE ... ENGINE=MyISAM
),MySQL 会自动提交当前事务
执行了 DDL 语句(如
ALTER TABLE
DROP INDEX
),InnoDB 会强制提交当前事务并开启新事务
连接异常断开(如超时、客户端崩溃),未
COMMIT
的修改直接丢弃
使用了自动提交模式(
AUTOCOMMIT=1
),单条 DML 语句执行完立即生效,
COMMIT
无实际作用

验证方式:执行

SELECT @@autocommit;
,返回
0
表示手动提交模式启用。

ROLLBACK
能回退到任意中间点吗?

不能。MySQL 默认不支持多级回滚,

ROLLBACK
总是回退到事务最开始的位置。若需部分回滚,必须配合
SAVEPOINT

START TRANSACTION;
INSERT INTO users (name) VALUES ('Alice');
SAVEPOINT sp1;
INSERT INTO users (name) VALUES ('Bob');
SAVEPOINT sp2;
INSERT INTO users (name) VALUES ('Charlie');
ROLLBACK TO SAVEPOINT sp1;  -- 只撤销 'Bob' 和 'Charlie'
COMMIT;
SAVEPOINT
名称区分大小写,且仅在当前事务内有效
回滚到某个
SAVEPOINT
后,该点之后定义的其他
SAVEPOINT
自动失效
事务结束后所有
SAVEPOINT
全部清除,无需手动释放

事务控制语句对锁和并发的影响

事务持续期间,InnoDB 会根据访问的数据行持有锁(如记录锁、间隙锁),这些锁直到

COMMIT
ROLLBACK
才释放。这意味着:

长事务(长时间未
COMMIT
)会拖住锁,导致其他会话阻塞,甚至触发
Lock wait timeout exceeded
ROLLBACK
操作本身可能很慢——它需要逆向执行所有已做的变更,尤其是涉及大量更新时
显式使用
START TRANSACTION
后,哪怕只读查询(如
SELECT
)在可重复读(RR)隔离级别下也会加一致性读锁,影响并发性能

线上业务中,事务应尽量短小,避免在事务内做 HTTP 请求、文件读写等不可控耗时操作。

相关推荐