mysql存储原理(3)InnoDB存储模型

我们在查询得时候,会先通过索引定位到对应得数据页,然后检测数据页是否在缓冲池中,如果在就直接返回,如果不在就去聚簇索引中通过磁盘IO读取对应得数据页并放入缓冲池,一个数据页会包含多个数据行,缓存池通过LRU算法对数据页进行管理,最频繁使用得数据页排在列表前面,不进场使用得排在队尾,当缓冲池满了的时候会淘汰队尾的数据页,从磁盘鑫读取到的数据页不会放在队列的头部,而是放在中间,这个中间位置可以通过参数进行修改。

InnoDB在更新数据库的时候使用的是WAL技术,这个日志就是redolog用来保证数据库宕机后可以通过该文件进行恢复,这个文件一般只会顺序写,只有在数据库启动的时候才会读取redolog文件,看是否需要进行恢复,该文件记录了对某个数据页的物理操作,

redolog 不是无限大的,他的大小是可以配置的,并且是循环使用的,例如配置大小为 4G ,一共 4 个文件,每个文件 1G 。首先从第一个文件开始顺序写,写到第四个文件后在从第一个文件开始写,类似一个环,用一个后台线程把 redolog 里的数据同步到聚簇索引上的数据页上。写入 redolog 的时候不能将没有同步到数据页上的记录覆盖,如果碰到这种情况会停下来先进行数据页同步然后在继续写入 redolog 。另外执行更新操作的时候,会先更新缓冲池里的数据页,然后写入 redolog , 这个时候真正存储数据的地方还没有更新,也就是说这时候缓冲池中的数据页和磁盘不一致,这种数据页称为脏页,当脏页由于内存不足或者其他原因需要丢弃的时候,一定要先将该脏页对应的redolog 刷新到磁盘里的真实数据页,不然下次查询的时候由于 redolog 没有同步到磁盘,而查询直接通过索引定位到数据页就会查询出脏数据。

更新的时候先从磁盘或者缓冲池中读取对应的数据页,然后对数据页里的数据进行更改并生成 redolog 到对应的缓冲池(redolog buffer)进行缓存,当事务提交的时候将缓存写入到 redolog 的物理磁盘文件上。这里由于操作系统的文件写入 InnoDB 并没有使用 O_DIRECT 直接写入到文件,为了保证性能而是先写入操作系统的缓存,之后在进行 flush ,所以事务提交的时候 InnoDB 需要在调用一次 fsync 的系统调用来确保数据落盘。为了提高性能 InnoDB 可以通过参数 innodb_flush_log_at_trx_commit 来控制事务提交时是否强制刷盘。默认为 1 ,事务每次提交都需要调用 fsync 进行刷盘,0 表示事务提交的时候不会调用  redolog 的文件写入,通过后台线程每秒同步一次,2 表示事务提交的时候会写入文件但是只保证写入操作系统缓存,不进行 fsync 操作。redolog 文件只会顺序写,所以磁盘操作性能不会太慢,所以建议生产环境都设置为 1 ,以防止数据库宕机导致数据丢失。

在执行更新逻辑的时候还会写入另外一个日志:undolog 。这个文件存储在共享表空间中,也就是即使打开了 innodb_file_per_table 参数,所有的表的 undolog 都存储在同一个文件里。该文件主要用来做事务回滚和 MVCC 。undolog 是逻辑日志,也就是他不是记录的将物理的数据页恢复到之前的状态,而是记录的和原 sql 相反的 sql , 例如 insert 对应 delete , delete 对应 insert ,update 对应另外一个 update 。事务回滚很好理解,执行相反的操作回滚到之前的状态,而 MVCC 是指镜像读,当一个事务需要查询某条记录,而该记录已经被其他事务修改,但该事务还没提交,而当前事务可以通过 undolog 计算到之前的值。这里我们只需要知道和 redolog 一样, undolog 也是需要在执行 update 语句的时候在事务提交前需要写入到文件的。另外 undolog 的写入也会有对应的 redolog ,因为 undolog 也需要持久化,通过 WAL 可以提高效率。这里可以总结下,在事务提交的时候要保证 redolog 写入到文件里,而这个 redolog 包含 主键索引上的数据页的修改,以及共享表空间的回滚段中 undolog 的插入。另外 undolog 的清理通过一个后台线程定时处理,清理的时候需要判断该 undolog 是否所有的事务都不会用到。

熟悉 MySQL 的都知道,他通过 binlog 来进行高可用,也就是通过 binlog 来将数据同步到集群内其他的 MySQL 实例。binlog 和 redolog 的区别是,他是在存储引擎上层 Server 层写入的,他记录的是逻辑操作,也就是对应的 sql ,而 redolog 记录的底层某个数据页的物理操作,redolog 是循环写的,而binlog 是追加写的,不会覆盖以前写的数据。而binlog 也需要在事务提交前写入文件。binlog 的写入页需要通过 fsync 来保证落盘,为了提高 tps ,MySQL 可以通过参数  sync_binlog 来控制是否需要同步刷盘,该策略会影响当主库宕机后备库数据可能并没有完全同步到主库数据。由于事务的原子性,需要保证事务提交的时候 redolog 和 binlog 都写入成功,所以 MySQL 执行层采用了两阶段提交来保证 redolog 和 binlog 都写入成功后才 commit,如果一方失败则会进行回滚。

  • 1.分配事务 ID ,开启事务,获取锁,没有获取到锁则等待。

  • 2.执行器先通过存储引擎找到 id = 1 的数据页,如果缓冲池有则直接取出,没有则去主键索引上取出对应的数据页放入缓冲池。

  • 3.在数据页内找到 id = 1 这行记录,取出,将 age 改为 30 然后写入内存

  • 4.生成 redolog undolog 到内存,redolog 状态为 prepare

  • 5.将 redolog undolog 写入文件并调用 fsync

  • 6.server 层生成 binlog 并写入文件调用 fsync

  • 7.事务提交,将 redolog 的状态改为 commited 释放锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值