Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8563cca

Browse files
committed
Simplify shared-memory lock data structures as per recent discussion:
it is sufficient to track whether a backend holds a lock or not, and store information about transaction vs. session locks only in the inside-the-backend LocalLockTable. Since there can now be but one PROCLOCK per lock per backend, LockCountMyLocks() is no longer needed, thus eliminating some O(N^2) behavior when a backend holds many locks. Also simplify the LockAcquire/LockRelease API by passing just a 'sessionLock' boolean instead of a transaction ID. The previous API was designed with the idea that per-transaction lock holding would be important for subtransactions, but now that we have subtransactions we know that this is unwanted. While at it, add an 'isTempObject' parameter to LockAcquire to indicate whether the lock is being taken on a temp table. This is not used just yet, but will be needed shortly for two-phase commit.
1 parent f5835b4 commit 8563cca

File tree

8 files changed

+221
-244
lines changed

8 files changed

+221
-244
lines changed

contrib/userlock/user_locks.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ user_lock(uint32 id1, uint32 id2, LOCKMODE lockmode)
3333

3434
SET_LOCKTAG_USERLOCK(tag, id1, id2);
3535

36-
return (LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
37-
lockmode, true) != LOCKACQUIRE_NOT_AVAIL);
36+
return (LockAcquire(USER_LOCKMETHOD, &tag, false,
37+
lockmode, true, true) != LOCKACQUIRE_NOT_AVAIL);
3838
}
3939

4040
int
@@ -44,7 +44,7 @@ user_unlock(uint32 id1, uint32 id2, LOCKMODE lockmode)
4444

4545
SET_LOCKTAG_USERLOCK(tag, id1, id2);
4646

47-
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
47+
return LockRelease(USER_LOCKMETHOD, &tag, lockmode, true);
4848
}
4949

5050
int

src/backend/commands/vacuum.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.309 2005/05/19 21:35:45 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.310 2005/06/14 22:15:32 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1009,7 +1009,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
10091009
* same process.
10101010
*/
10111011
onerelid = onerel->rd_lockInfo.lockRelId;
1012-
LockRelationForSession(&onerelid, lmode);
1012+
LockRelationForSession(&onerelid, onerel->rd_istemp, lmode);
10131013

10141014
/*
10151015
* Remember the relation's TOAST relation for later

src/backend/storage/lmgr/README

+14-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.16 2005/04/29 22:28:24 tgl Exp $
1+
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.17 2005/06/14 22:15:32 tgl Exp $
22

33

44
LOCKING OVERVIEW
@@ -57,16 +57,17 @@ details.
5757
There are two fundamental lock structures in shared memory: the
5858
per-lockable-object LOCK struct, and the per-lock-and-requestor PROCLOCK
5959
struct. A LOCK object exists for each lockable object that currently has
60-
locks held or requested on it. A PROCLOCK struct exists for each transaction
60+
locks held or requested on it. A PROCLOCK struct exists for each backend
6161
that is holding or requesting lock(s) on each LOCK object.
6262

6363
In addition to these, each backend maintains an unshared LOCALLOCK structure
6464
for each lockable object and lock mode that it is currently holding or
6565
requesting. The shared lock structures only allow a single lock grant to
66-
be made per lockable object/lock mode/transaction. Internally to a backend,
66+
be made per lockable object/lock mode/backend. Internally to a backend,
6767
however, the same lock may be requested and perhaps released multiple times
68-
in a transaction. The internal request counts are held in LOCALLOCK so that
69-
the shared LockMgrLock need not be obtained to alter them.
68+
in a transaction, and it can also be held both transactionally and session-
69+
wide. The internal request counts are held in LOCALLOCK so that the shared
70+
LockMgrLock need not be obtained to alter them.
7071

7172
---------------------------------------------------------------------------
7273

@@ -112,9 +113,8 @@ nRequested -
112113
acquired. The count includes attempts by processes which were put
113114
to sleep due to conflicts. It also counts the same backend twice
114115
if, for example, a backend process first acquires a read and then
115-
acquires a write, or acquires the lock under two different transaction
116-
IDs. (But multiple acquisitions of the same lock/lock mode under the
117-
same transaction ID are not multiply counted here; they are recorded
116+
acquires a write. (But multiple acquisitions of the same lock/lock mode
117+
within a backend are not multiply counted here; they are recorded
118118
only in the backend's LOCALLOCK structure.)
119119

120120
requested -
@@ -153,23 +153,17 @@ tag -
153153
tag.proc
154154
SHMEM offset of PROC of backend process that owns this PROCLOCK.
155155

156-
tag.xid
157-
XID of transaction this PROCLOCK is for, or InvalidTransactionId
158-
if the PROCLOCK is for session-level locking.
159-
160-
Note that this structure will support multiple transactions running
161-
concurrently in one backend. Currently we do not use it for that
162-
purpose: subtransactions acquire locks in the name of their top parent
163-
transaction, to simplify reassigning lock ownership at subtransaction end.
164-
So the XID field is really only needed to distinguish per-transaction
165-
locks from session locks. User locks are always session locks, and we
166-
also use session locks for multi-transaction operations like VACUUM.
167-
168156
holdMask -
169157
A bitmask for the lock types successfully acquired by this PROCLOCK.
170158
This should be a subset of the LOCK object's grantMask, and also a
171159
subset of the PGPROC object's heldLocks mask.
172160

161+
releaseMask -
162+
A bitmask for the lock types due to be released during LockReleaseAll.
163+
This must be a subset of the holdMask. Note that it is modified without
164+
taking the LockMgrLock, and therefore it is unsafe for any backend except
165+
the one owning the PROCLOCK to examine/change it.
166+
173167
lockLink -
174168
List link for shared memory queue of all the PROCLOCK objects for the
175169
same LOCK.

src/backend/storage/lmgr/lmgr.c

+39-38
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.75 2005/05/29 22:45:02 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.76 2005/06/14 22:15:32 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -142,8 +142,8 @@ LockRelation(Relation relation, LOCKMODE lockmode)
142142
relation->rd_lockInfo.lockRelId.dbId,
143143
relation->rd_lockInfo.lockRelId.relId);
144144

145-
res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
146-
lockmode, false);
145+
res = LockAcquire(LockTableId, &tag, relation->rd_istemp,
146+
lockmode, false, false);
147147

148148
/*
149149
* Check to see if the relcache entry has been invalidated while we
@@ -179,8 +179,8 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
179179
relation->rd_lockInfo.lockRelId.dbId,
180180
relation->rd_lockInfo.lockRelId.relId);
181181

182-
res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
183-
lockmode, true);
182+
res = LockAcquire(LockTableId, &tag, relation->rd_istemp,
183+
lockmode, false, true);
184184

185185
if (res == LOCKACQUIRE_NOT_AVAIL)
186186
return false;
@@ -214,7 +214,7 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
214214
relation->rd_lockInfo.lockRelId.dbId,
215215
relation->rd_lockInfo.lockRelId.relId);
216216

217-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
217+
LockRelease(LockTableId, &tag, lockmode, false);
218218
}
219219

220220
/*
@@ -230,14 +230,14 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
230230
* relcache entry is up to date.
231231
*/
232232
void
233-
LockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
233+
LockRelationForSession(LockRelId *relid, bool istemprel, LOCKMODE lockmode)
234234
{
235235
LOCKTAG tag;
236236

237237
SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
238238

239-
(void) LockAcquire(LockTableId, &tag, InvalidTransactionId,
240-
lockmode, false);
239+
(void) LockAcquire(LockTableId, &tag, istemprel,
240+
lockmode, true, false);
241241
}
242242

243243
/*
@@ -250,7 +250,7 @@ UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
250250

251251
SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
252252

253-
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
253+
LockRelease(LockTableId, &tag, lockmode, true);
254254
}
255255

256256
/*
@@ -272,8 +272,8 @@ LockRelationForExtension(Relation relation, LOCKMODE lockmode)
272272
relation->rd_lockInfo.lockRelId.dbId,
273273
relation->rd_lockInfo.lockRelId.relId);
274274

275-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
276-
lockmode, false);
275+
(void) LockAcquire(LockTableId, &tag, relation->rd_istemp,
276+
lockmode, false, false);
277277
}
278278

279279
/*
@@ -288,7 +288,7 @@ UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
288288
relation->rd_lockInfo.lockRelId.dbId,
289289
relation->rd_lockInfo.lockRelId.relId);
290290

291-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
291+
LockRelease(LockTableId, &tag, lockmode, false);
292292
}
293293

294294
/*
@@ -307,8 +307,8 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
307307
relation->rd_lockInfo.lockRelId.relId,
308308
blkno);
309309

310-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
311-
lockmode, false);
310+
(void) LockAcquire(LockTableId, &tag, relation->rd_istemp,
311+
lockmode, false, false);
312312
}
313313

314314
/*
@@ -327,8 +327,8 @@ ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
327327
relation->rd_lockInfo.lockRelId.relId,
328328
blkno);
329329

330-
return (LockAcquire(LockTableId, &tag, GetTopTransactionId(),
331-
lockmode, true) != LOCKACQUIRE_NOT_AVAIL);
330+
return (LockAcquire(LockTableId, &tag, relation->rd_istemp,
331+
lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
332332
}
333333

334334
/*
@@ -344,7 +344,7 @@ UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
344344
relation->rd_lockInfo.lockRelId.relId,
345345
blkno);
346346

347-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
347+
LockRelease(LockTableId, &tag, lockmode, false);
348348
}
349349

350350
/*
@@ -365,8 +365,8 @@ LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
365365
ItemPointerGetBlockNumber(tid),
366366
ItemPointerGetOffsetNumber(tid));
367367

368-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
369-
lockmode, false);
368+
(void) LockAcquire(LockTableId, &tag, relation->rd_istemp,
369+
lockmode, false, false);
370370
}
371371

372372
/*
@@ -383,7 +383,7 @@ UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
383383
ItemPointerGetBlockNumber(tid),
384384
ItemPointerGetOffsetNumber(tid));
385385

386-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
386+
LockRelease(LockTableId, &tag, lockmode, false);
387387
}
388388

389389
/*
@@ -400,8 +400,8 @@ XactLockTableInsert(TransactionId xid)
400400

401401
SET_LOCKTAG_TRANSACTION(tag, xid);
402402

403-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
404-
ExclusiveLock, false);
403+
(void) LockAcquire(LockTableId, &tag, false,
404+
ExclusiveLock, false, false);
405405
}
406406

407407
/*
@@ -419,7 +419,7 @@ XactLockTableDelete(TransactionId xid)
419419

420420
SET_LOCKTAG_TRANSACTION(tag, xid);
421421

422-
LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock);
422+
LockRelease(LockTableId, &tag, ExclusiveLock, false);
423423
}
424424

425425
/*
@@ -438,19 +438,18 @@ void
438438
XactLockTableWait(TransactionId xid)
439439
{
440440
LOCKTAG tag;
441-
TransactionId myxid = GetTopTransactionId();
442441

443442
for (;;)
444443
{
445444
Assert(TransactionIdIsValid(xid));
446-
Assert(!TransactionIdEquals(xid, myxid));
445+
Assert(!TransactionIdEquals(xid, GetTopTransactionId()));
447446

448447
SET_LOCKTAG_TRANSACTION(tag, xid);
449448

450-
(void) LockAcquire(LockTableId, &tag, myxid,
451-
ShareLock, false);
449+
(void) LockAcquire(LockTableId, &tag, false,
450+
ShareLock, false, false);
452451

453-
LockRelease(LockTableId, &tag, myxid, ShareLock);
452+
LockRelease(LockTableId, &tag, ShareLock, false);
454453

455454
if (!TransactionIdIsInProgress(xid))
456455
break;
@@ -470,9 +469,11 @@ XactLockTableWait(TransactionId xid)
470469
* LockDatabaseObject
471470
*
472471
* Obtain a lock on a general object of the current database. Don't use
473-
* this for shared objects (such as tablespaces). It's usually unwise to
474-
* apply it to entire relations, also, since a lock taken this way will
475-
* NOT conflict with LockRelation.
472+
* this for shared objects (such as tablespaces). It's unwise to apply it
473+
* to relations, also, since a lock taken this way will NOT conflict with
474+
* LockRelation, and also may be wrongly marked if the relation is temp.
475+
* (If we ever invent temp objects that aren't tables, we'll want to extend
476+
* the API of this routine to include an isTempObject flag.)
476477
*/
477478
void
478479
LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
@@ -486,8 +487,8 @@ LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
486487
objid,
487488
objsubid);
488489

489-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
490-
lockmode, false);
490+
(void) LockAcquire(LockTableId, &tag, false,
491+
lockmode, false, false);
491492
}
492493

493494
/*
@@ -505,7 +506,7 @@ UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
505506
objid,
506507
objsubid);
507508

508-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
509+
LockRelease(LockTableId, &tag, lockmode, false);
509510
}
510511

511512
/*
@@ -525,8 +526,8 @@ LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
525526
objid,
526527
objsubid);
527528

528-
(void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
529-
lockmode, false);
529+
(void) LockAcquire(LockTableId, &tag, false,
530+
lockmode, false, false);
530531
}
531532

532533
/*
@@ -544,5 +545,5 @@ UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
544545
objid,
545546
objsubid);
546547

547-
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
548+
LockRelease(LockTableId, &tag, lockmode, false);
548549
}

0 commit comments

Comments
 (0)