您的位置:首页 > 科技 > 能源 > 境外域名注册_网站ui设计包括哪些原则_培训_广州新闻热点事件

境外域名注册_网站ui设计包括哪些原则_培训_广州新闻热点事件

2024/11/15 22:58:39 来源:https://blog.csdn.net/qq_45875349/article/details/143414255  浏览:    关键词:境外域名注册_网站ui设计包括哪些原则_培训_广州新闻热点事件
境外域名注册_网站ui设计包括哪些原则_培训_广州新闻热点事件

InnoDB架构官方给出的架构图如下图所示。https://dev.mysql.com/doc/refman/8.0/en/innodb-architecture.html

可以看出InnoDB存储引擎主要分为内存结构和磁盘结构。

其中内存结构中主要有:

  • Buffer Pool缓冲池、
  • Change Buffer变更缓冲区
  • adaptive_hash_index 自适应哈希索引
  • Log Buffer日志缓冲区

磁盘结构主要包含:

  • 系统表空间
  • 独立表空间
  • 通用表空间
  • 临时表空间
  • Redo Log
  • 回滚表空间
  • 双写缓存文件

这篇博客先来介绍一下内存结构中的Buffer Pool。


1. 为什么需要内存结构

从MySQL实现的角度来思考这个问题,数据库的作用就是保存数据,用户的真实数据最终都会保存在磁盘上,在查询数据的过程中,如果每次都从磁盘上读取会严重影响效率,为了提高数据的访问效率,InnoDB会把查询到的数据缓存到内存中,当再次查询时,如果目标数据已经存在于内存中,就可以从内存中直接读取,从而大幅提升效率。也就是说磁盘结构中的文件是用来保存数据实现数据持久化的,内存结构是用来缓存数据提升效率的。

2. 缓存池-Buffer Pool

2.1 缓存池的作用

先看一下缓冲池在内存结构中的位置:

缓冲池主要用来缓存被访问的InnoDB表和索引数据页,是主内存中的一片区域,允许直接从内存访问频繁使用的数据从而提高效率。在专用数据库服务器上,通常会将多达80%的物理内存分配给缓冲池。

其次缓冲池不仅缓存了磁盘的数据页,也存储了锁信息、Change Buffer信息、Adaptive hashindex、Double write buffer等信息。如上图所。至于详细的Change Buffer和自适应哈希索引以及双鞋缓冲区等内容后面会详细介绍。

2.2 缓存池是如何组织数据的?

缓冲池组织数据的方式也可以说是缓冲池用到的数据结构,在这之前回顾一下InnoDB表空间的存
诸结构。每个InnoDB表空间在磁盘上对应一个.ibd 文件,其中包含了叶子节点段和非叶子节点段等逻辑段,段中包含了区组,区组中管理着区,区别包含数据页,数据页中包含数据行,每分别对着不同的数据结构目的就是便于数据的管理与高效访问。

缓存池的结构

从缓冲池的概念了解到它是主内存中的一片区域,在专用服务器上会将多达80%的物理内存分配给缓冲池,在这么大的内存空间中如何保证效率就是要解决的问题。

缓冲池也采用与表空间类似的方式对数据进行组织,如下图所示:

  • 缓冲池中包含至少一个 Instances 实例,Instances 是真正的缓冲池的实例对象,内存操作都是在 Instances 中进行的;
  • 每个 Instances 中包含至少一个 Chunk 块,Chunk 是在服务器运行状态下动态调缓冲池进行大小时操作的块大小;
  • 每个块中包含和管理若干个从磁盘加载到内存的 Page 数据页

可以看出缓冲池通过定义不同的数据结构,但最终管理的是每个数据页,这些数据页是从磁盘中加载到内存的,也就是说磁盘中的数据页加载到内存中之后,对应的就是内存中的数据页,并且页与页之间用链表连接。

那么这时就有一个问题,我们知道磁盘中的数据页大小默认是16KB,并且通过头信息中的next_record 记录下一行地址偏移量,在页的结构定义中并没有一个字段用来表示内存中下一页的地址,那么在内存中如何为每个页建立连接呢?

缓存池中页与页之间如何建立联系

由于数据页中没有一个字段用来表示内存中下一页的地址,为了每个数据页在内存中实现链表连接,InnoDB定义了一个叫"控制块"的数据结构,"控制块"中有三个重要的信息分别是:

  • 指向数据页的内存地址。
  • 前一个控制块的内存地址
  • 后一下控制块的内存地址

之后再用一个双向链表管理每个控制块,如下图所示:

为了确定控制块链表的超始位置,专门定义了一个头节点,头节点中包含了三个主要的信息,如图中所示:

  • 第一个控制块的内存地址
  • 最后一个控制块的内存地址
  • 链表中控制块的数量

通过遍历控制块链表就可以遍历内存中的数据页 。

2.3 Buffer Pool的大小可以设置吗?

可以通过系统变量 innodb_buffer_pool_size 进行设置,设置时以字节为单位:默认值为134217728 字节,即 128MB;最大值取决于CPU架构和操作系统,在32位系统上最大值为4294967295(2^32-1),在64位系统上最大值为 18446744073709551615(2^64-1)

这里需要注意的是, InnoDB 为"控制块"分配额外的内存空间,也就是说"控制块"并不会占用Buffer Pool的内存空间,所以实际分配的内存总空间比指定的缓冲池大小大 10%左右。

缓冲池设置的值越大,在多次访问相同表数据时,磁盘I/0就会越少,因为数据都已经缓存在内存中,所以效率也就越高,但是服务器启动时初始化时间会比较长。 

2.4 Buffer Pool中的Instance的数量如何确定?

通过系统变量 innodb_buffer_pool_instances 可以设置缓冲池实例的个数,默认是1,最大值 64;

当缓冲池的大小小于 1GB 时,无论指定 innodb_buffer_pool_instances 数是多少都会自动调整为 1;
当缓冲池的大小大于 1GB 时,innodb_buffer_pool_instances 默认值为 8,也可以指定大于1的值来设置 Instances 的数量,多个 Instances 可以提升服务器的并发性;

为了获得最佳的效率,通过指定innodb_buffer_pool_instances 和innodb_buffer_pool_size 为每个缓冲池实例设置至少为 1GB 的空间;

查看Instances的数量可以使用下面的SQL语句,默认为1个

2.5 Instances中的Chunk的数量如何确定?

Chunk 大小可以通过系统变量 innodb_buffer_pool_chunk_size 进行设置,默认为134217728 字节即 128MB ;在设置大小时可以以 1048576 字节即 1MB 为单位增加或减少;块中包含的数据页数取决于 innodb_page_size;

更改 innodb_buffer_pool_chunk_size 的值时注意以下条件:

  • 如果 innodb_buffer_pool_chunk_size*innodb_buffer_pool instances 大于当前缓冲池大小,innodb_buffer_pool_chunk_size 将被截断为innodb_buffer_pool size / innodb_buffer _pool instances .
  • 缓冲池大小必须始终等于或倍数于innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances。如果修改了innodb_buffer_pool_chunk_size 的值,导致不符合这个规则,那么在缓冲池初始化时innodb_buffer_pool_size 会自动四舍五入为等于或者倍数于innodb_buffer_pool_chunk size *innodb_buffer_pool_instances 的值

2.6 控制块与Page是如何初始化的?

前面介绍了 chunk 中管理的是具体的数据页,当缓冲池初始化完成时会把每个数据页所占用的内存空间和对应的控制块分配好,只不是没有从磁盘加载数据时,内存中的数据页是空的而已。

当缓冲池初始化的过程中,会为 Chunk 分配置内存空间,此时"控制块"会从 Chunk 的内存空间从左向右进行初始化,数据页所占的内存会从 chunk 的内存空间从右向左进行初始化,当所剩的内存空间不够一组"控制块"+数据页所占的空间时,就会产生碎片空间,如果适好够用则不会出现碎片空间,如下图所示:

内存初始化完成之后,建立控制块与内存中缓冲数据页之间的关系,从左开始第一个控制块指向第一个缓冲数据页的内存地址 

当前从磁盘中加载数据页时,就可以在把数据缓存在内存中的空闲数据页中

2.7 缓存池中的页是如何进行管理的?

当缓冲池初始化完成后,缓冲池中的数据页只是被分配了内存空间,并没有真实的数据,当用户进行数据查询时真实的数据从磁盘加载到内存中并分配一个内存中的数据页,这时内存中数据页的状态从空间变成了有实际的数据;当用户修改数据时,并不是直接修改磁盘中的数据页,而是修改内存中数据页中的数据页,这时内存中数据页的状态从有实际数据变成了被修改。

在缓冲池中采用三个链表维护内存页,这三个链表也对应着内存中页的三种状态,分别是:

  • Free 未使用的页,也可以称做空闲页;。
  • Clean 已使用但未修改的页,也可以称做干净页;
  • Dirty 已修改的页,也可以称做脏页。

对应的三个链表分别是 Free List、LRU List和 Flush List:

  • Free List:只管理Free 页
  • LRU List:管理 Clean页和Dirty页
  • Flush List:只管理Dirty页

  • Free List:管理着空闲的也就是没有被使用的内存页,当执行查询操作时,如果对应的页已经在 buffer pool 中则直接返回数据,如果没有且 Free List 不为空,则从磁盘中查询对应的数据并存到 Free List 的某一页中,然后把这个页从 Free List 中移除并放入 LRU List中。
  • LRU List:管理所有从磁盘中读取的数据页,包括未被修改的和已被修改的数据页,并根据LRU算法对链表中的页节点进行维护与淘汰。当数据库刚启动时LRU List 是空的,这时从内存中申请到的页都存放在 Free List 中,当数据从磁盘读取到缓冲池时,首先从 Free List 中查找是否有可用的空闲页,如果有则把该页从 Free List中删除并加入到 LRU List;如果没有,则根据 LRU 算法淘汰 LRU List 末尾的页,并将该内存空间分配给新数据页;
  • Flush List:当 LRU List 中的页被修改后会被标识为脏页(Dirty page),并把脏页加入到Flush List 中,在这种情况下,数据库会通过刷盘机制把 Flush List 中的脏页刷回磁盘; Flush List 是一个专门用来管理脏页的列表。脏页既存在于 LRU List 中,也存在于Flush List 中,LRU List 用来管理缓冲池中页的可用性, Flush List 用来管理要被刷回磁盘的页,二者互不影响。Flush List 中的脏页在执行了刷盘操作后会将空间还给 FreeList。

2.8 缓存池的淘汰策略

缓冲池淘汰策略采用变形的最近最少使用(LRU)算法(在原来LRU算法的基础做了修改),以下出现的LRU算法指的是LRU变形算法。

缓冲池使用 LRU算法管理链表,当有新页面添加到缓冲池时,最近最少使用的页将被淘汰,并将新页添加到列表的中间,这种中点插入策略将列表视为两个子列表:

  • 链表头部,是存放最近访问的新页(年轻页)子列表;
  • 链表尾部,是存放最近较少访问的旧页子列表。

经常使用的页保存在新子列表中,较少使用的页保存在旧子列表中,随着时间的推移,旧子列表中的页将会逐渐被淘汰。默认情况下,算法的执行过程如下:

  • 缓冲池总容量的 5/8 用于新子列表,3/8用于旧子列表,。
  • 列表的中间插入点是新子列表的尾部与旧子列表头部的交界;
  • 当一个页被读入缓冲池时,首先插入到中间做为旧子列表的头节点
  • 当访问的页在旧子列表中时,把被访问的页移动到新子列表的头部,使其成为“新"页;
  • 数据库运行的过程中,缓冲池中被访问页面的位置不断更新,未访问的页面向列表的尾部移动,从而逐渐"变老"最终超出缓冲池容量的页从旧子列表的尾部被淘汰。 

为什么把页插入到LRUList中间为不是直接插入新子列表的头部?

因为InnoDB在读取页时,可能会发生"预读",预读的意思是InnoDB根据当前访问的记录自动推断后面可能会访问哪个页,并把他们提前加载到内存中,从而提高以后查询的效率,预读的页以并不一定会被真正的读取,从中间点插入可以使其尽快被淘汰。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com