PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。
第23讲:缓冲区管理器
内容1 : 缓冲区概述
内容2 : 缓冲区管理器结构
内容3 : 缓冲区管理器锁
内容4 : 缓冲区管理器如何工作
内容5 : 环形缓冲区
内容6 : 脏块写
缓冲区概述
· 缓冲区结构(存放各种类型的数据块)
数据文件页—表和索引块
可用空间地图块
可见性地图块
缓冲区数组索引--buffer_ids
· Buffer Tag结构
RelFileNode (分别为表对象oid、数据库oid、表空间oid)
页面的fork number (分别为0、1、2)
页面number 示例:
缓冲区标记{(16821、16384、37721)、0、7}
1、标识第七个块中的页
2、其关系的OID和fork号分别为37721和0(0即为存放表数据的文件)
3、该块存放在OID为16384的数据库中,表空间的OID为16821
· Backend进程读数据块到缓冲区
· 写脏块
下面进程工作时会导致脏块写:
· Checkpointer
· background writer
缓冲区管理器结构
· 管理器结构
· 第一层(Buffer Table)
在这一层内置的hash函数将buffer_tags映射到插槽,插槽中记录了buffer_tags和描述层的buffer_id的映射关系。
· 第二层(Buffer Descriptor)
描述层包含了很多重要的信息,包括buffer_tag与缓冲池插槽id的映射关系,访问次数统计,锁等信息。
· Tag
· buffer_id
· refcount (被进程访问过一次加一,被时钟扫描过后减一,为零时可用)
· usage_count
· context_lock and io_in_progress_lock
· Flags
dirty bit
valid bit
io_in_progress bit
· freeNext
· Buffer Descriptors Layer (Loading the first page)
先请求一个缓冲区空间,buffer table层把描述层的buffer_id与buffer_tag进行映射;然后在描述层把buffer_tag与缓冲区id进行映射;最后把数据块读到相应的缓冲区槽中。
· 第三层(Buffer Pool)
缓冲池是存储数据文件页(如表和索引)的简单数组。缓冲池数组的索引称为buffer_ids。
缓冲池被分割成大小为8 KB的插槽,等于页面大小。因此,每个槽可以存储整个页面。缓冲区管理器锁
· Buffer Manager Locks
缓冲区管理器为许多不同的目的使用许多锁
锁是缓冲区管理器同步机制的一部分;它们与任何SQL语句和SQL选项都不相关
· Buffer Table 层的锁
BufMappingLock保护整个缓冲表的数据完整性。它是一个轻量锁,可以在共享和独占模式下使用。在缓冲区表中搜索条目时,后端进程保存共享的BufMappingLock。当插入或删除条目时,后端进程持有独占锁。
· Buffer Descriptor 层锁
每个缓冲区描述符使用两个轻量级锁
· content_lock
· io_in_progress_lock
· content_lock
content_lock是一种典型的强制访问限制的锁。它可以用于共享和独占模式。
当执行下列操作之一时,将获取独占内容锁:
· dml操作
· 物理删除元组或压缩存储页上的可用空间(vacuum和HOT处理)
· 冻结存储页中的元组
· io_in_progress_lock
io_in_progress锁用于等待缓冲区上的I/O完成。当PostgreSQL进程从存储器加载/写入页面数据时,该进程在访问存储器时持有相应描述符的独占io_in_progress锁。
· spinlock
下面显示如何固定缓冲区描述符:
1、获取缓冲区描述符的自旋锁。
2、将其refcount和usage_count的值增加1。
3、松开旋转锁。
下面显示如何将脏位设置为“1”:
1、获取缓冲区描述符的自旋锁。
2、使用按位操作将脏位设置为“1”。
3、松开旋转锁。
缓冲区管理器如何工作
· 访问已存放在缓冲区中的数据块
· 加载数据块到空的缓冲池插槽
· 加载数据块到一个需要释放的缓冲池插槽
· 缓冲区块替换机制
替换页面算法
· 时钟扫描(8.1开始及以后的版本)
· LRU算法(8.1以前的版本)
· 时钟扫描算法
缓冲区描述符显示为蓝色或青色框,框中的数字显示每个描述符的使用计数,每扫描一次则减一,缓冲区每被访问过一次则加一。
Ring Buffer
· Ring Buffer
· Bulk-reading
需要大块的缓冲池时,如果扫描缓冲池时其大小超过(共享缓冲区/4)四分之一的空间时,还没有找到足够的缓冲池,则分配256KB环形缓冲区。
· Bulk-writing
执行下面列出的SQL命令时。在这种情况下,环缓冲区大小为16MB。
COPY FROM command.
CREATE TABLE AS command.
CREATE MATERIALIZED VIEW or REFRESH MATERIALIZED VIEW command.
ALTER TABLE command.
· Vacuum-processing
当自动真空机进行真空处理时。在这种情况下,环缓冲区大小为256 KB。
脏块写
· Flushing Dirty Pages
检查点进程和后台写入进程将脏页刷新到存储区,检查点与后台写进程分离。
检查点进程将检查点记录写入WAL段文件,并在检查点启动时刷新脏页。
后台写进程的作用是减少检查点密集写的影响。后台写进程持续一点一点地刷新脏页,对数据库活动的影响最小。
默认情况下,后台写入程序每200毫秒唤醒一次(由bgwriter_delay定义),并最多刷新为100页(由bgwriter_lru_maxpages 定义)
共享池缓冲区参数设置
· 共享缓冲区相关参数
shared_buffers参数设置 show shared_buffers;
Alter system set shared_buffers=256M;
wal_buffers参数设置 show wal_buffers;
Alter system set wal_buffers =4M;
effective_cache_size 参数设置 show effective_cache_size;
提供可用于磁盘高速缓存的内存量的估计值。它只是一个建议值,而不是确切分配的内存或缓存大小。它不会实际分配内存,而是会告知优化器内核中可用的缓存量。在一个索引的代价估计中,更高的数值会使得索引扫描更可能被使用,更低的数值会使得顺序扫描更可能被使用。在设置这个参数时,还应该考虑PostgreSQL的共享缓冲区以及将被用于PostgreSQL数据文件的内核磁盘缓冲区。默认值是4GB。
以上就是【PostgreSQL从小白到专家】第23讲 - 缓冲区管理 的内容
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。