内存架构
注意缓冲池的底层是通过链表数据结构来管理Page
change Buffer (更改缓冲区) : 其中存储的是,如果数据不存在于Buffer pool【缓冲池】,不会直接从磁盘中取数据,那么他会先将对这些数据的操作存放在【更改缓冲区】,直到数据到达Buffer pool后,InnoDB 会将 Change Buffer 中的操作应用到内存页,并写入磁盘。
InnoDB存储引擎中的更改缓冲区 适用条件:更改缓冲区仅适用于非唯一索引的写操作(insert ,update,delete)。
为什么只支持非唯一索引?
唯一索引必须即时检查唯一性约束,需要从磁盘读取数据页进行验证,无法避免磁盘io->无法使用change Buffer优化
Change Buffer的意义是什么?
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引数中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘io。有了ChangeBuffer,我们可以在缓冲池进行合并操作,减少磁盘io
日志缓冲区的核心内容(实际存储什么?)
redo log:
不存储原始数据:日志缓冲区不会保存被删除数据的完整副本(如 id=5 的全部字段值)。不存储 SQL 指令:不会记录 DELETE FROM table WHERE id=5 这条 SQL。
真实存储的是:
数据页的物理变化描述(最小粒度的字节级修改)。例如:
【页号: 128】在偏移量 0x1F4 处:
原 16 字节: "id=5,name=Alice,age=25"
修改为: 标记为"已删除" (0xFFFF...)
在 InnoDB 中,Undo Log 存储的是被修改前的原始数据(物理副本),而非 SQL 语句。这种设计是 MVCC 机制高效运行的核心基础
磁盘结构
文件表空间: 当创建一张表的时候,也会生成对应的文件表空间【ibd文件】,存储表数据,存储索引
创建通用表空间,并且指定创建的表存放在该表空间中
数据是如何从内存->磁盘?
后台线程的作用是:将InnoDB存储引擎缓冲池中的数据,在合适的时期刷新到磁盘文件中
AIO:异步非阻塞IO
、
master Thread
缓冲池脏页比例监控( 触发刷新脏页)
日志缓冲区刷新,合并Change Buffer,Undo页回收
- 调度逻辑:每秒/每10秒循环检查,生成任务给其他线程执行。
Page Cleaner Thread(刷脏线程)他只是识别哪些脏页需要刷新到磁盘,真正执行的是IO Thread中的write thread;
核心职责:专门负责将缓冲池(Buffer Pool)中的脏页刷到磁盘,包括:
数据页 → 数据文件(.ibd)
日志相关 → Redo Log
关键特性:
多线程并发刷脏(innodb_page_cleaners,默认4个)
异步操作不阻塞用户线程
IO Thread(读写线程)
Read Thread 从磁盘读取数据页到 Buffer Pool
Write Thread 将脏页/日志写入磁盘数据文件
Insert Buffer Thread 合并 Change Buffer 到二级索引
Log Thread 专刷 Redo Log 到磁盘文件
Purge Thread(清理线程)
核心职责:清理无效的 Undo 日志(提交事务后不再需要的旧版本数据)。
事务原理
redo log & undo log
redo log
流程:
当用户开启事务执行写操作时,InnoDB 会优先检查目标数据页是否已在缓冲池(Buffer Pool)中:若存在,则直接修改内存中的数据页生成脏页;若不存在(尤其是针对非唯一二级索引的修改),则将这些变更暂存至内存中的更改缓冲区(Change Buffer)。事务提交的关键时刻,系统会强制将包含数据页变更和 Change Buffer 操作的 Redo 日志写入日志缓冲区(Redo Log Buffer),并由 IO 写线程立即刷入磁盘的 Redo 日志文件——这保证了事务的持久性(即使崩溃也不丢失)。此后当用户首次查询触发数据页加载到缓冲池时,InnoDB 自动合并 Change Buffer 中的待执行操作到该数据页(生成脏页),最终由 Page Cleaner 线程扫描到这些老化的脏页后,指挥 IO 写线程通过双写缓冲区安全写入磁盘数据文件。
undo Log
MVCC
在 InnoDB 中,当前读能获取到最新数据的本质在于其绕过 MVCC 机制,通过锁机制强制访问数据页最新物理状态
三个隐式字段
undo log
在更新数据之前将数据先写入undo log日志;
不同事物或者相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最新的旧数据,链表的尾部是最早的旧数据
在 InnoDB 中,已提交事务的 Undo Log 不会立即从链中删除,而是通过异步的 Purge 机制延迟清理。
readview
快照读 读取版本链中的那条数据呢? readView决定
在 InnoDB 的 MVCC 机制中,已提交事务的 ID 会立即从 ReadView 的活跃列表 m_ids 中移除,但其修改产生的 Undo Log 数据会延迟清除
RC (读已提交)
目的:了解事务5两次快照读,读到的是什么数据;
首先是第一次快照读:
事务5中没有DML操作,所以记录中为事务id为4的数据,观察发现trx_id = 4不符合版本连数据访问规则中的任何一条,于是开始判断事务id为3的数据,发现仍然没有符合条件,然后判断2,1;
RR (可重复读)
同理;