MySQL innodb引擎深入讲解( 三 )


2、此时缓冲池中的数据页发生了变更 , 还没刷写到磁盘 , 这个数据页称为脏页 。脏页不是实时刷新到磁盘的 , 而是根据你配置的刷写策略进行刷写到磁盘的(
innodb_flush_log_at_trx_commit , 0,1,2三个值) 。如果脏页在往磁盘刷新的时候出现了故障 , 会丢失数据 , 导致事务的持久性得不到保证 。为了避免这种现象 , 当对缓冲池中的数据进行增删改操作时 , 会把增删改记录到redo log buffer当中 , redo log buffer会把数据页的物理变更持久化到磁盘文件中(ib_logfile0/ib_logfile1) 。如果脏页刷新失败 , 就可以通过这两个日志文件进行恢复 。
undo log , 它是用来解决事务的原子性的 , 也称为回滚日志 。用于记录数据被修改前的信息 , 作用包括:提供回滚和MVCC多版本并发控制 。
undo log和redo log的记录物理日志不一样 , 它是逻辑日志 。可以认为当delete一条记录时 , undo log中会记录一条对应的insert记录 , 当update一条记录时 , 它记录一条对应相反的update记录 , 当执行rollback时 , 就可以从undo log中的逻辑记录读取到相应的内容并进行回滚 。
undo log销毁: undo log 在事务执行时产生 , 事务提交时 , 并不会立即删除undo log , 因为这些日子可能用于MVCC 。
undo log存储: undo log 采用段的方式进行管理和记录 , 存放在前面介绍的rollback segment回滚段中 , 内部包含1024个undo log segment 。
MVCCmvcc(multi-Version Concurrency Control),多版本并发控制 , 指维护一个数据的多个版本 , 使得读写操作没有冲突 , 快照读为MySQL实现MVCC提供了一个非阻塞读功能 , MVCC的具体实现 , 还需要依赖于数据库记录中的三个隐式字段 , undo log日志、readView 。

  • 当前读 , 指的是记录的最新版本 , 读取时还要保证其他并发事务不能修改当前记录 , 会对读取的记录进行加锁 。对于我们日常的操作 , 如 select。。。lock in share mode , select。。。for update、update、insert、delete都是一种当前读 。
  • 快照读 , 简单的select(不加锁)就是快照读 , 读取的是记录数据的可见版本 , 有可能是历史数据 , 不加锁是非阻塞读 。
read committed 每次select 都生成一个快照读
repeatable read 开启事务后第一个select语句才是快照读的地方
serializable 快照读会退化为当前读 。
mvcc的实现原理
  • 记录中的隐藏字段 DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID (ibd2sdi stu.ibd查看表空间)
DB_TRX_ID: 最近修改事务ID , 记录插入这条记录或最后一次修改该记录的事务ID
DB_ROLL_PTR: 回滚指针 , 指向这条记录的上一个版本 , 用于配合undo log , 指向上一个 版本
DB_ROW_ID: 隐藏主键 , 如果表结构没有指定主键 , 将会生成该隐藏字段 。
  • undo log 回滚日志 , 在insert、update、delete的时候产生的便于数据回滚的日志 , 当insert的时候 , 产生的undo log日志只在回滚时需要 , 在事务提交后可以立即删除 。而update、delete的时候 , 产生的undo log 日志不仅仅在回滚时需要 , 在快照读时也需要 , 不会立即被删除 。
  • undo log版本链 , 不同事务或相同事务对同一条记录进行修改 , 会导致该记录的undo log生成一条记录版本链表 , 链表的头部是最新的旧记录 , 链表尾部是最早的旧记录 。
  • readView(读视图),就是快照读SQL执行时mvcc提取数据的依据 , 记录并维护系统当前活跃的事务(为提交的)ID , readview中包含了四个核心字段 。
m_ids当前活跃的事务ID集合
min_trx_id: 最小活跃事务id
max_trx_id: 预分配事务ID , 当前最大事务id+1 , 因为事务id是自增的
creator_trx_id: ReadView创建者的事务ID
 
版本链数据访问规则:
trx_id: 表示当前的事务ID
1、trx_id == creator_trx_id? 可以访问读版本-->成立的话,说明数据是当前这个事务更改的
2、trx_id<min_trx_id?可以访问读版本-->成立,说明数据已经提交了 。


推荐阅读