本篇内容主要讲解“怎么理解PostgreSQL Locks中的Lock Manager Internal Locking”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解PostgreSQL Locks中的Lock Manager Internal Locking”吧!
一、Lock Manager Internal Locking
Lock Manager Internal Locking
-----------------------------
内部锁机制
Before PostgreSQL 8.2, all of the shared-memory data structures used by
the lock manager were protected by a single LWLock, the LockMgrLock;
any operation involving these data structures had to exclusively lock
LockMgrLock. Not too surprisingly, this became a contention bottleneck.
To reduce contention, the lock manager's data structures have been split
into multiple "partitions", each protected by an independent LWLock.
Most operations only need to lock the single partition they are working in.
Here are the details:
在PG 8.2或更旧的版本中,共享缓存中的数据结构通过一个单一的LWLock(LockMgrLock)保护;
涉及这些数据结构的所有操作必须持有LockMgrLock独占锁.不用说太多,这会成为争用的瓶颈.
为了减少争用,锁管理器数据结构已拆分为多个"partitions",每一个分区使用独立的LWLock保护.
大多数操作只需要锁定其中一个分区,下面是实现细节:
* Each possible lock is assigned to one partition according to a hash of
its LOCKTAG value. The partition's LWLock is considered to protect all the
LOCK objects of that partition as well as their subsidiary PROCLOCKs.
* 只需要授予属于LOCKTAG哈希值的某个分区的锁,分区的LWLock用于保护该分区的所有LOCK对象.
* The shared-memory hash tables for LOCKs and PROCLOCKs are organized
so that different partitions use different hash chains, and thus there
is no conflict in working with objects in different partitions. This
is supported directly by dynahash.c's "partitioned table" mechanism
for the LOCK table: we need only ensure that the partition number is
taken from the low-order bits of the dynahash hash value for the LOCKTAG.
To make it work for PROCLOCKs, we have to ensure that a PROCLOCK's hash
value has the same low-order bits as its associated LOCK. This requires
a specialized hash function (see proclock_hash).
LOCKs和PROCLOCKs被组织为存储在共享内存中哈希表以便不同的分区使用不同的哈希链,
这样不同分区中的对象就不会出现冲突,通过dynahash.c's "partitioned table"机制实现.
只需要确保分区号从LOCKTAG的dynahash哈希值的低位中获取即可.
对于PROCLOCKs,必须确保PROCLOCK的哈希值有与LOCK有相同的低位.这需要特别的哈希函数(proclock_hash)
* Formerly, each PGPROC had a single list of PROCLOCKs belonging to it.
This has now been split into per-partition lists, so that access to a
particular PROCLOCK list can be protected by the associated partition's
LWLock. (This rule allows one backend to manipulate another backend's
PROCLOCK lists, which was not originally necessary but is now required in
connection with fast-path locking; see below.)
以前的做法,每一个PGPROC都有一个单独的PROCLOCKs链表.现在已拆分为每一个分区一个链表,
这样的好处是访问一个PROCLOCK链表可通过相关的分区LWLock保护.
(这个规则允许一个后台进程可管理另外一个后台进程的PROCLOCK链表,这个事情本来是不需要做的,
但现在在使用fast-path锁的连接时需要)
* The other lock-related fields of a PGPROC are only interesting when
the PGPROC is waiting for a lock, so we consider that they are protected
by the partition LWLock of the awaited lock.
PGPROC中与锁相关的域只在PRPROC等待锁才会变得有用,因此我们考虑通过分区LWLOCK中awaited lock来进行保护.
For normal lock acquisition and release, it is sufficient to lock the
partition containing the desired lock. Deadlock checking needs to touch
multiple partitions in general; for simplicity, we just make it lock all
the partitions in partition-number order. (To prevent LWLock deadlock,
we establish the rule that any backend needing to lock more than one
partition at once must lock them in partition-number order.) It's
possible that deadlock checking could be done without touching every
partition in typical cases, but since in a properly functioning system
deadlock checking should not occur often enough to be performance-critical,
trying to make this work does not seem a productive use of effort.
对于普通的锁请求和释放,锁定包含目标锁的分区就已经足够了.
通常来说,死锁检测需要访问多个分区.简单来说,我们只要按分区顺序锁定相关的所有分区即可.
(为了避免LWLock死锁,设定的规则是所有需要锁定一个以上分区的后台进程必须一次过按顺序所有所有分区)
在典型情况下,不需要访问每一个分区进行死锁检测是可以做到的,但因为在一个正常运行的系统中,
死锁检测不应经常发生,因此不会对性能造成较大的影响.
A backend's internal LOCALLOCK hash table is not partitioned. We do store
a copy of the locktag hash code in LOCALLOCK table entries, from which the
partition number can be computed, but this is a straight speed-for-space
tradeoff: we could instead recalculate the partition number from the LOCKTAG
when needed.
后台进程的内部LOCALLOCK哈希表没有分区.
我们确实在LOCALLOCK表条目中存储了locktag哈希值的副本,分区号可以计算,这是一个以空间换时间的考量:
我们可以从LOCKTAG重新计算分区号.
到此,相信大家对“怎么理解PostgreSQL Locks中的Lock Manager Internal Locking”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!