第8章的摘要:书中的“缓冲经理”“ Postgresql的内部”部分2部分
#postgres #database #apacheage #agenssql

此博客旨在帮助您理解章节的内侧概念:8 [Buffer Manager] The Internals of PostgreSQL

注意:确保您对
有透彻的了解 在我们进入第8章第2章之前,Chapter 8 Part-1和Posttresql的基础是我们探索的基础。

所以,让我们继续:

缓冲区描述符层

  • 缓冲区描述符的集合形成了数组。在本文档中,数组称为缓冲区描述符层

  • 当PostgreSQL Server启动时,所有缓冲区描述符的状态均为 empty 。在PostgreSQL中,这些描述符包含一个链接列表,称为 freelist

Buffer Manager初始状态 PostgreSQL中的如下图:

Image description

在PostgreSQL中加载第一页如下图:

Image description

缓冲池

  • 缓冲池是一个简单的数组,它存储数据文件页面,例如表和索引。缓冲池阵列的索引称为 buffer_ids

  • 缓冲池插槽大小为 8 kb ,等于页面的大小。因此,每个插槽都可以存储整个页面。


缓冲管理器锁

缓冲桌锁

  • bufmappinglock 保护整个缓冲区表的数据完整性。

  • 轻巧可以在共享模式和独家模式中使用的锁。在缓冲表中搜索条目时,后端进程保存共享 bufmappinglock

  • bufmappinglock分为分区以减少缓冲表中的争论(默认值为 128个分区)。每个bufmappinglock分区守护相应的哈希桶插槽的一部分。

两个过程同时以独家模式以bufmappinglock的相应分区插入了新的数据条目在PostgreSQL中插入:

Image description

锁定每个缓冲区描述符

  • 每个缓冲区描述符都使用两个轻量重量锁, content_lock io_in_progress_lock ,控制对相应缓冲池中存储的页面的访问投币口。当检查或更改自己的字段的值时,使用 Spinlock

content_lock

  • content_lock是强制执行访问限制的典型锁。它可以用于共享独家模式。

  • 阅读页面时,后端过程获取了存储页面的缓冲区描述符的共享 content_lock

  • 在以下方案中获取独家content_lock

  1. 将行(元组)插入存储的页面。
  2. 更改存储页面内的t_xmin/t_xmax字段。
  3. 在存储的页面上删除物理或压实的自由空间。
  4. 存储页面中的冻结元素。

io_in_progress_lock

  • io_in_progress锁用于在缓冲区上等待 i/o 完成。

  • 当postgresql加载/从/到存储中写页数据数据时,该过程在访问存储时包含相应描述符的独家 io_in_progress lock

Spinlock

  • 检查或更改了标志或其他字段(例如重新数和usage_count)时,使用 spinlock

  • 两个 spinlock使用的特定示例如下:

1. The following shows how to pin the buffer descriptor:

  • 获取缓冲区描述符的单锁。
  • 将其重新计算的值和USAGE_COUNT的值增加1。
  • 释放自旋锁。

2. The following shows how to set the dirty bit to '1':

  • 获取缓冲区描述符的单锁。
  • 使用位操作将脏点设置为“ 1”。
  • 释放自旋锁。

缓冲区管理器的工作方式

  • 当后端进程想要访问所需的页面时,它将调用 deadBufferextended 函数。

  • 读取功能的行为取决于三个逻辑案例。

1。访问存储在缓冲池中的页面

  • 首先,描述了最简单的情况,即所需的页面已经存储在 buffer池中

  • 在这种情况下,缓冲区管理器执行以下步骤:

  • (1)创建所需页面的buffer_tag(在此示例中,buffer_tag是'tag_c'),并使用哈希函数来计算包含创建buffer_tag的关联条目的哈希桶插槽。

  • (2)获取涵盖共享模式下获得的哈希桶插槽的bufmappinglock分区(此锁将在步骤(5)中发布)。

  • (3)查找标签为'tag_c'的条目,并从条目中获取Buffer_ID。在此示例中,Buffer_ID为2。

  • (4)固定buffer_id 2的缓冲区描述符,即描述符的重新数和usage_count增加了1。

  • (5)释放bufmappinglock。

  • (6)使用Buffer_ID2。

  • 访问缓冲池插槽

访问postgresql中存储在缓冲池中的页面如下图:

Image description

  • 从缓冲池插槽中的页面读取行时,PostgreSQL进程将获取相应的缓冲区描述符的共享 content_lock 。因此,缓冲池可以通过多个过程读取插槽。

  • 在插入(并更新或删除)行插入页面时,Postgres进程获取相应的缓冲区描述符的 exclusive content_lock 页面的位必须设置为'1')。

  • 访问页面后,相应的缓冲区描述符的重新数值减少了1

2。从存储到空插槽

加载页面
  • 在第二种情况下,假设所需的页面是不是缓冲池中的,而自由主义者具有免费元素(空描述符)。

  • 在这种情况下,缓冲区管理器执行以下步骤:

  • (1)查找缓冲台(我们假设找不到)。

  1. 创建所需页面的buffer_tag(在此示例中,buffer_tag为'tag_e')并计算哈希桶插槽。
  2. 以共享模式获取bufmappinglock分区。
  3. 查找缓冲表(未根据假设找到)。
  4. 释放bufmappinglock。
  • (2)从FreeList获取空的缓冲区描述符,然后将其固定。在此示例中,获得的描述符的Buffer_ID为4。

  • (3)以独家模式获取Bufmappinglock分区(该锁将在步骤(6)中发布)。

  • (4)创建一个新的数据条目,该输入包括buffer_tag'tag_e'和buffer_id 4;将创建的条目插入缓冲区表。

  • (5)使用Buffer_ID 4加载所需的页面数据从存储到缓冲池插槽,如下所示:

  1. 获得相应描述符的独家io_in_progress_lock。

  2. 将相应描述符的io_in_progress位设置为'1,以防止其他过程访问。

  3. 加载所需的页面数据从存储到缓冲池插槽。

  4. 更改相应描述符的状态; io_in_progress位设置为'0',有效位设置为'1'。

  5. 释放io_in_progress_lock。

  • (6)释放bufmappinglock。
  • (7)使用Buffer_ID访问缓冲池插槽4。

在PostgreSQL中从存储中加载页面从存储到空插槽如下图:

Image description


我希望,这个博客帮助您理解了postresql中缓冲经理的内侧概念。

查看Chapter : 8 Part-3

的摘要

如果您想了解PostgreSQL In-Depth