PostgreSQL V9.6 LWLock实现分析(九)

LWLockPostgreSQL中的作用

    PostgreSQL中,LWLock锁可以加在特定的对象上,如对某个进程加锁,以获取其上锁的状态信息:

GetLockStatusData(void)

{...

    for (i = 0; i < ProcGlobal->allProcCount; ++i)

    {

        PGPROC               *proc = &ProcGlobal->allProcs[i];

...

        LWLockAcquire(&proc->backendLock, LW_SHARED);  //proc->backendLock锁对象上加轻量的共享锁

    ...}

...}

    另外,PostgreSQL中,LWLock锁也可以在其它特定对象上加排它锁,如在ProcArrayLock上加锁:

void

analyze_rel(Oid relid, RangeVar *relation, int options,

            VacuumParams *params, List *va_cols, bool in_outer_xact,

            BufferAccessStrategy bstrategy)

{...

    /*

     * OK, let's do it.  First let other backends know I'm in ANALYZE.

     */

    // ProcArrayLock宏定义,进程数组锁: #define ProcArrayLock (&MainLWLockArray[4].lock)

    LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);  //ProcArrayLock锁对象上加轻量的排它锁

    MyPgXact->vacuumFlags |= PROC_IN_ANALYZE; 

    LWLockRelease(ProcArrayLock);  //快速释放锁

...}

    buf上加锁或释放锁:

LockBuffer(Buffer buffer, int mode) //buf上加锁或释放锁

{...

    buf = GetBufferDescriptor(buffer - 1); //获取buf

 

    if (mode == BUFFER_LOCK_UNLOCK)

        LWLockRelease(BufferDescriptorGetContentLock(buf)); //buf上释放锁

    else if (mode == BUFFER_LOCK_SHARE)

        LWLockAcquire(BufferDescriptorGetContentLock(buf), LW_SHARED); //buf上加锁

    else if (mode == BUFFER_LOCK_EXCLUSIVE)

        LWLockAcquire(BufferDescriptorGetContentLock(buf), LW_EXCLUSIVE); //buf上加锁

    else

        elog(ERROR, "unrecognized buffer lock mode: %d", mode);

}

 

缓存区的封锁管理

    共享缓存区的读写,存在竞争操作,因而需要使用锁进行保护。PostgreSQL使用LWLock锁的来保护共享缓存区,但是对共享缓存区采取分段保护的策略,即把共享缓存区分为几个子块,每个子块使用一个LWLock锁进行保护,这样做的好处,能增大对共享缓存区的并发访问粒度、减少竞争冲突。

/*

 * The shared buffer mapping table is partitioned to reduce contention.

 * To determine which partition lock a given tag requires, compute the tag's

 * hash code with BufTableHashCode(), then apply BufMappingPartitionLock().

 * NB: NUM_BUFFER_PARTITIONS must be a power of 2!

 */

#define BufTableHashPartition(hashcode) \

    ((hashcode) % NUM_BUFFER_PARTITIONS)

#define BufMappingPartitionLock(hashcode) \

    (&MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + \

        BufTableHashPartition(hashcode)].lock)

#define BufMappingPartitionLockByIndex(i) \

    (&MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + (i)].lock)

    同理,锁管理器的共享的Hash表(LockHashPartitionLock)、谓词锁的共享Hash表(PredicateLockHashPartitionLock),也被分段后用不同的LWLock加以保护。

SpinLockLWLock比较

   从系统的生命周期看,这2种锁,因加锁对象都是系统层级所以都是在系统初始化期间建立;但是使用的范围和粒度看却不同:SpinLock锁的粒度非常小,通常保护的都是结构体,是对“自我”的保护;LWLock锁的粒度相对大一些,通常保护的是内存结构一级的对象,如一个hash表,这个属于“系统业务”级别的保护。从下面这个示例,我们可以体会这个差别。

typedef struct pgssSharedState  //本结构体中的两种锁的详细用法,可以参见:pg_stat_statements_internal()

{

    LWLock      *lock;               /* protects hashtable search/modification */   //用以保护“static HTAB *pgss_hash

    double      cur_median_usage;    /* current median usage in hashtable */

    Size        mean_query_len;      /* current mean entry text length */

    slock_t     mutex;               /* protects following fields only: */          //用以保护pgssSharedState这个结构体自身的数据

    Size        extent;              /* current extent of query file */

    int         n_writers;           /* number of active writers to query file */

    int         gc_count;            /* query file garbage collection cycle count */

} pgssSharedState;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值