InnoDB 默认支持事务,无需额外开启
MySQL 5.5 及以后版本中,
InnoDB是默认存储引擎,且**事务支持是内置开启的**。只要建表时没显式指定
ENGINE=MyISAM等不支持事务的引擎,就自动具备事务能力。不需要手动执行
SET AUTOCOMMIT=1或调用
START TRANSACTION来“启用”事务——它们只是控制事务边界的行为,不是开关。
ACID 中的 A(原子性)靠 undo log 实现
执行
UPDATE、
DELETE或
INSERT时,InnoDB 会先写入
undo log,再修改数据页。如果事务中途失败或执行
ROLLBACK,就靠 undo log 回滚到之前状态。
undo log存在
ibdata1或独立表空间里,不是用户直接管理的文件 长事务会阻止 undo log 清理,可能引发
Undo tablespace is full报错
SELECT不加锁时读的是快照(MVCC),不是最新物理数据,所以不会被未提交事务阻塞
隔离级别影响可见性与锁行为
InnoDB 支持全部四种 SQL 标准隔离级别,但默认是
REPEATABLE READ,这点和 PostgreSQL、SQL Server 不同。它通过
next-key lock(间隙锁 + 行锁)防止幻读,但也因此更容易出现死锁。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 此后该连接的 SELECT 将看到其他已提交事务的变更 -- UPDATE/DELETE 仍只锁匹配到的行,不锁间隙
READ UNCOMMITTED:极少用,可能读到未提交的脏数据,InnoDB 不推荐
READ COMMITTED:每次
SELECT都生成新快照,适合高并发读场景
REPEATABLE READ:事务内多次
SELECT结果一致,但需注意
UPDATE ... WHERE可能锁住更大范围
SERIALIZABLE:隐式为所有
SELECT加共享锁,基本等于串行执行,性能损耗大
崩溃恢复靠 redo log 保证 D(持久性)
事务提交前,InnoDB 先把变更写入内存中的
redo log buffer,再刷盘到磁盘上的
ib_logfile0和
ib_logfile1。即使数据库异常宕机,重启时也能根据 redo log 重放未落盘的已提交事务。
innodb_flush_log_at_trx_commit = 1(默认):每次
COMMIT都强制刷盘,最安全但有 I/O 开销
= 0:每秒刷一次,崩溃可能丢一秒事务
= 2:写入 OS cache 即返回,不强制 fsync,崩溃可能丢数据(OS 崩溃时) 不要仅靠
sync_binlog控制持久性,它管的是 binlog,不是 redo log
InnoDB 的 ACID 不是抽象概念,而是由
undo log、
redo log、
buffer pool、
lock system这几块具体机制协同实现的。最容易被忽略的是:事务是否生效,首先得确认表引擎确实是
InnoDB,而不是因为建表语句漏写引擎、或者被
ALTER TABLE ... ENGINE=MyISAM意外改掉。
