Innodb内存架构和外存结构

MySQL 官方文档中给出的InnoDB的架构模型

Innodb内存架构和外存结构_第1张图片

内存架构

内存结构主要分为:Buffer Pool、Change Buffer、Adaptive Hash Index 和 Log Buffer

缓冲池(buffer pool)
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页(page)的方式进行管理。但是由于CPU速度和磁盘速度之间的鸿沟(每次io上限肯定不止一页,修改却可能是一两条记录),基于磁盘的数据库系统通常使用缓冲池记录来提高数据库的的整体性能。
缓冲池是主存储器中的一个区域,用于在访问时缓存表和索引数据。缓冲池允许直接从内存中处理常用数据,从而加快处理速度。在专用服务器上,通常会将最多80%的物理内存分配给缓冲池。
为了提高大容量读取操作的效率,缓冲池被分成可以容纳多行的页(page)。为了提高缓存管理的效率,缓冲池被实现为链接的页链表(linked list of pages);使用**LRU**算法的变体,很少使用的数据在缓存中老化(aged out)。
在数据库中进行读取操作,首先将从磁盘中读到的页放在缓冲池中,下次再读相同的页中时,首先判断该页是否在缓冲池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。否则,读取磁盘上的页。
具体来看,缓冲池中缓存的数据页类型有:索引页、数据页、undo页、更改缓冲区(change buffer)、自适应HASH索引(adaptive hash index)、锁信息(lock info)、数据字典信息等。
Innodb内存架构和外存结构_第2张图片

日志缓冲区
日志缓冲区是保存要写入磁盘上日志文件的数据的内存区域,即redo log buffer
当缓冲池中的页的版本比磁盘要新时,数据库需要将新版本的页从缓冲池刷新到磁盘。但是如果每次一个页发送变化,就进行刷新,那么性能开销是非常大的,于是InnoDB采用了Write Ahead Log策略,即当事务提交时,先写redo log,然后再择时将脏页(在内存中被修改过的页称为脏数据页)写入磁盘。如果发生宕机导致数据丢失,就通过重做日志进行数据恢复。
日志缓冲区大小由 innodb_log_buffer_size 变量定义,默认大小为16MB。日志缓冲区的内容会定期刷新到磁盘。大容量的日志缓冲区使大的事务能够运行,而无需在事务提交之前将重做日志数据写入磁盘。因此,如果有更新,插入或删除许多行的事务,则增加日志缓冲区的大小可以节省磁盘I/O。

innodb_log_buffer_sizeInnoDB
用于写入磁盘上的日志文件的缓冲区的大小(以字节为单位)。这就是定义我们文章标题的Log Buffer大小的参数。随着32KB和64KBinnodb_page_size值的引入,默认值从8MB更改为16MB。大型日志缓冲区使大型事务能够运行,而无需在事务提交之前将日志写入磁盘。因此,如果您有更新、插入或删除许多行的事务,则增大日志缓冲区可以节省磁盘 I/O。

set persist innodb_log_buffer_size =33554432;

innodb_flush_log_at_trx_commit
变量控制如何写入日志缓冲区的内容并刷新到磁盘。该参数默认值为1,表示事务提交必须进行一次fsync操作,还可以设置为0和2。0表示事务提交时不进行写入重做日志操作,该操作只在主线程中完成,2表示提交时写入重做日志,但是只写入文件系统缓存,不进行fsync操作。由此可见,设置为0时,性能最高,但是丧失了事务的一致性。
innodb_flush_log_at_timeout 变量控制日志刷新频率。

磁盘存储架构

InnoDB的硬盘存储架构主要分为几大部分组成,包括表空间数据表数据字典双写缓冲区更改缓冲区Undo LogsRedo Log

逻辑存储结构

表空间(Tablespace)
表空间可以看做是InnoDB引擎存储结构的最高层,所有的数据都存放在表空间当中
表空间是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有一个或多个段,但是一个段只能属于一个表空间。表空间数据库由一个或多个表空间组成,表空间从管理上可以划分为系统表空间 (System tablespace)、独立表空间(File-per-table tablespace)、撤销表空间(Undo Tablespace)和临时表空间(Temporary Tablespace)等。

段(segment)

段其实不对应表空间中某一个连续的物理区域,而是一个逻辑上的概念,由若干个零散的页面以及一些完整的区组成。
表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的(index organized),因此数据即索引,索引即数据。数据段即为B+树的页节点(leaf node segment),索引段即为B+树的非页节点(non-leaf node segment)。

区(extent)
区(extent)是由64个物理地址上连续的页组成的,默认情况下,每个页大小为16KB,即每个区的大小为1MB
但是当用户启用参数innodb_file_per_talbe后,创建的表默认大小为96KB。表是由区组成,那么默认大小应该是1M才对呀?这是因为在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。这样的好处是,对于一些小表,可以在开始时申请较少的空间,节省磁盘容量开销。
基于此区可以划分为四种区
1.空闲的区(FREE): 现在还没有用到这个区中的任何页面。
2.有剩余空间的碎片区(FREE_FRAG): 表示碎片区中还有可用的页面。
3.没有剩余空间的碎片区(FULL_FRAG)︰表示碎片区中的所有页面都被使用,没有空闲页面。
4.附属于某个段的区(FSEG):每一个索引都可以分为叶子节点段和非叶子节点段。

页(page)
页是InnoDB磁盘管理的最小单位,数据表中的实际每一行数据也是存储在页当中。在上一篇中,我们讲到InnoDB内部缓冲池的操作,都是基于对页的操作。
页的大小,可以通过参数 innodb_page_size 进行调整,可以设定为4K、8K、16K,默认为16K。

行(row)
InnoDB存储引擎是面向行的(row-oriented),也就是说数据的存放按行进行存放。每个页中可以存放多行记录。

补充:独立表空间和系统表空间

独立表空间,即每张表有一个独立的表空间,也就是数据和索引信息都会保存在自己的表空间中。独立的表空间(即:单表)可以在不同的数据库之间进行迁移
空间可以回收(DROPTABLE操作可自动回收表空间;其他情况,表空间不能自己回收)。如果对于统计分析或是日志表,删除大量数据后可以通过: alter table TableName engine=innodb;回收不用的空间。对于使用独立表空间的表,不管怎么删除,表空间的碎片影响性能不会太严重,而且还有机会处理。

系统表空间
整个MySQL进程只有一个系统表空间,在系统表空间中会额外记录一些有关整个系统信息的页面,这部分是独立表空间中没有的。information_schema 和performance_schema 就是在系统表空间中

你可能感兴趣的:(数据库,mysql)