文档章节

PostgreSQL在启动时如何分配共享缓存

有理想的猪
 有理想的猪
发布于 07/22 13:17
字数 782
阅读 18
收藏 0

相信很多人知道 shared_buffers 这个参数,它设置共享缓存的大小,本篇简单讲一下它是怎样分配的。

1、参数设置(src/backend/utils/misc/guc.c)

	/*
	 * We sometimes multiply the number of shared buffers by two without
	 * checking for overflow, so we mustn't allow more than INT_MAX / 2.
	 */
	{
		{"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
			gettext_noop("Sets the number of shared memory buffers used by the server."),
			NULL,
			GUC_UNIT_BLOCKS
		},
		&NBuffers,
		1024, 16, INT_MAX / 2,
		NULL, NULL, NULL
	},

可以看到,这个参数在内核中并不是实际内存的大小,而是块数GUC_UNIT_BLOCKS(这个有兴趣可以读guc代码,看起来也有必要单独写一篇。)

假设我们设置512M,编译时选择块尺寸8k,那么应该分配块数是 51210241024/8192,总共65536个块。

2、共享内存的分配

实际上,共享缓存只是共享内存的一部分,这不是我们本篇的重点,所以只是简单一提。数据库启动时计算总共享内存的大小,然后从OS申请(src/backend/storage/buffer/buf_init.c):

Size
BufferShmemSize(void)
{
	Size		size = 0;

	/* size of buffer descriptors */
	size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
	/* to allow aligning buffer descriptors */
	size = add_size(size, PG_CACHE_LINE_SIZE);

	/* size of data pages */
	size = add_size(size, mul_size(NBuffers, BLCKSZ));
...
	size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded)));
	/* to allow aligning the above */
	size = add_size(size, PG_CACHE_LINE_SIZE);

	/* size of checkpoint sort array in bufmgr.c */
	size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
...

还有块描述符、锁、检查点排序区的分配,这里有过大的改动,为了更好的利用cache line,早先版本一个单独的结构体拆成多个。

诸位有兴趣可以找以前的代码做对比,不写这篇文章我都不会看到这变化,对社区补丁关注不够。

3、共享缓存初始化

在申请OS共享内存(见PGSharedMemoryCreate,有多个平台版本)之后,再从中分配(ShmemInitStruct)出上边看到的几个部分,这些代码见src/backend/storage/buffer/buf_init.c:

	BufferBlocks = (char *)
		ShmemInitStruct("Buffer Blocks",
						NBuffers * (Size) BLCKSZ, &foundBufs);

这是缓存部分的申请,可以看到,它又从共享内存中分配出512M(65536*8192)。

然后就是初始化,各种锁、状态。

4、更多考虑

从上边代码可以看出为什么PG不能动态增加共享缓存,因为它的块描述是一次性分配,然后就不能再改变。考虑下Oracle参数SGA_MAX_SIZE,允许动态分配但有这个上限,可以推断它似乎也有缓存块描述符类似的东西,一次性分配留作以后使用。PG想实现动态管理是不是就有了思路,也不是很难,这取决于共享内存的分配方式,可以阅读 PGSharedMemoryCreate 了解更多,也可以对比以前的老版本,看看分配方式实现有什么不同(记得是 9.1、9.2)。

字数写得不多,点出主要代码在何处,把代码搬到这里也没什么意思。

 

欢迎关注我的公众号,文章同步发布。

© 著作权归作者所有

有理想的猪
粉丝 136
博文 113
码字总数 46195
作品 0
红挢
高级程序员
私信 提问
PostgreSQL DBA快速入门(四) - 体系架构

PostgreSQL在开源关系型数据库市场是最先进的数据库。他的第一个版本在1989年发布,从那时开始,他得到了很多扩展。根据db-enginers上的排名情况,PostgreSQL目前在数据库领域排名第四。 本篇...

闻术苑
2018/08/02
251
0
postgresql数据库体系结构

postgresql数据库是由:连接管理系统(系统控制器)、编译执行系统、存储管理系统、事务系统、系统表 五大部分组成。 ①:连接管理系统:接收外部操作对系统的请求,对操作请求进行预处理和分...

一个笨小孩
2018/07/19
0
0
PostgreSQL 硬件性能调整

POSTGRESQL 是一个对象关系型数据库,由来自全球一组网络开发者开发。它是一个可代替如Oracle、Informix商业数据库的开源版本。 POSTGRESQL 最初由加州大学伯克利分校开发。1996年,一个小组...

oschina
2014/11/27
6.4K
7
PostgreSQL 并行查询概述

大数据时代,人们使用数据库系统处理的数据量越来越大,请求越来越复杂,对数据库系统的大数据处理能力和混合负载能力提出更高的要求。PostgreSQL 作为世界上最先进的开源数据库,在大数据处...

东明
01/05
0
0
linux的swapper_pg_dir的初始化

linux的启动涉及到一个解压与定位的过程,对于x86体系结构而言,系统被加载到0x100000的地方,那么swapper_pg_dir的值是什么呢?我们知道swapper_pg_dir是一个很重要的东西,它是所有进程内核...

晨曦之光
2012/04/10
292
0

没有更多内容

加载失败,请刷新页面

加载更多

spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部