Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitec0baf9

Browse files
committed
Divide the lock manager's shared state into 'partitions', so as to
reduce contention for the former single LockMgrLock. Per my recentproposal. I set it up for 16 partitions, but on a pgbench test thisgives only a marginal further improvement over 4 partitions --- we needto test more scenarios to choose the number of partitions.
1 parentbe8100d commitec0baf9

File tree

10 files changed

+627
-399
lines changed

10 files changed

+627
-399
lines changed

‎src/backend/access/transam/twophase.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
*$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.17 2005/11/22 18:17:07 momjian Exp $
10+
*$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.18 2005/12/11 21:02:17 tgl Exp $
1111
*
1212
* NOTES
1313
*Each global transaction is associated with a global transaction
@@ -284,7 +284,8 @@ MarkAsPreparing(TransactionId xid, const char *gid,
284284
gxact->proc.lwWaitLink=NULL;
285285
gxact->proc.waitLock=NULL;
286286
gxact->proc.waitProcLock=NULL;
287-
SHMQueueInit(&(gxact->proc.procLocks));
287+
for (i=0;i<NUM_LOCK_PARTITIONS;i++)
288+
SHMQueueInit(&(gxact->proc.myProcLocks[i]));
288289
/* subxid data must be filled later by GXactLoadSubxactData */
289290
gxact->proc.subxids.overflowed= false;
290291
gxact->proc.subxids.nxids=0;

‎src/backend/storage/ipc/procarray.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
*
1515
* The process array now also includes PGPROC structures representing
1616
* prepared transactions. The xid and subxids fields of these are valid,
17-
* asis theprocLocks list. They can be distinguished from regular backend
18-
* PGPROCs at need by checking for pid == 0.
17+
* asare themyProcLocks lists. They can be distinguished from regular
18+
*backendPGPROCs at need by checking for pid == 0.
1919
*
2020
*
2121
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
2222
* Portions Copyright (c) 1994, Regents of the University of California
2323
*
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.8 2005/11/22 18:17:20 momjian Exp $
26+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.9 2005/12/11 21:02:18 tgl Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/

‎src/backend/storage/lmgr/README

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.18 2005/12/09 01:22:04 tgl Exp $
1+
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.19 2005/12/11 21:02:18 tgl Exp $
22

33

44
LOCKING OVERVIEW
@@ -50,9 +50,12 @@ LOCK DATA STRUCTURES
5050
Lock methods describe the overall locking behavior. Currently there are
5151
two lock methods: DEFAULT and USER. (USER locks are non-blocking.)
5252

53-
Lock modes describe the type of the lock (read/write or shared/exclusive).
54-
See src/tools/backend/index.html and src/include/storage/lock.h for more
55-
details.
53+
Lock modes describe the type of the lock (read/write or shared/exclusive).
54+
In principle, each lock method can have its own set of lock modes with
55+
different conflict rules, but currently DEFAULT and USER methods use
56+
identical lock mode sets. See src/tools/backend/index.html and
57+
src/include/storage/lock.h for more details. (Lock modes are also called
58+
lock types in some places in the code and documentation.)
5659

5760
There are two fundamental lock structures in shared memory: the
5861
per-lockable-object LOCK struct, and the per-lock-and-requestor PROCLOCK
@@ -67,7 +70,7 @@ be made per lockable object/lock mode/backend. Internally to a backend,
6770
however, the same lock may be requested and perhaps released multiple times
6871
in a transaction, and it can also be held both transactionally and session-
6972
wide. The internal request counts are held in LOCALLOCK so that the shared
70-
LockMgrLockneed not beobtained to alter them.
73+
data structuresneed not beaccessed to alter them.
7174

7275
---------------------------------------------------------------------------
7376

@@ -103,10 +106,10 @@ procLocks -
103106
be waiting for more!).
104107

105108
waitProcs -
106-
This is a shared memory queue of allprocess structures corresponding to
107-
a backendthatis waiting (sleeping) until another backend releases this
109+
This is a shared memory queue of allPGPROC structures corresponding to
110+
backendsthatare waiting (sleeping) until another backend releases this
108111
lock. The process structure holds the information needed to determine
109-
if it should be woken up whenthis lock is released.
112+
if it should be woken up whenthe lock is released.
110113

111114
nRequested -
112115
Keeps a count of how many times this lock has been attempted to be
@@ -131,12 +134,12 @@ nGranted -
131134
granted -
132135
Keeps count of how many locks of each type are currently held. Once again
133136
only elements 1 through MAX_LOCKMODES-1 are used (0 is not). Also, like
134-
requested, summing the values of granted should total to the value
137+
requested[], summing the values of granted[] should total to the value
135138
of nGranted.
136139

137140
We should always have 0 <= nGranted <= nRequested, and
138-
0 <= granted[i] <= requested[i] for each i.Ifthe request counts go to
139-
zero, thelock object is no longer needed and can be freed.
141+
0 <= granted[i] <= requested[i] for each i.When allthe request counts
142+
go tozero, theLOCK object is no longer needed and can be freed.
140143

141144
---------------------------------------------------------------------------
142145

@@ -154,15 +157,16 @@ tag -
154157
SHMEM offset of PGPROC of backend process that owns this PROCLOCK.
155158

156159
holdMask -
157-
A bitmask for the locktypes successfully acquired by this PROCLOCK.
160+
A bitmask for the lockmodes successfully acquired by this PROCLOCK.
158161
This should be a subset of the LOCK object's grantMask, and also a
159-
subset of the PGPROC object's heldLocks mask.
162+
subset of the PGPROC object's heldLocks mask (if the PGPROC is
163+
currently waiting for another lock mode on this lock).
160164

161165
releaseMask -
162-
A bitmask for the locktypes due to be released during LockReleaseAll.
166+
A bitmask for the lockmodes due to be released during LockReleaseAll.
163167
This must be a subset of the holdMask. Note that it is modified without
164-
taking theLockMgrLock, and therefore it is unsafe for any backend except
165-
the one owning the PROCLOCK to examine/change it.
168+
taking thepartition LWLock, and therefore it is unsafe for any
169+
backend exceptthe one owning the PROCLOCK to examine/change it.
166170

167171
lockLink -
168172
List link for shared memory queue of all the PROCLOCK objects for the
@@ -174,7 +178,60 @@ procLink -
174178

175179
---------------------------------------------------------------------------
176180

177-
The deadlock detection algorithm:
181+
182+
LOCK MANAGER INTERNAL LOCKING
183+
184+
Before PostgreSQL 8.2, all of the shared-memory data structures used by
185+
the lock manager were protected by a single LWLock, the LockMgrLock;
186+
any operation involving these data structures had to exclusively lock
187+
LockMgrLock. Not too surprisingly, this became a contention bottleneck.
188+
To reduce contention, the lock manager's data structures have been split
189+
into multiple "partitions", each protected by an independent LWLock.
190+
Most operations only need to lock the single partition they are working in.
191+
Here are the details:
192+
193+
* Each possible lock is assigned to one partition according to a hash of
194+
its LOCKTAG value (see LockTagToPartition()). The partition's LWLock is
195+
considered to protect all the LOCK objects of that partition as well as
196+
their subsidiary PROCLOCKs. The shared-memory hash tables for LOCKs and
197+
PROCLOCKs are divided into separate hash tables for each partition, and
198+
operations on each hash table are likewise protected by the partition
199+
lock.
200+
201+
* Formerly, each PGPROC had a single list of PROCLOCKs belonging to it.
202+
This has now been split into per-partition lists, so that access to a
203+
particular PROCLOCK list can be protected by the associated partition's
204+
LWLock. (This is not strictly necessary at the moment, because at this
205+
writing a PGPROC's PROCLOCK list is only accessed by the owning backend
206+
anyway. But it seems forward-looking to maintain a convention for how
207+
other backends could access it. In any case LockReleaseAll needs to be
208+
able to quickly determine which partition each LOCK belongs to, and
209+
for the currently contemplated number of partitions, this way takes less
210+
shared memory than explicitly storing a partition number in LOCK structs
211+
would require.)
212+
213+
* The other lock-related fields of a PGPROC are only interesting when
214+
the PGPROC is waiting for a lock, so we consider that they are protected
215+
by the partition LWLock of the awaited lock.
216+
217+
For normal lock acquisition and release, it is sufficient to lock the
218+
partition containing the desired lock. Deadlock checking needs to touch
219+
multiple partitions in general; for simplicity, we just make it lock all
220+
the partitions in partition-number order. (To prevent LWLock deadlock,
221+
we establish the rule that any backend needing to lock more than one
222+
partition at once must lock them in partition-number order.) It's
223+
possible that deadlock checking could be done without touching every
224+
partition in typical cases, but since in a properly functioning system
225+
deadlock checking should not occur often enough to be performance-critical,
226+
trying to make this work does not seem a productive use of effort.
227+
228+
A backend's internal LOCALLOCK hash table is not partitioned. We do store
229+
the partition number in LOCALLOCK table entries, but this is a straight
230+
speed-for-space tradeoff: we could instead recalculate the partition
231+
number from the LOCKTAG when needed.
232+
233+
234+
THE DEADLOCK DETECTION ALGORITHM
178235

179236
Since we allow user transactions to request locks in any order, deadlock
180237
is possible. We use a deadlock detection/breaking algorithm that is

‎src/backend/storage/lmgr/deadlock.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.37 2005/12/09 01:22:04 tgl Exp $
15+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.38 2005/12/11 21:02:18 tgl Exp $
1616
*
1717
*Interface:
1818
*
@@ -53,9 +53,9 @@ typedef struct
5353
* Information saved about each edge in a detected deadlock cycle.This
5454
* is used to print a diagnostic message upon failure.
5555
*
56-
* Note: because we want to examine this info after releasing theLockMgrLock,
57-
* we can't just store LOCK and PGPROC pointers; we must extract out all the
58-
* info we want to be able to print.
56+
* Note: because we want to examine this info after releasing thelock
57+
*manager's partition locks,we can't just store LOCK and PGPROC pointers;
58+
*we must extract out all theinfo we want to be able to print.
5959
*/
6060
typedefstruct
6161
{
@@ -188,19 +188,11 @@ InitDeadLockChecking(void)
188188
* deadlock. If resolution is impossible, return TRUE --- the caller
189189
* is then expected to abort the given proc's transaction.
190190
*
191-
* We can't block on user locks, so no sense testing for deadlock
192-
* because there is no blocking, and no timer for the block. So,
193-
* only look at regular locks.
194-
*
195-
* We must have already locked the master lock before being called.
196-
* NOTE: although the lockmethod structure appears to allow each lock
197-
* table to have a different masterLock, all locks that can block had
198-
* better use the same LWLock, else this code will not be adequately
199-
* interlocked!
191+
* Caller must already have locked all partitions of the lock tables.
200192
*
201193
* On failure, deadlock details are recorded in deadlockDetails[] for
202194
* subsequent printing by DeadLockReport(). That activity is separate
203-
* because we don't want to do it while holdingthe master lock.
195+
* because we don't want to do it while holdingall those LWLocks.
204196
*/
205197
bool
206198
DeadLockCheck(PGPROC*proc)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp