Lock

全局hash

LockMethodLockHash:存储LOCK
LockMethodProcLockHash:存储PROCLOCK
LockMethodLocalHash:存储LOCALLOCK

同一个LOCK资源对象可以被多个不同的 PROCLOCK 持有,而这些 PROCLOCK 又分别属于不同的进程。

LOCKTAG

1
2
3
4
5
6
7
8
9
typedef struct LOCKTAG
{
uint32 locktag_field1; /* a 32-bit ID field */
uint32 locktag_field2; /* a 32-bit ID field */
uint32 locktag_field3; /* a 32-bit ID field */
uint16 locktag_field4; /* a 16-bit ID field */
uint8 locktag_type; /* see enum LockTagType */
uint8 locktag_lockmethodid; /* lockmethod indicator */
} 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,用于用户自定义锁。

PROCLOCK

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct PROCLOCK
{
/* tag */
PROCLOCKTAG tag; /* unique identifier of proclock object */

/* data */
PGPROC *groupLeader; /* proc's lock group leader, or proc itself */
LOCKMASK holdMask; /* bitmask for lock types currently held */
LOCKMASK releaseMask; /* bitmask for lock types to be released */
dlist_node lockLink; /* list link in LOCK's list of proclocks */
dlist_node procLink; /* list link in PGPROC's list of proclocks */
} PROCLOCK;

LOCK

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct LOCK
{
LOCKTAG tag;
LOCKMASK grantMask;
LOCKMASK waitMask;
dlist_head procLocks;
dclist_head waitProcs;
int requested[MAX_LOCKMODES];
int nRequested;
int granted[MAX_LOCKMODES];
int nGranted;
} LOCK;
  • waitProcs
    等待本LOCK的PGPROC链表
  • waitMask
    该资源上等待的锁类型:目前有进程在等待的锁类型集合
  • procLocks
    进程对于一个LOCK的持有以及request情况;如果进程占有多个LOCK,则会有多个PROCLOCK
    • 一个 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
2
3
4
5
6
7
8
9
10
11
12
13
14
#define NoLock					0
#define AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
#define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL), ANALYZE, CREATE
* INDEX CONCURRENTLY */
#define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW
* SHARE */
#define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR UPDATE */
#define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM FULL,
* and unqualified LOCK TABLE */

#define MaxLockMode 8 /* highest standard lock mode */

Table-Level Lock Modes

  • ACCESS SHARE (AccessShareLock)
    Conflicts with the ACCESS EXCLUSIVE lock mode only.

    The SELECT command acquires a lock of this mode on referenced tables

  • ROW SHARE (RowShareLock)
    Conflicts with the EXCLUSIVE and ACCESS EXCLUSIVE lock modes.

    SELECT FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE, or FOR KEY SHARE

  • ROW EXCLUSIVE (RowExclusiveLock)
    Conflicts with the SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes.

    The commands UPDATE, DELETE, INSERT, and MERGE acquire this lock mode on the target table.

  • SHARE UPDATE EXCLUSIVE (ShareUpdateExclusiveLock)
    Conflicts with the SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS EXCLUSIVE lock modes.This mode protects a table against concurrent schema changes and VACUUM runs.

    Acquired by VACUUM (without FULL), ANALYZE, CREATE INDEX CONCURRENTLY, CREATE STATISTICS, COMMENT ON, REINDEX CONCURRENTLY, and certain ALTER INDEX and ALTER TABLE variants (for full details see the documentation of these commands).

Conflicting Lock Modes

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

参考链接

postgres官方文档