• Mysql-持久性实现


    Mysql数据增删改的一个大致过程如下:

    • 先从索引中找到数据所在的表空间ID以及在表空间中的数据页的页号
    • 然后通过表空间ID+页号作为Key,去缓存页哈希表中查找Buffer Pool是否已经加载了这个缓存页。如果已经加载了缓存页,就直接读取这个缓存页。
    • 如果没有这个缓存页,就需要从磁盘表空间中加载数据页到内存,此时需要从Free链表获取一个空闲页加入LRU链表中,加载的数据页就会放到这个空闲的缓存页中。
    • 接着在对应的缓存页中执行增删改操作,被修改过的缓存页就变成了脏页,会加入Flush链表中。
    • 最后,后台线程会在一些时机将LRU链表尾部的冷数据和Flush链表中的脏页刷盘。

    这个过程有个最大的问题就是,数据修改且事务已经提交了,但只是修改了Buffer Pool中的缓存页,数据并没有持久化到磁盘,如果此时数据库宕机,那数据不就丢失了!

    但是也不可能每次事务一提交,就把事务更新的缓存页都刷新回磁盘文件里去,因为缓存页刷新到磁盘文件里是随机磁盘读写,性能是很差的,这会导致数据库性能和并发能力都很差。

    所以此时就引入了一个 redo log 机制,在提交事务的时候,先把对缓存页的修改以日志的形式,写到 redo log 文件里去,而且保证写入文件成功才算事务提交成功。而且redo log顺序写入磁盘文件,每次都是追加到磁盘文件末尾去,速度是非常快的。之后再在某个时机将修改的缓存页刷入磁盘,这时就算数据库宕机,也可以利用redo log来恢复数据。

    随机磁盘读写:一个事务里的SQL可能牵涉到多个数据页的修改,而这些数据页可能不是相邻的,也就是属于随机IO。显然操作随机IO,速度会比较慢。

    参考:https://juejin.cn/post/6976060698757595150

  • 相关阅读:
    yaml简单模板
    goland之基础使用 X
    redis之性能优化 X
    定时任务管理之qinglong X
    golang数据库操作之gorm X
    低代码平台汇总 X
    kafka之介绍 X
    ClickHouse之基础 X
    gitlab安装与基本使用 X
    ClickHouse之物化MySQL X
  • 原文地址:https://www.cnblogs.com/kenLoong/p/15473664.html
Copyright © 2020-2023  润新知