PostgreSQL 源码解读(219)- Locks(Overview)
短信预约 -IT技能 免费直播动态提醒
本节是PostgreSQL Locks的概要部分,翻译自README文件.
一、Overview
class="lazy" data-src/backend/storage/lmgr/README
Locking Overview
================
Postgres uses four types of interprocess locks:
PG使用四种类型的锁:
* Spinlocks. These are intended for *very* short-term locks. If a lock
is to be held more than a few dozen instructions, or across any sort of
kernel call (or even a call to a nontrivial subroutine), don't use a
spinlock. Spinlocks are primarily used as infrastructure for lightweight
locks. They are implemented using a hardware atomic-test-and-set
instruction, if available. Waiting processes busy-loop until they can
get the lock. There is no provision for deadlock detection, automatic
release on error, or any other nicety. There is a timeout if the lock
cannot be gotten after a minute or so (which is approximately forever in
comparison to the intended lock hold time, so this is certainly an error
condition).
* Spinlocks(自旋锁).这种一种非常短期的锁.如果持有锁会超过几十个指令周期,或者
跨越多个类型的内核调用,那么不要使用自旋锁.
如可用的话(部分平台并不可用),Spinlocks主要用于轻量级锁的基础"设施".
等待进程会一直等待直至获取到锁(等待1分钟则超时).没有提供死锁检测/错误时自动释放.
* Lightweight locks (LWLocks). These locks are typically used to
interlock access to datastructures in shared memory. LWLocks support
both exclusive and shared lock modes (for read/write and read-only
access to a shared object). There is no provision for deadlock
detection, but the LWLock manager will automatically release held
LWLocks during elog() recovery, so it is safe to raise an error while
holding LWLocks. Obtaining or releasing an LWLock is quite fast (a few
dozen instructions) when there is no contention for the lock. When a
process has to wait for an LWLock, it blocks on a SysV semaphore so as
to not consume CPU time. Waiting processes will be granted the lock in
arrival order. There is no timeout.
* Lightweight locks (轻量级锁,LWLocks).这些锁典型的用于保护共享内存中的数据结构.
LWLocks提供了共享和独占模式,没有提供死锁检测,但在elog()恢复期间自动释放持有的锁,
因此在持有轻量级锁时抛出异常是安全的.
没有冲突的情况下,获取或者释放轻量级锁是相当快的(几十个指令周期).
如进程从必须等到LWLock,则会阻塞等待SysV信号量,这样可以不需要耗费CPU时间.
等待进程按到达顺序授予锁.LWLocks没有超时机制.
* Regular locks (a/k/a heavyweight locks). The regular lock manager
supports a variety of lock modes with table-driven semantics, and it has
full deadlock detection and automatic release at transaction end.
Regular locks should be used for all user-driven lock requests.
* Regular locks (重量级锁,a/k/a heavyweight locks).
常规的锁管理支持多种表驱动语义上的锁模式,有完善的死锁检测机制并在事务结束时自动释放锁.
常规锁应在所有用户驱动的锁请求中使用.
* SIReadLock predicate locks. See separate README-SSI file for details.
* SIReadLock predicate locks(SIReadLock谓词锁).详情参见README-SSI.
Acquisition of either a spinlock or a lightweight lock causes query
cancel and die() interrupts to be held off until all such locks are
released. No such restriction exists for regular locks, however. Also
note that we can accept query cancel and die() interrupts while waiting
for a regular lock, but we will not accept them while waiting for
spinlocks or LW locks. It is therefore not a good idea to use LW locks
when the wait time might exceed a few seconds.
自旋锁/轻量级锁都会导致取消查询和die()中断被延迟,直至释放锁.
对于常规锁就没有这样的限制.
同时,要注意在等待常规锁时可以接受取消查询和die()中断,但在等待自旋锁/轻量级锁时则不接受.
如果等待时间超过几十秒,使用LWLocks并不是明智的选择.
The rest of this README file discusses the regular lock manager in detail.
Lock Data Structures
--------------------
Lock数据结构
Lock methods describe the overall locking behavior. Currently there are
two lock methods: DEFAULT and USER.
锁定方法描述了锁定动作的概览.目前有两种锁定方法:DEFAULT和USER.
Lock modes describe the type of the lock (read/write or shared/exclusive).
In principle, each lock method can have its own set of lock modes with
different conflict rules, but currently DEFAULT and USER methods use
identical lock mode sets. See class="lazy" data-src/include/storage/lock.h for more details.
(Lock modes are also called lock types in some places in the code and
documentation.)
锁定模式描述了lock(R/W或共享/独占)的类型.
原则上,每一种锁方法可以有自己的锁模式集合和不同的冲突原则,但当前的DEFAULT/USER方法
会使用相同的锁模式集合,详情参见class="lazy" data-src/include/storage/lock.h
(锁模式在代码和文档中的某些地方也被称为锁类型)
There are two main methods for recording locks in shared memory. The primary
mechanism uses two main structures: the per-lockable-object LOCK struct, and
the per-lock-and-requestor PROCLOCK struct. A LOCK object exists for each
lockable object that currently has locks held or requested on it. A PROCLOCK
struct exists for each backend that is holding or requesting lock(s) on each
LOCK object.
在共享内存中保存锁信息有两种主要的方法.其中一种主要的机制使用两种结构体:
LOCK:每一个锁定对象一个,per-lockable-object.存储每一个锁定的对象(持有锁或者等待锁).
PROCLOCK:每一个锁和请求者一个,per-lock-and-requestor.存储每一个持有/请求LOCK对象的后端进程.
There is also a special "fast path" mechanism which backends may use to
record a limited number of locks with very specific characteristics: they must
use the DEFAULT lockmethod; they must represent a lock on a database relation
(not a shared relation), they must be a "weak" lock which is unlikely to
conflict (AccessShareLock, RowShareLock, or RowExclusiveLock); and the system
must be able to quickly verify that no conflicting locks could possibly be
present. See "Fast Path Locking", below, for more details.
另外,还有一种成为"fast path"的机制,后台进程可使用非常规特性的用于记录有限数量的锁,
这种情况下必须使用DEFAULT锁方法.它们必须表示数据库关系(非共享关系)上的锁,
它们必须是一个不太可能出现冲突的"弱"锁(AccessShareLock, RowShareLock, or RowExclusiveLock);
系统必须能够快速的验证冲突锁有没有可能出现.详细参见下面的"Fast Path Locking".
Each backend also maintains an unshared LOCALLOCK structure for each lockable
object and lock mode that it is currently holding or requesting. The shared
lock structures only allow a single lock grant to be made per lockable
object/lock mode/backend. Internally to a backend, however, the same lock may
be requested and perhaps released multiple times in a transaction, and it can
also be held both transactionally and session-wide. The internal request
counts are held in LOCALLOCK so that the shared data structures need not be
accessed to alter them.
每一个后台进程同时会维护非共享的LOCALLOCK结构体,该结构体存储锁定对象和当前持有/请求的锁模式.
共享锁结构体只允许为每个锁定对象/锁模式/后台进程授予一个锁.
但是,在后台进程内部,同一个锁可能在同一个事务中请求和释放多次,并且可以事务/会话模式持有.
内部请求的计数在LOCALLOCK结构体中存储以便共享数据结构体在更新时不需要访问.
LOCK
typedef struct LOCK
{
LOCKTAG tag;
LOCKMASK grantMask;
LOCKMASK waitMask;
SHM_QUEUE procLocks;
PROC_QUEUE waitProcs;
int requested[MAX_LOCKMODES];
int nRequested;
int granted[MAX_LOCKMODES];
int nGranted;
} LOCK;
#define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
PROCLOCK
typedef struct PROCLOCKTAG
{
LOCK *myLock;
PGPROC *myProc;
} PROCLOCKTAG;
typedef struct PROCLOCK
{
PROCLOCKTAG tag;
PGPROC *groupLeader;
LOCKMASK holdMask;
LOCKMASK releaseMask;
SHM_QUEUE lockLink;
SHM_QUEUE procLink;
} PROCLOCK;
#define PROCLOCK_LOCKMETHOD(proclock) \
LOCK_LOCKMETHOD(*((proclock).tag.myLock))
LOCALLOCK
typedef struct LOCALLOCKTAG
{
LOCKTAG lock;
LOCKMODE mode;
} LOCALLOCKTAG;
typedef struct LOCALLOCKOWNER
{
struct ResourceOwnerData *owner;
int64 nLocks;
} LOCALLOCKOWNER;
typedef struct LOCALLOCK
{
LOCALLOCKTAG tag;
uint32 hashcode;
LOCK *lock;
PROCLOCK *proclock;
int64 nLocks;
int numLockOwners;
int maxLockOwners;
LOCALLOCKOWNER *lockOwners;
bool holdsStrongLockCount;
bool lockCleared;
} LOCALLOCK;
#define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)
二、参考资料
README
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
PostgreSQL 源码解读(219)- Locks(Overview)
下载Word文档到电脑,方便收藏和打印~
下载Word文档
猜你喜欢
2024-04-02
Rust Atomics and Locks 源码解读
这篇文章主要为大家介绍了Rust Atomics and Locks 源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-27
2024-04-02
2024-04-02
2024-04-02
2024-04-02
2024-04-02
PostgreSQL 源码解读(248)- HTAB动态扩展图解#2
本节简单介绍了PostgreSQL中的HTAB如何动态扩展,这是第2部分,结合代码进行解析.一、数据结构/* * Top control structure for a hashtable --- in a shared table, ea
2023-05-31
2024-04-02