(精华)Mysql之BufferPool_JAVA_流程图_架构图_系统图_数据库
2024-11-03 14:22:20 31 举报
innodb为了减少磁盘的读写,提升性能,引入了缓存。增删改查都是在缓存中进行的,如果想了解innodb是如何利用缓存来提升性能的,就必须进一步了解其缓存核心 -- Innodb Buffer Pool、Change Buffer、DoubleWrite Buffer、RedoLog Buffer
作者其他创作
大纲/内容
文件3.ibd(4K)
缓冲池 innodb buffer pool
数据页
控制块
缓存区(innodb buffer pool)本身是一块内存空间,在多线程并发访问缓存的情况下,为了保证缓存页数据的正确性,可能会对缓存区单实例锁互斥访问,如果缓存区非常大并且多线程并发访问非常高的情况下,单实例缓存区的可能会影响请求的处理速度。缓存区实例innodb为了提高并发性能,引入缓存区实例(innodb_buffer_pool_instances),该值默认为1注:1、缓存区实例有自己的锁/信号量/物理块/逻辑链表,缓存区实例之间没有锁竞争关系;2、所有缓存区实例的空间在数据库启动时分配,数据库关闭后释放;3、缓存页按照哈希函数随机分布到不同的缓存实例中;BufferChunk缓存区实例由多个BufferChunk组成,BufferChunk包含控制块和数据页1、控制块:页面管理信息/互斥锁/页面的状态等数据块控制信息;2、数据页:数据库数据/锁数据/自适应哈希数据,数据页的大小默认为16K;注:InnoDB中的每个数据页都有一个相对应的控制块,用于存储数据页的管理信息控制块1、页面管理的普通信息/互斥锁/页面的状态等;2、空闲链表/LRU链表/FLU链表等链表的管理;3、按照一定的哈希函数快速定位数据页位置;数据页1、用户数据,聚簇索引和非聚簇索引对应的节点数据;2、行锁信息,InnoDB锁过多异常时,可以通过增加BufferPool大小解决;3、自适应哈希,用于缓存热点数据;4、ChangeBuffer缓存;
next
global
...
碎片
Innodb 内存,磁盘架构
ctl
更改操作
已用数据span style=\
undo 表空间(.ibu)
count=6
pre
Header
InnoDB 缓存区概览
插入缓存insert buffer
2M
通过os cache再刷到磁盘
Change Buffer
doublewrite(1M)
内存拷贝
崩溃恢复第二步
索引页index page
自适应哈稀索引
最近最少使用链表(LRU)
独立表空间(.ibd)
ib_logfile0
数据空间管理(无数据页加载)
Log Buffer
undo 001
第一步内存拷贝
更改数据在缓存中直接更改数据页
t1.ibd
Tail
数据空间管理(有数据页加载)
双写缓存区Doublewrite buffer
锁信息lock info
SQL插入/更新/删除
change buffer
第三步,随机写
在脏页数据刷盘时,由于缓存池里面的数据页是16K,而磁盘上面的数据页是4K,意味着要写到4页中去,而这个操作并不是原子的,会存在写入部分页后,系统宕机,数据丢失的情况,即Partial Page Write(部分页写入)。为什么Redo Log无法解决这个问题?redo日志记录的内容包括 存储表空间ID、页号、偏移量和需要更新的值,类似账本,如果部分页数据已经写入了,再使用redo来恢复,可能会出现已经写入的部分页再次被修改的情况。注:redo适合脏页数据还未刷入磁盘时就丢失的情况DoubleWrite为了解决部分页写入的问题,innodb引入了DoubleWrite,包括两个部分。- 内存结构:Doublewrite Buffer内存结构由128个页(Page)构成,大小是2MB。- 磁盘结构:Doublewrite Buffer磁盘结构在系统表空间上是128个页(2个区,extend1和extend2),大小是2MB。DoubleWrite写入过程?当脏页数据需要刷盘时(到这一步时,前面已经写入了redo log了),1、数据页先通过memcpy函数拷贝至内存中的Doublewrite Buffer中。2、Doublewrite Buffer的内存里的数据页,会fsync刷到Doublewrite Buffer的磁盘上,分两次写入磁盘共享表空间中(连续存储,顺序写,性能很高),每次写1MB。3、Doublewrite Buffer的内存里的数据页,再刷到数据磁盘存储.ibd文件上(随机写)注意:1、如第二步前出现问题,可以直接通过redo来恢复,因为数据只在内存中2、如第二步后出现问题,可先从双写缓冲文件中拷贝数据到.idb,然后通过redo来恢复
空闲链表FreeList
未缓存数据页
16K
undo 002.ibu
count=4
通用表空间(.ibd)
内存
ib_16384_0dblwr
中间省略了许多链表节点
BufferChunk3
2、merge操作
Redo Log
为了提升数据库的读写性能,InnoDB为数据库增加了一块连续的内存缓存区,即innodb_buffer_pool,默认大小128M,所有读写操作都发生在这个缓存池内。Change Buffer在 MySQL5.5 之前,叫插入缓冲(Insert Buffer),只针对 INSERT 做了优化;现在对 DELETE 和 UPDATE 也有效,叫做写缓冲(Change Buffer)。
ib_logfile1
双写缓冲文件(Doublewrite buffer)
MySQL5.5后叫做Change Buffer
更改数据不在缓存中则缓存更改操作到Change Buffer中
o_direct
临时表空间(.ibt)
ib_16384_1dblwr
脏数据页span style=\
ibtmp1
Innodb DoubleWrite 双写
缓存区实例之BufferChunk
session
磁盘结构
顺序写
文件4.ibd(4K)
BufferChunk1
system
count=2
磁盘
存储索引和数据
重做日志redolog buffer
空闲数据span style=\
Change Buffer (Insert Buffer)
第二步,顺序写
t2.ibd
缓存区实例2
temp_1.ibt
脏数据链表FLL
t.ibd
BufferChunk2
InnoDB 内存结构
额外内存池
OS Cache
数据空间管理(有数据页更新)
数据字典信息
修改数据数据时,如果对应的数据页不在缓存区,就需要把数据页从磁盘加载到缓存区,然后进行修改。对于写多读少的场景,会产生大量的磁盘IO,影响数据库的性能。因此引入了ChangeBuffer。ChangeBufferChangeBuffer会缓存修改操作(不会立马从磁盘页上加载数据到缓存中),等到后面磁盘数据页真正被加载到缓冲区时,再进行merge操作。变更操作什么时候放入ChangeBuffer?- 修改的是非唯一索引;- SQL语句不需要返回变更后的数据;- 涉及的数据页不在缓存中;ChangeBuffer什么时候合并到原数据页?- 访问变更操作对应的数据页;- InnoDB后台定期Merge;- 数据库BufferPool空间不足;- 数据库正常关闭时;- RedoLog写满时;注:唯一索引的更新,如果内存中没有,也是先加载到内存中,然后更新,不会写入ChangeBuffer
文件1.ibd(4K)
崩溃恢复第一步
count=10
user defined
文件2.ibd(4K)
服务启动时,会分配内存空间,把它划分成若干对控制块和缓存页。此时并没有真实的磁盘页被缓存到缓存中(因为还没有用到),之后随着程序的运行,会不断的有磁盘上的页被缓存到缓存中。空闲链表FreeListInnoDB刚刚启动,缓存区的所有缓存页都是空闲的,每一个缓存页都会被加入到空闲链表中,链表的指针指向控制块font color=\"#e00707\
脏数据页
系统表空间(.ibdata1)
1、未来数据页加载到缓冲区时
数据页data page
前言:innodb为了减少磁盘的读写,提升性能,引入了缓存,增删改查都是在缓存中进行的。如果想了解innodb是如何利用缓存来提升性能的,就必须进一步了解其缓存核心 -- Innodb Buffer Pool、Change Buffer、DoubleWrite Buffer、RedoLog Buffer
缓存区实例1
已缓存数据页
双写缓冲文件
数据页(脏页)
0 条评论
下一页
为你推荐
查看更多