postgresql共享内存之——分片(slice)

前端之家收集整理的这篇文章主要介绍了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数据结构“收容”,此后,这片共享内存才能被正常使用与维护。

原文链接:https://www.f2er.com/postgresql/196002.html

猜你在找的Postgre SQL相关文章