什么是mysql事务_mysql事务基础概念解析

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

MySQL事务
是一组 DML 操作(
INSERT
UPDATE
DELETE
)的逻辑集合,它必须全部成功,或全部失败——没有“一半生效”的中间状态。这是 InnoDB 存储引擎提供的核心能力,MyISAM 等引擎不支持事务,直接绕过这个机制。


为什么默认转账会出错?因为 autocommit=1

你写两条

UPDATE
转账语句,没加任何事务控制,结果张三扣了钱、李四没到账——这不是 bug,是 MySQL 的默认行为在起作用:

autocommit
默认为
1
,即每条 DML 语句单独成一个事务,自动提交
第一条
UPDATE
执行完立刻落盘;第二条若因网络中断、程序崩溃、SQL 错误而失败,已提交的第一条无法撤回
这就是典型的“数据不一致”:总金额凭空减少

✅ 正确做法:显式关闭自动提交,用

START TRANSACTION
包裹操作:

SET autocommit = 0;
START TRANSACTION;
UPDATE account SET money = money - 100 WHERE name = '张三';
UPDATE account SET money = money + 100 WHERE name = '李四';
COMMIT;

⚠️ 注意:

SET autocommit = 0
只对当前会话有效;生产环境更推荐在代码里用
BEGIN
/
COMMIT
显式控制,避免依赖会话级配置。


事务不是万能锁:ACID 里最常被误解的是“一致性”

很多人以为“事务保证数据正确”,其实

consistency
不是数据库自动校验业务规则,而是指:事务前后,数据库必须满足你定义的约束(如主键、外键、
CHECK
、唯一索引等)。

如果你没给
money
字段加
CHECK(money >= 0)
,事务照样允许余额变成 -500 —— 这不算违反 ACID,只是你的业务一致性没落地
转账中 A 减、B 增,但没加外键或触发器校验双方账户存在?事务提交了,但业务上已经错了
COMMIT
成功 ≠ 业务正确;它只代表“数据库层面没违反约束”

? 真正兜底要靠:约束定义 + 应用层校验 + 幂等设计(比如用转账单号防重)


事务隔离级别不是调高就安全:REPEATABLE READ 也挡不住幻读

MySQL 默认隔离级别是

REPEATABLE READ
,它能防止脏读、不可重复读,但**无法完全避免幻读**(比如
SELECT ... FOR UPDATE
范围内新插入一行,再次查出来多了一条)。

READ COMMITTED
:每次
SELECT
都读最新已提交版本 → 可能不可重复读,但幻读概率更低
REPEATABLE READ
:基于 MVCC 快照读,可重复读,但快照不覆盖新插入行 → 幻读仍可能发生
SERIALIZABLE
:加范围锁强制串行,性能差,一般不用

? 实际选择建议:

普通 Web 应用:保持默认
REPEATABLE READ
,幻读场景手动加
SELECT ... FOR UPDATE
或用唯一业务键替代范围查询
强一致性金融场景:别只调隔离级别,配合乐观锁(
version
字段)或分布式事务框架(如 Seata)

事务生命周期结束的 4 种方式,第 3 种最容易被忽略

事务不是开了就一直挂着,它会在以下任一情况自动终止:

COMMIT
ROLLBACK
显式结束
执行了
DDL
(如
ALTER TABLE
)、
DCL
(如
GRANT
)——这些语句会隐式提交当前事务
客户端连接异常断开(如超时、kill connection) → MySQL 会自动回滚未提交事务 用户会话正常退出(如命令行
exit
)→ 同样自动回滚

⚠️ 关键陷阱:应用层长事务(比如导出报表+更新状态)若没设好连接超时,可能卡住锁、拖垮并发。务必在代码里明确

COMMIT
ROLLBACK
,不要依赖自动清理。

相关推荐