mysql 事务原理
redo log
重做日志,记录事务提交时对数据页的修改,用来实现事务的持久性.
事务提交时,数据会在缓冲区脏页更新,然后定时刷新到磁盘ibd文件,这个持久化过程是随机写操作,耗时比较久,如果刷新脏页到磁盘文件这个过程因为系统故障断电停机等失败了,会导致数据没有持久化.
引入redolog 事务提交时,会在内存刷入更新记录到redolog buffer,然后把buffer记录到磁盘redo log日志文件,这个是顺序写操作,性能比较快,当从脏页刷回磁盘操作失败时,会在redolog中找到操作记录重新执行.
undo log回滚日志
解决事务的原子性,事务回滚时会执行undo log中的记录.
是逻辑日志,如执行了insert操作就log会生成一条对应的delete记录,update生成一条update,delete生成insert,总之是保存一条恢复到原有状态的记录
MVCC
当前读:读取记录的最新版本,读取时需保证其他并发事务不能修改当前记录,会对读取记录加锁
select xxx lock in share mode,select xxx for update/ update/ insert/delete都是当前读
快照读
简单select 语句 不加锁,读取的是数据的可见版本,可能是历史数据,不加锁,非阻塞
Read Uncommit:select 当前读
Read Commited:select 快照读,每次查询读取数据的快照
Repeatable Read: 开启事务的第一个select 是快照读,后续select 是读取的这个快照
Serializable:快照读退化未当前读
mvcc 多版本并发控制,维护数据多个版本,使得读取操作没有冲突.
mvcc具体实现依赖数据库记录的三个隐藏字段 和 undo log 以及readView
1. 记录的隐藏字段
db_trx_id:最近修改事务id
db_roll_ptr:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本
db_row_id:隐藏主键,没有指定主键会生成此字段
2.undo日志版本链 是一个链表 头部是最新数据,尾部是最老数据
3.readView 由几部分组成:
当前执行事务的列表,最小事务id,最大事务id(预分配事务id),创建readView的事务id
通过undolog的db_trx_id与readView的4个属性比较,来确认是否可匹配此条数据
mvcc + 锁保证事务隔离性
undolog 和redolog 实现事务的一致性