mysql InnoDB如何进行数据提交和回滚_mysql事务处理原理

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

MySQL InnoDB 的事务提交靠
COMMIT
,回滚靠
ROLLBACK

InnoDB 默认开启自动提交(

autocommit=1
),每条 SQL 执行完立刻生效、不可撤销。要手动控制事务,必须先关闭它:
SET autocommit = 0
,再显式用
START TRANSACTION
BEGIN
开启事务块。此时后续的 DML(
INSERT
/
UPDATE
/
DELETE
)会暂存在事务私有版本链中,直到遇到
COMMIT
写入聚簇索引并释放锁,或
ROLLBACK
清空变更、恢复到事务开始前的快照。

事务能回滚的前提是:未被
COMMIT
且连接未断开

常见误解是“只要没关终端就能回滚”,其实关键在连接状态和事务活跃性:

ROLLBACK
只对当前活跃事务有效;执行后事务结束,再执行
ROLLBACK
会报错
ERROR 1370 (42000): execute command denied to user
(实际是 “No transaction in progress” 类错误)
客户端异常断连(如网络中断、kill 连接)、超时(
wait_timeout
触发)会导致事务自动回滚,但不会通知应用层
如果事务中执行了 DDL(如
ALTER TABLE
),InnoDB 会隐式提交当前事务,后续语句不在同一事务内 —— 此时
ROLLBACK
只能回滚 DDL 之后的 DML,无法撤回 DDL 本身

COMMIT
不等于“立刻刷盘”,取决于
innodb_flush_log_at_trx_commit

这个参数决定日志落盘时机,直接影响事务持久性和性能:

innodb_flush_log_at_trx_commit = 1
(默认):每次
COMMIT
都触发
fsync
将 redo log 刷到磁盘,崩溃不丢事务,但 IO 压力大
= 0
:每秒刷一次日志,事务提交只写内存,宕机可能丢失最多 1 秒数据
= 2
:提交时写 OS cache,由系统异步刷盘,崩溃时若 OS 挂了仍可能丢数据

注意:无论设成几,

COMMIT
返回成功即代表该事务已进入 InnoDB 的“已提交但未刷盘”状态,其他事务按隔离级别可见其结果(如可重复读下不可见,读已提交下可见)。

回滚段(undo log)不是无限空间,长事务容易撑爆
ibdata1

InnoDB 把旧版本数据存于 undo log,供 MVCC 和回滚使用。问题在于:

一个运行 10 分钟未提交的事务,会阻止所有早于它的 undo 记录被清理,导致
undo log
持续增长
如果
innodb_undo_tablespaces
未启用,undo 日志全挤在系统表空间
ibdata1
里,文件只增不减
SHOW ENGINE INNODB STATUS
中的
History list length
值持续升高,就是 undo 积压的信号

线上应监控长事务(查

information_schema.INNODB_TRX
表),避免业务逻辑里出现无意义的长时间持锁或交互等待。

相关推荐