MySQL事务详解
一、事务概述
事务是一组数据库操作,要么全部成功,要么全部失败。
ACID特性
原子性(Atomicity):
- 事务是不可分割的工作单位
- 要么都做,要么都不做
一致性(Consistency):
- 事务必须使数据库从一个一致性状态变换到另一个一致性状态
隔离性(Isolation):
- 多个事务并发执行时,互不干扰
持久性(Durability):
- 事务一旦提交,对数据库的改变是永久的
二、事务的使用
基本语法
1 | -- 开启事务 |
示例
1 | START TRANSACTION; |
三、事务隔离级别
并发问题
脏读:
- 读到其他事务未提交的数据
不可重复读:
- 同一事务中,两次读取同一数据结果不同
- 重点是其他事务修改了数据
幻读:
- 同一事务中,两次查询结果数量不同
- 重点是其他事务新增或删除了数据
四种隔离级别
读未提交(READ UNCOMMITTED):
- 允许读取未提交的数据
- 可能脏读、不可重复读、幻读
读已提交(READ COMMITTED):
- 只能读取已提交的数据
- 可能不可重复读、幻读
- Oracle默认级别
可重复读(REPEATABLE READ):
- 同一事务中读取同一数据结果相同
- 可能幻读
- MySQL默认级别
串行化(SERIALIZABLE):
- 最高隔离级别
- 解决所有问题
- 性能最低
查看和设置
1 | -- 查看隔离级别 |
四、事务实现原理
原子性实现
使用undo log(回滚日志):
- 记录数据修改前的值
- 回滚时恢复数据
undo log类型:
- insert undo log:插入操作,回滚直接删除
- update undo log:更新操作,回滚恢复旧值
持久性实现
使用redo log(重做日志):
- 记录数据修改后的值
- 崩溃恢复时重放操作
WAL机制:
- 先写日志,再写磁盘
- 减少随机I/O
隔离性实现
锁机制:
- 读写锁
- 行锁、表锁
- 共享锁、排他锁
MVCC(多版本并发控制):
- 读操作不加锁
- 写操作加锁
- 通过版本号实现
一致性实现
- 原子性保证操作完整
- 隔离性保证并发正确
- 持久性保证结果永久
- 数据库约束保证数据正确
五、MVCC详解
版本链
每条记录包含隐藏列:
- DB_TRX_ID:最后修改的事务ID
- DB_ROLL_PTR:回滚指针,指向undo log
通过回滚指针形成版本链。
Read View
读操作时生成一致性视图:
- m_ids:活跃事务ID列表
- min_trx_id:最小活跃事务ID
- max_trx_id:下一个将分配的事务ID
- creator_trx_id:创建者事务ID
可见性判断
记录的DB_TRX_ID:
- 小于min_trx_id:已提交,可见
- 大于等于max_trx_id:未开始,不可见
- 在m_ids中:未提交,不可见
- 不在m_ids中:已提交,可见
- 等于creator_trx_id:自己修改,可见
RC和RR区别
READ COMMITTED:
- 每次SELECT生成新的Read View
REPEATABLE READ:
- 第一次SELECT生成Read View,后续复用
六、事务最佳实践
事务控制
- 事务尽量简短,减少锁持有时间
- 避免在事务中进行耗时操作
- 避免事务嵌套
隔离级别选择
- 默认使用REPEATABLE READ
- 需要实时数据用READ COMMITTED
- 数据一致性要求极高用SERIALIZABLE
死锁避免
- 按相同顺序访问资源
- 避免长事务
- 设置合理的锁等待超时
1 | -- 查看锁等待超时时间 |
七、总结
事务核心要点:
- ACID特性保证数据完整性
- 四种隔离级别解决并发问题
- undo log保证原子性
- redo log保证持久性
- MVCC实现非阻塞读
理解事务机制是数据库开发的基础。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 夏天的风吹向哪里!
