Lock
全局hash
LockMethodLockHash:存储LOCK
LockMethodProcLockHash:存储PROCLOCK
LockMethodLocalHash:存储LOCALLOCK
同一个LOCK资源对象可以被多个不同的 PROCLOCK 持有,而这些 PROCLOCK 又分别属于不同的进程。
LOCKTAG
1 | typedef struct LOCKTAG |
- locktag_type
标识这个锁是针对哪类资源的。每种 LockTagType 决定了 LOCKTAG 里后面几个字段(locktag_field1 ~ locktag_field4)是怎么解释的,比如:
LOCKTAG_TRANSACTION:xid
LOCKTAG_RELATION:dbOid + relOid
LOCKTAG_TUPLE:dbOid + relOid + blockNum + offNum - locktag_lockmethodid
- DEFAULT_LOCKMETHOD(id = DEFAULT_LOCKMETHOD)
绝大多数用户可见的锁(relation, tuple, transactionid 等)都走它。 - USER_LOCKMETHOD(id = USER_LOCKMETHOD)
提供给 pg_advisory_lock() 一类的 advisory lock,用于用户自定义锁。
- DEFAULT_LOCKMETHOD(id = DEFAULT_LOCKMETHOD)
LOCK
1 | typedef struct LOCK |
- waitProcs
等待本LOCK的PGPROC链表 - procLocks
等待本LOCK的PROCLOCK链表 - waitMask
该资源上等待的锁类型:目前有进程在等待的锁类型集合 - procLocks
- 一个 LOCK(资源)可以挂很多 PROCLOCK(不同后台进程),每个 PROCLOCK 只对应一个 PGPROC + 一个 LOCK。
- 同一进程与同一资源只会有一个 PROCLOCK;它的 holdMask 可以同时包含多个锁模式位,且内部还有引用计数在 LOCALLOCK 里,不会创建多个 PROCLOCK
- 资源侧用 LOCK.procLocks 链表串起所有持有/等待它的 PROCLOCK;进程侧在 PGPROC.myProcLocks(见 proc.h)里串起它关联的所有 PROCLOCK
因此:一个资源可以被多个进程持锁;一个进程可以同时持有多个资源的锁;对同一资源如需多模式/多次持有,累加在同一个 PROCLOCK 的掩码/计数里。
- grantMask
该资源上已经授予的锁类型,LOCKMASK 每一位对应 “编号为 N 的锁模式是否已持有/等待”,位号就是 lockmode, bit0 保留不适用 - requested[i]
当前有多少个后台对模式 i 提出请求(已授予 + 正在等待) - nRequested:是总和
“等待者数” = requested[i] - granted[i](或总等待 = nRequested - nGranted),依此可以知道有没有人还在等
授予/释放锁时同步更新这些计数,并据此调整 grantMask/waitMask,决定是否要唤醒等待队列; - granted[i]
当前有多少个后台成功得到了模式 i 的锁 - nGranted:
总和
LOCKMODE
每种资源支持8种锁(lockmode)
1 |
冲突矩阵
| Requested Lock Mode | ACCESS SHARE | ROW SHARE | ROW EXCL. | SHARE UPDATE EXCL. | SHARE | SHARE ROW EXCL. | EXCL. | ACCESS EXCL. |
|---|---|---|---|---|---|---|---|---|
| ACCESS SHARE | X | |||||||
| ROW SHARE | X | X | ||||||
| ROW EXCL. | X | X | X | X | ||||
| SHARE UPDATE EXCL. | X | X | X | X | X | |||
| SHARE | X | X | X | X | X | |||
| SHARE ROW EXCL. | X | X | X | X | X | X | ||
| EXCL. | X | X | X | X | X | X | X | |
| ACCESS EXCL. | X | X | X | X | X | X | X | X |