LWLock in postgres
一 相关结构体说明
1 | typedef struct LWLock |
tranche
每个 LWLock 都属于某个 tranche,tranche 是一个 int 类型的 ID,代表这把锁的用途state (不同版本可能会有变化,本文对应版本:PostgreSQL 19devel(开发版,尚未正式发布的 19))
bit0..17:共享持有者计数(一个整数计数,不是位图)
bit18:独占锁哨兵位(LW_VAL_EXCLUSIVE = 1<<18)
bit29: LW_FLAG_LOCKED,是 wait list 自身的小锁(保护等待队列操作)
bit30: LW_FLAG_RELEASE_OK,表示当前可以在释放路径执行唤醒
bit31: LW_FLAG_HAS_WAITERS,表示等待队列里有 waiter
- waiters
等待队列
二 Interface说明
2.1 LWLockAcquire
加锁,失败进入等待队列,直接加上锁的情况,可能会造成等待队列无效唤醒
acquire a lightweight lock in the specified mode
Side effect: cancel/die interrupts are held off until lock release.
1 | if (mode == LW_EXCLUSIVE) |
上述代码确认是否可以加锁
2.2 LWLockRelease
进行唤醒条件:
- oldstate & LW_FLAG_HAS_WAITERS:等待队列非空。这个条件确认有进程在等待锁。
- oldstate & LW_FLAG_RELEASE_OK: 允许唤醒。这个标志表示系统在上次唤醒后,已经将再次唤醒其他等待者的权限交给了被唤醒的进程。
- (oldstate & LW_LOCK_MASK) == 0:锁已空闲。这个条件确认锁当前没有被任何进程占用(无论是独占模式还是共享模式,计数都为零)
三 分配与类型(默认值,版本相关)
NUM_INDIVIDUAL_LWLOCKS:核心按表生成的单锁(lwlocklist.h),数量随版本变化,不是固定 56。NUM_BUFFER_PARTITIONS(默认 128):共享缓冲区 mapping hash 的分区锁BufferMappingLock[i]。NUM_LOCK_PARTITIONS(默认 16):heavyweight lock manager 哈希分区锁(LWTRANCHE_LOCK_MANAGER)。NUM_PREDICATELOCK_PARTITIONS(默认 16):谓词锁哈希分区锁。- 扩展自定义:在 postmaster 启动阶段调用
RequestNamedLWLockTranche(name, n)申请一组锁,重启后GetNamedLWLockTranche取基址。需要shared_preload_libraries的扩展通常属于此类。