微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

postgresql共享内存之——分片slice

本文原创为freas_1990,转载请表明出处:http://www.jb51.cc/article/p-cpagvcnt-yu.html

如果接触过Oracle数据库,或者多进程框架的server软件,对共享内存的概念自然不会陌生。

共享内存到底是什么呢?共享内存与常见的malloc()获取到的内存有什么区别呢?

在单进程模型里,直接调用malloc即可获取到内存,然后对该内存进行读、写,如果有多线程存在,再通过mutex接口即可做到并发控制。

众所周知的是,进程与进程的内存区域是相互隔开的,如果一个server为了提高并发能力而使用了多进程,此时,多个进程必须要能访问同一块内存区域(才能实现同步),问题出来了。进程与进程的内存区域是隔开的,必须要采用“共享内存”机制,才能让多进程共同访问这一块内存区域。

然而,接下的问题是,posix的标准只给出了shmget()获取到一大块内存,这一大块内存如何才能有效使用?

从本质上来说,如果这一大块内存没用好,它就和“数组”一样呆板无用。

我们来看一下postgresql是如何对共享内存进行slice的呢?

/*
 * ShmemAlloc -- allocate word-aligned byte string from
 * 	shared memory
 *
 * Assumes Shmemlock and ShmemFreeStart are initialized.
 * Returns: real pointer to memory or NULL if we are out
 * 	of space.  Has to return a real pointer in order 
 *  	to be compatable with malloc().
 */
long *
ShmemAlloc(unsigned long size)
{
    unsigned long tmpFree;
    long *newSpace;
    
    /*
     * ensure space is word aligned.
     *
     * Word-alignment is not good enough. We have to be more
     * conservative: doubles need 8-byte alignment. (We probably only need
     * this on RISC platforms but this is not a big waste of space.) 
     *                                                - ay 12/94
     */
    if (size % sizeof(double))
	size += sizeof(double) - (size % sizeof(double));
    
    Assert(*ShmemFreeStart);
    
    SpinAcquire(Shmemlock);
    
    tmpFree = *ShmemFreeStart + size;
    if (tmpFree <= ShmemSize) {
	newSpace = (long *)MAKE_PTR(*ShmemFreeStart);
	*ShmemFreeStart += size;
    } else {
	newSpace = NULL;
    }
    
    SpinRelease(Shmemlock); 
    
    if (! newSpace) {
	elog(NOTICE,"ShmemAlloc: out of memory ");
    }
    return(newSpace);
}


相比于已经设计好的malloc,共享内存需要自己设计管理这一大片内存的数据结构。而上面这个函数就类似于malloc里调用的get_one_page()。

本质上,它是在共享内存的起始地址与结束地址之间滑动(cursor的概念)。

从ShmemAlloc返回的内存block会被postgresql的hash数据结构“收容”,此后,这片共享内存才能被正常使用与维护。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果是个PostGreSQL的数据,于是装数据库,但这个也不懂呀,而且本系统用的Oracle,于是得解决迁移转换的问题。 总结下来两个思路。1、PostgresToOracle多金的
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么查看PostgreSQL数据库中所有表”文章能帮助大...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正确。  pg_hba.conf文件在Postgre安装文件目录下的data文件夹中。解决方案1、进入到data目录下,找到pg_hba.conf文件
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本地localhost访问正常,在相同网段的远程机器访问报如下错误
wamp 环境 这个提示就是说你的版本低于10了。 先打印php_info(),查看自己的版本(我这边是已经处理后的,之前的忘记截图了)
psycopg2.OperationalError: SSL SYSCALL error: EOF detected 问题提示:exception psycopg2.OperationalError
项目 postgres 连接不上, 所有连接报错 :psql: FATAL: sorry, too many clients already问题原由程序使用连接未及时释放, 连接一直处于 idle 状态处理方式1、 程序里面未释放的连接, 在使用后及时释放
服务器在同一个数据目录上启动了两个PostgreSQL实例(它已经删除postmaster.pid并使用了新的端口号,因此绕过了这种行为的正常保护措施被绕过),导致PostgreSQL的误操作postgresql 报错 FATAL: the database system is
问题原因:数据库崩溃,内存不足造成 或者 数据已损坏,磁盘故障造成首先介绍一下背景,在测试Deepgreen(Greenplum升级版)数据库时,pgbench并发数设置过多,导致数据库卡死了,在进行连接、重启、关闭时,都报同样
第 11 届 PostgreSQL 中国技术大会于 2022 年 1 月 7 日至 9 日在武汉光谷会展酒店成功举办。作为 PostgreSQL 技术领域的年度盛事,postgreSQL 中文社区旨在搭建开放、合作共享的平台,基于开源,创新驱动,共同探讨数据库行业数字化发展方向和未来新机遇。