Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * lmgr.c
4 : * POSTGRES lock manager code
5 : *
6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/storage/lmgr/lmgr.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include "access/subtrans.h"
19 : #include "access/xact.h"
20 : #include "catalog/catalog.h"
21 : #include "commands/progress.h"
22 : #include "miscadmin.h"
23 : #include "pgstat.h"
24 : #include "storage/lmgr.h"
25 : #include "storage/proc.h"
26 : #include "storage/procarray.h"
27 : #include "utils/inval.h"
28 :
29 :
30 : /*
31 : * Per-backend counter for generating speculative insertion tokens.
32 : *
33 : * This may wrap around, but that's OK as it's only used for the short
34 : * duration between inserting a tuple and checking that there are no (unique)
35 : * constraint violations. It's theoretically possible that a backend sees a
36 : * tuple that was speculatively inserted by another backend, but before it has
37 : * started waiting on the token, the other backend completes its insertion,
38 : * and then performs 2^32 unrelated insertions. And after all that, the
39 : * first backend finally calls SpeculativeInsertionLockAcquire(), with the
40 : * intention of waiting for the first insertion to complete, but ends up
41 : * waiting for the latest unrelated insertion instead. Even then, nothing
42 : * particularly bad happens: in the worst case they deadlock, causing one of
43 : * the transactions to abort.
44 : */
45 : static uint32 speculativeInsertionToken = 0;
46 :
47 :
48 : /*
49 : * Struct to hold context info for transaction lock waits.
50 : *
51 : * 'oper' is the operation that needs to wait for the other transaction; 'rel'
52 : * and 'ctid' specify the address of the tuple being waited for.
53 : */
54 : typedef struct XactLockTableWaitInfo
55 : {
56 : XLTW_Oper oper;
57 : Relation rel;
58 : ItemPointer ctid;
59 : } XactLockTableWaitInfo;
60 :
61 : static void XactLockTableWaitErrorCb(void *arg);
62 :
63 : /*
64 : * RelationInitLockInfo
65 : * Initializes the lock information in a relation descriptor.
66 : *
67 : * relcache.c must call this during creation of any reldesc.
68 : */
69 : void
70 5730888 : RelationInitLockInfo(Relation relation)
71 : {
72 : Assert(RelationIsValid(relation));
73 : Assert(OidIsValid(RelationGetRelid(relation)));
74 :
75 5730888 : relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
76 :
77 5730888 : if (relation->rd_rel->relisshared)
78 859514 : relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
79 : else
80 4871374 : relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
81 5730888 : }
82 :
83 : /*
84 : * SetLocktagRelationOid
85 : * Set up a locktag for a relation, given only relation OID
86 : */
87 : static inline void
88 40633856 : SetLocktagRelationOid(LOCKTAG *tag, Oid relid)
89 : {
90 : Oid dbid;
91 :
92 40633856 : if (IsSharedRelation(relid))
93 1829970 : dbid = InvalidOid;
94 : else
95 38803886 : dbid = MyDatabaseId;
96 :
97 40633856 : SET_LOCKTAG_RELATION(*tag, dbid, relid);
98 40633856 : }
99 :
100 : /*
101 : * LockRelationOid
102 : *
103 : * Lock a relation given only its OID. This should generally be used
104 : * before attempting to open the relation's relcache entry.
105 : */
106 : void
107 40218534 : LockRelationOid(Oid relid, LOCKMODE lockmode)
108 : {
109 : LOCKTAG tag;
110 : LOCALLOCK *locallock;
111 : LockAcquireResult res;
112 :
113 40218534 : SetLocktagRelationOid(&tag, relid);
114 :
115 40218534 : res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock,
116 : false);
117 :
118 : /*
119 : * Now that we have the lock, check for invalidation messages, so that we
120 : * will update or flush any stale relcache entry before we try to use it.
121 : * RangeVarGetRelid() specifically relies on us for this. We can skip
122 : * this in the not-uncommon case that we already had the same type of lock
123 : * being requested, since then no one else could have modified the
124 : * relcache entry in an undesirable way. (In the case where our own xact
125 : * modifies the rel, the relcache update happens via
126 : * CommandCounterIncrement, not here.)
127 : *
128 : * However, in corner cases where code acts on tables (usually catalogs)
129 : * recursively, we might get here while still processing invalidation
130 : * messages in some outer execution of this function or a sibling. The
131 : * "cleared" status of the lock tells us whether we really are done
132 : * absorbing relevant inval messages.
133 : */
134 40218508 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
135 : {
136 36241422 : AcceptInvalidationMessages();
137 36241282 : MarkLockClear(locallock);
138 : }
139 40218368 : }
140 :
141 : /*
142 : * ConditionalLockRelationOid
143 : *
144 : * As above, but only lock if we can get the lock without blocking.
145 : * Returns true iff the lock was acquired.
146 : *
147 : * NOTE: we do not currently need conditional versions of all the
148 : * LockXXX routines in this file, but they could easily be added if needed.
149 : */
150 : bool
151 3204 : ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
152 : {
153 : LOCKTAG tag;
154 : LOCALLOCK *locallock;
155 : LockAcquireResult res;
156 :
157 3204 : SetLocktagRelationOid(&tag, relid);
158 :
159 3204 : res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
160 : false);
161 :
162 3204 : if (res == LOCKACQUIRE_NOT_AVAIL)
163 36 : return false;
164 :
165 : /*
166 : * Now that we have the lock, check for invalidation messages; see notes
167 : * in LockRelationOid.
168 : */
169 3168 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
170 : {
171 3060 : AcceptInvalidationMessages();
172 3060 : MarkLockClear(locallock);
173 : }
174 :
175 3168 : return true;
176 : }
177 :
178 : /*
179 : * LockRelationId
180 : *
181 : * Lock, given a LockRelId. Same as LockRelationOid but take LockRelId as an
182 : * input.
183 : */
184 : void
185 220094 : LockRelationId(LockRelId *relid, LOCKMODE lockmode)
186 : {
187 : LOCKTAG tag;
188 : LOCALLOCK *locallock;
189 : LockAcquireResult res;
190 :
191 220094 : SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
192 :
193 220094 : res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock,
194 : false);
195 :
196 : /*
197 : * Now that we have the lock, check for invalidation messages; see notes
198 : * in LockRelationOid.
199 : */
200 220094 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
201 : {
202 220094 : AcceptInvalidationMessages();
203 220094 : MarkLockClear(locallock);
204 : }
205 220094 : }
206 :
207 : /*
208 : * UnlockRelationId
209 : *
210 : * Unlock, given a LockRelId. This is preferred over UnlockRelationOid
211 : * for speed reasons.
212 : */
213 : void
214 36172208 : UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
215 : {
216 : LOCKTAG tag;
217 :
218 36172208 : SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
219 :
220 36172208 : LockRelease(&tag, lockmode, false);
221 36172208 : }
222 :
223 : /*
224 : * UnlockRelationOid
225 : *
226 : * Unlock, given only a relation Oid. Use UnlockRelationId if you can.
227 : */
228 : void
229 412118 : UnlockRelationOid(Oid relid, LOCKMODE lockmode)
230 : {
231 : LOCKTAG tag;
232 :
233 412118 : SetLocktagRelationOid(&tag, relid);
234 :
235 412118 : LockRelease(&tag, lockmode, false);
236 412118 : }
237 :
238 : /*
239 : * LockRelation
240 : *
241 : * This is a convenience routine for acquiring an additional lock on an
242 : * already-open relation. Never try to do "relation_open(foo, NoLock)"
243 : * and then lock with this.
244 : */
245 : void
246 48598 : LockRelation(Relation relation, LOCKMODE lockmode)
247 : {
248 : LOCKTAG tag;
249 : LOCALLOCK *locallock;
250 : LockAcquireResult res;
251 :
252 48598 : SET_LOCKTAG_RELATION(tag,
253 : relation->rd_lockInfo.lockRelId.dbId,
254 : relation->rd_lockInfo.lockRelId.relId);
255 :
256 48598 : res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock,
257 : false);
258 :
259 : /*
260 : * Now that we have the lock, check for invalidation messages; see notes
261 : * in LockRelationOid.
262 : */
263 48598 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
264 : {
265 48598 : AcceptInvalidationMessages();
266 48598 : MarkLockClear(locallock);
267 : }
268 48598 : }
269 :
270 : /*
271 : * ConditionalLockRelation
272 : *
273 : * This is a convenience routine for acquiring an additional lock on an
274 : * already-open relation. Never try to do "relation_open(foo, NoLock)"
275 : * and then lock with this.
276 : */
277 : bool
278 700 : ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
279 : {
280 : LOCKTAG tag;
281 : LOCALLOCK *locallock;
282 : LockAcquireResult res;
283 :
284 700 : SET_LOCKTAG_RELATION(tag,
285 : relation->rd_lockInfo.lockRelId.dbId,
286 : relation->rd_lockInfo.lockRelId.relId);
287 :
288 700 : res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
289 : false);
290 :
291 700 : if (res == LOCKACQUIRE_NOT_AVAIL)
292 404 : return false;
293 :
294 : /*
295 : * Now that we have the lock, check for invalidation messages; see notes
296 : * in LockRelationOid.
297 : */
298 296 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
299 : {
300 296 : AcceptInvalidationMessages();
301 296 : MarkLockClear(locallock);
302 : }
303 :
304 296 : return true;
305 : }
306 :
307 : /*
308 : * UnlockRelation
309 : *
310 : * This is a convenience routine for unlocking a relation without also
311 : * closing it.
312 : */
313 : void
314 296 : UnlockRelation(Relation relation, LOCKMODE lockmode)
315 : {
316 : LOCKTAG tag;
317 :
318 296 : SET_LOCKTAG_RELATION(tag,
319 : relation->rd_lockInfo.lockRelId.dbId,
320 : relation->rd_lockInfo.lockRelId.relId);
321 :
322 296 : LockRelease(&tag, lockmode, false);
323 296 : }
324 :
325 : /*
326 : * CheckRelationLockedByMe
327 : *
328 : * Returns true if current transaction holds a lock on 'relation' of mode
329 : * 'lockmode'. If 'orstronger' is true, a stronger lockmode is also OK.
330 : * ("Stronger" is defined as "numerically higher", which is a bit
331 : * semantically dubious but is OK for the purposes we use this for.)
332 : */
333 : bool
334 0 : CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
335 : {
336 : LOCKTAG tag;
337 :
338 0 : SET_LOCKTAG_RELATION(tag,
339 : relation->rd_lockInfo.lockRelId.dbId,
340 : relation->rd_lockInfo.lockRelId.relId);
341 :
342 0 : return LockHeldByMe(&tag, lockmode, orstronger);
343 : }
344 :
345 : /*
346 : * CheckRelationOidLockedByMe
347 : *
348 : * Like the above, but takes an OID as argument.
349 : */
350 : bool
351 0 : CheckRelationOidLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger)
352 : {
353 : LOCKTAG tag;
354 :
355 0 : SetLocktagRelationOid(&tag, relid);
356 :
357 0 : return LockHeldByMe(&tag, lockmode, orstronger);
358 : }
359 :
360 : /*
361 : * LockHasWaitersRelation
362 : *
363 : * This is a function to check whether someone else is waiting for a
364 : * lock which we are currently holding.
365 : */
366 : bool
367 0 : LockHasWaitersRelation(Relation relation, LOCKMODE lockmode)
368 : {
369 : LOCKTAG tag;
370 :
371 0 : SET_LOCKTAG_RELATION(tag,
372 : relation->rd_lockInfo.lockRelId.dbId,
373 : relation->rd_lockInfo.lockRelId.relId);
374 :
375 0 : return LockHasWaiters(&tag, lockmode, false);
376 : }
377 :
378 : /*
379 : * LockRelationIdForSession
380 : *
381 : * This routine grabs a session-level lock on the target relation. The
382 : * session lock persists across transaction boundaries. It will be removed
383 : * when UnlockRelationIdForSession() is called, or if an ereport(ERROR) occurs,
384 : * or if the backend exits.
385 : *
386 : * Note that one should also grab a transaction-level lock on the rel
387 : * in any transaction that actually uses the rel, to ensure that the
388 : * relcache entry is up to date.
389 : */
390 : void
391 220088 : LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
392 : {
393 : LOCKTAG tag;
394 :
395 220088 : SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
396 :
397 220088 : (void) LockAcquire(&tag, lockmode, true, false);
398 220088 : }
399 :
400 : /*
401 : * UnlockRelationIdForSession
402 : */
403 : void
404 220044 : UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
405 : {
406 : LOCKTAG tag;
407 :
408 220044 : SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
409 :
410 220044 : LockRelease(&tag, lockmode, true);
411 220044 : }
412 :
413 : /*
414 : * LockRelationForExtension
415 : *
416 : * This lock tag is used to interlock addition of pages to relations.
417 : * We need such locking because bufmgr/smgr definition of P_NEW is not
418 : * race-condition-proof.
419 : *
420 : * We assume the caller is already holding some type of regular lock on
421 : * the relation, so no AcceptInvalidationMessages call is needed here.
422 : */
423 : void
424 321660 : LockRelationForExtension(Relation relation, LOCKMODE lockmode)
425 : {
426 : LOCKTAG tag;
427 :
428 321660 : SET_LOCKTAG_RELATION_EXTEND(tag,
429 : relation->rd_lockInfo.lockRelId.dbId,
430 : relation->rd_lockInfo.lockRelId.relId);
431 :
432 321660 : (void) LockAcquire(&tag, lockmode, false, false);
433 321660 : }
434 :
435 : /*
436 : * ConditionalLockRelationForExtension
437 : *
438 : * As above, but only lock if we can get the lock without blocking.
439 : * Returns true iff the lock was acquired.
440 : */
441 : bool
442 0 : ConditionalLockRelationForExtension(Relation relation, LOCKMODE lockmode)
443 : {
444 : LOCKTAG tag;
445 :
446 0 : SET_LOCKTAG_RELATION_EXTEND(tag,
447 : relation->rd_lockInfo.lockRelId.dbId,
448 : relation->rd_lockInfo.lockRelId.relId);
449 :
450 0 : return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
451 : }
452 :
453 : /*
454 : * RelationExtensionLockWaiterCount
455 : *
456 : * Count the number of processes waiting for the given relation extension lock.
457 : */
458 : int
459 135976 : RelationExtensionLockWaiterCount(Relation relation)
460 : {
461 : LOCKTAG tag;
462 :
463 135976 : SET_LOCKTAG_RELATION_EXTEND(tag,
464 : relation->rd_lockInfo.lockRelId.dbId,
465 : relation->rd_lockInfo.lockRelId.relId);
466 :
467 135976 : return LockWaiterCount(&tag);
468 : }
469 :
470 : /*
471 : * UnlockRelationForExtension
472 : */
473 : void
474 321660 : UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
475 : {
476 : LOCKTAG tag;
477 :
478 321660 : SET_LOCKTAG_RELATION_EXTEND(tag,
479 : relation->rd_lockInfo.lockRelId.dbId,
480 : relation->rd_lockInfo.lockRelId.relId);
481 :
482 321660 : LockRelease(&tag, lockmode, false);
483 321660 : }
484 :
485 : /*
486 : * LockDatabaseFrozenIds
487 : *
488 : * This allows one backend per database to execute vac_update_datfrozenxid().
489 : */
490 : void
491 5156 : LockDatabaseFrozenIds(LOCKMODE lockmode)
492 : {
493 : LOCKTAG tag;
494 :
495 5156 : SET_LOCKTAG_DATABASE_FROZEN_IDS(tag, MyDatabaseId);
496 :
497 5156 : (void) LockAcquire(&tag, lockmode, false, false);
498 5156 : }
499 :
500 : /*
501 : * LockPage
502 : *
503 : * Obtain a page-level lock. This is currently used by some index access
504 : * methods to lock individual index pages.
505 : */
506 : void
507 132 : LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
508 : {
509 : LOCKTAG tag;
510 :
511 132 : SET_LOCKTAG_PAGE(tag,
512 : relation->rd_lockInfo.lockRelId.dbId,
513 : relation->rd_lockInfo.lockRelId.relId,
514 : blkno);
515 :
516 132 : (void) LockAcquire(&tag, lockmode, false, false);
517 132 : }
518 :
519 : /*
520 : * ConditionalLockPage
521 : *
522 : * As above, but only lock if we can get the lock without blocking.
523 : * Returns true iff the lock was acquired.
524 : */
525 : bool
526 0 : ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
527 : {
528 : LOCKTAG tag;
529 :
530 0 : SET_LOCKTAG_PAGE(tag,
531 : relation->rd_lockInfo.lockRelId.dbId,
532 : relation->rd_lockInfo.lockRelId.relId,
533 : blkno);
534 :
535 0 : return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
536 : }
537 :
538 : /*
539 : * UnlockPage
540 : */
541 : void
542 132 : UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
543 : {
544 : LOCKTAG tag;
545 :
546 132 : SET_LOCKTAG_PAGE(tag,
547 : relation->rd_lockInfo.lockRelId.dbId,
548 : relation->rd_lockInfo.lockRelId.relId,
549 : blkno);
550 :
551 132 : LockRelease(&tag, lockmode, false);
552 132 : }
553 :
554 : /*
555 : * LockTuple
556 : *
557 : * Obtain a tuple-level lock. This is used in a less-than-intuitive fashion
558 : * because we can't afford to keep a separate lock in shared memory for every
559 : * tuple. See heap_lock_tuple before using this!
560 : */
561 : void
562 412190 : LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
563 : {
564 : LOCKTAG tag;
565 :
566 412190 : SET_LOCKTAG_TUPLE(tag,
567 : relation->rd_lockInfo.lockRelId.dbId,
568 : relation->rd_lockInfo.lockRelId.relId,
569 : ItemPointerGetBlockNumber(tid),
570 : ItemPointerGetOffsetNumber(tid));
571 :
572 412190 : (void) LockAcquire(&tag, lockmode, false, false);
573 412190 : }
574 :
575 : /*
576 : * ConditionalLockTuple
577 : *
578 : * As above, but only lock if we can get the lock without blocking.
579 : * Returns true iff the lock was acquired.
580 : */
581 : bool
582 82 : ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode,
583 : bool logLockFailure)
584 : {
585 : LOCKTAG tag;
586 :
587 82 : SET_LOCKTAG_TUPLE(tag,
588 : relation->rd_lockInfo.lockRelId.dbId,
589 : relation->rd_lockInfo.lockRelId.relId,
590 : ItemPointerGetBlockNumber(tid),
591 : ItemPointerGetOffsetNumber(tid));
592 :
593 82 : return (LockAcquireExtended(&tag, lockmode, false, true, true, NULL,
594 82 : logLockFailure) != LOCKACQUIRE_NOT_AVAIL);
595 : }
596 :
597 : /*
598 : * UnlockTuple
599 : */
600 : void
601 460362 : UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
602 : {
603 : LOCKTAG tag;
604 :
605 460362 : SET_LOCKTAG_TUPLE(tag,
606 : relation->rd_lockInfo.lockRelId.dbId,
607 : relation->rd_lockInfo.lockRelId.relId,
608 : ItemPointerGetBlockNumber(tid),
609 : ItemPointerGetOffsetNumber(tid));
610 :
611 460362 : LockRelease(&tag, lockmode, false);
612 460362 : }
613 :
614 : /*
615 : * XactLockTableInsert
616 : *
617 : * Insert a lock showing that the given transaction ID is running ---
618 : * this is done when an XID is acquired by a transaction or subtransaction.
619 : * The lock can then be used to wait for the transaction to finish.
620 : */
621 : void
622 271434 : XactLockTableInsert(TransactionId xid)
623 : {
624 : LOCKTAG tag;
625 :
626 271434 : SET_LOCKTAG_TRANSACTION(tag, xid);
627 :
628 271434 : (void) LockAcquire(&tag, ExclusiveLock, false, false);
629 271434 : }
630 :
631 : /*
632 : * XactLockTableDelete
633 : *
634 : * Delete the lock showing that the given transaction ID is running.
635 : * (This is never used for main transaction IDs; those locks are only
636 : * released implicitly at transaction end. But we do use it for subtrans IDs.)
637 : */
638 : void
639 7338 : XactLockTableDelete(TransactionId xid)
640 : {
641 : LOCKTAG tag;
642 :
643 7338 : SET_LOCKTAG_TRANSACTION(tag, xid);
644 :
645 7338 : LockRelease(&tag, ExclusiveLock, false);
646 7338 : }
647 :
648 : /*
649 : * XactLockTableWait
650 : *
651 : * Wait for the specified transaction to commit or abort. If an operation
652 : * is specified, an error context callback is set up. If 'oper' is passed as
653 : * None, no error context callback is set up.
654 : *
655 : * Note that this does the right thing for subtransactions: if we wait on a
656 : * subtransaction, we will exit as soon as it aborts or its top parent commits.
657 : * It takes some extra work to ensure this, because to save on shared memory
658 : * the XID lock of a subtransaction is released when it ends, whether
659 : * successfully or unsuccessfully. So we have to check if it's "still running"
660 : * and if so wait for its parent.
661 : */
662 : void
663 720 : XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid,
664 : XLTW_Oper oper)
665 : {
666 : LOCKTAG tag;
667 : XactLockTableWaitInfo info;
668 : ErrorContextCallback callback;
669 720 : bool first = true;
670 :
671 : /*
672 : * If an operation is specified, set up our verbose error context
673 : * callback.
674 : */
675 720 : if (oper != XLTW_None)
676 : {
677 : Assert(RelationIsValid(rel));
678 : Assert(ItemPointerIsValid(ctid));
679 :
680 678 : info.rel = rel;
681 678 : info.ctid = ctid;
682 678 : info.oper = oper;
683 :
684 678 : callback.callback = XactLockTableWaitErrorCb;
685 678 : callback.arg = &info;
686 678 : callback.previous = error_context_stack;
687 678 : error_context_stack = &callback;
688 : }
689 :
690 : for (;;)
691 : {
692 4 : Assert(TransactionIdIsValid(xid));
693 : Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
694 :
695 724 : SET_LOCKTAG_TRANSACTION(tag, xid);
696 :
697 724 : (void) LockAcquire(&tag, ShareLock, false, false);
698 :
699 710 : LockRelease(&tag, ShareLock, false);
700 :
701 710 : if (!TransactionIdIsInProgress(xid))
702 706 : break;
703 :
704 : /*
705 : * If the Xid belonged to a subtransaction, then the lock would have
706 : * gone away as soon as it was finished; for correct tuple visibility,
707 : * the right action is to wait on its parent transaction to go away.
708 : * But instead of going levels up one by one, we can just wait for the
709 : * topmost transaction to finish with the same end result, which also
710 : * incurs less locktable traffic.
711 : *
712 : * Some uses of this function don't involve tuple visibility -- such
713 : * as when building snapshots for logical decoding. It is possible to
714 : * see a transaction in ProcArray before it registers itself in the
715 : * locktable. The topmost transaction in that case is the same xid,
716 : * so we try again after a short sleep. (Don't sleep the first time
717 : * through, to avoid slowing down the normal case.)
718 : */
719 4 : if (!first)
720 : {
721 0 : CHECK_FOR_INTERRUPTS();
722 0 : pg_usleep(1000L);
723 : }
724 4 : first = false;
725 4 : xid = SubTransGetTopmostTransaction(xid);
726 : }
727 :
728 706 : if (oper != XLTW_None)
729 668 : error_context_stack = callback.previous;
730 706 : }
731 :
732 : /*
733 : * ConditionalXactLockTableWait
734 : *
735 : * As above, but only lock if we can get the lock without blocking.
736 : * Returns true if the lock was acquired.
737 : */
738 : bool
739 90 : ConditionalXactLockTableWait(TransactionId xid, bool logLockFailure)
740 : {
741 : LOCKTAG tag;
742 90 : bool first = true;
743 :
744 : for (;;)
745 : {
746 0 : Assert(TransactionIdIsValid(xid));
747 : Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
748 :
749 90 : SET_LOCKTAG_TRANSACTION(tag, xid);
750 :
751 90 : if (LockAcquireExtended(&tag, ShareLock, false, true, true, NULL,
752 : logLockFailure)
753 : == LOCKACQUIRE_NOT_AVAIL)
754 90 : return false;
755 :
756 0 : LockRelease(&tag, ShareLock, false);
757 :
758 0 : if (!TransactionIdIsInProgress(xid))
759 0 : break;
760 :
761 : /* See XactLockTableWait about this case */
762 0 : if (!first)
763 : {
764 0 : CHECK_FOR_INTERRUPTS();
765 0 : pg_usleep(1000L);
766 : }
767 0 : first = false;
768 0 : xid = SubTransGetTopmostTransaction(xid);
769 : }
770 :
771 0 : return true;
772 : }
773 :
774 : /*
775 : * SpeculativeInsertionLockAcquire
776 : *
777 : * Insert a lock showing that the given transaction ID is inserting a tuple,
778 : * but hasn't yet decided whether it's going to keep it. The lock can then be
779 : * used to wait for the decision to go ahead with the insertion, or aborting
780 : * it.
781 : *
782 : * The token is used to distinguish multiple insertions by the same
783 : * transaction. It is returned to caller.
784 : */
785 : uint32
786 4128 : SpeculativeInsertionLockAcquire(TransactionId xid)
787 : {
788 : LOCKTAG tag;
789 :
790 4128 : speculativeInsertionToken++;
791 :
792 : /*
793 : * Check for wrap-around. Zero means no token is held, so don't use that.
794 : */
795 4128 : if (speculativeInsertionToken == 0)
796 0 : speculativeInsertionToken = 1;
797 :
798 4128 : SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, speculativeInsertionToken);
799 :
800 4128 : (void) LockAcquire(&tag, ExclusiveLock, false, false);
801 :
802 4128 : return speculativeInsertionToken;
803 : }
804 :
805 : /*
806 : * SpeculativeInsertionLockRelease
807 : *
808 : * Delete the lock showing that the given transaction is speculatively
809 : * inserting a tuple.
810 : */
811 : void
812 4122 : SpeculativeInsertionLockRelease(TransactionId xid)
813 : {
814 : LOCKTAG tag;
815 :
816 4122 : SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, speculativeInsertionToken);
817 :
818 4122 : LockRelease(&tag, ExclusiveLock, false);
819 4122 : }
820 :
821 : /*
822 : * SpeculativeInsertionWait
823 : *
824 : * Wait for the specified transaction to finish or abort the insertion of a
825 : * tuple.
826 : */
827 : void
828 2 : SpeculativeInsertionWait(TransactionId xid, uint32 token)
829 : {
830 : LOCKTAG tag;
831 :
832 2 : SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, token);
833 :
834 : Assert(TransactionIdIsValid(xid));
835 : Assert(token != 0);
836 :
837 2 : (void) LockAcquire(&tag, ShareLock, false, false);
838 2 : LockRelease(&tag, ShareLock, false);
839 2 : }
840 :
841 : /*
842 : * XactLockTableWaitErrorCb
843 : * Error context callback for transaction lock waits.
844 : */
845 : static void
846 8 : XactLockTableWaitErrorCb(void *arg)
847 : {
848 8 : XactLockTableWaitInfo *info = (XactLockTableWaitInfo *) arg;
849 :
850 : /*
851 : * We would like to print schema name too, but that would require a
852 : * syscache lookup.
853 : */
854 16 : if (info->oper != XLTW_None &&
855 16 : ItemPointerIsValid(info->ctid) && RelationIsValid(info->rel))
856 : {
857 : const char *cxt;
858 :
859 8 : switch (info->oper)
860 : {
861 0 : case XLTW_Update:
862 0 : cxt = gettext_noop("while updating tuple (%u,%u) in relation \"%s\"");
863 0 : break;
864 8 : case XLTW_Delete:
865 8 : cxt = gettext_noop("while deleting tuple (%u,%u) in relation \"%s\"");
866 8 : break;
867 0 : case XLTW_Lock:
868 0 : cxt = gettext_noop("while locking tuple (%u,%u) in relation \"%s\"");
869 0 : break;
870 0 : case XLTW_LockUpdated:
871 0 : cxt = gettext_noop("while locking updated version (%u,%u) of tuple in relation \"%s\"");
872 0 : break;
873 0 : case XLTW_InsertIndex:
874 0 : cxt = gettext_noop("while inserting index tuple (%u,%u) in relation \"%s\"");
875 0 : break;
876 0 : case XLTW_InsertIndexUnique:
877 0 : cxt = gettext_noop("while checking uniqueness of tuple (%u,%u) in relation \"%s\"");
878 0 : break;
879 0 : case XLTW_FetchUpdated:
880 0 : cxt = gettext_noop("while rechecking updated tuple (%u,%u) in relation \"%s\"");
881 0 : break;
882 0 : case XLTW_RecheckExclusionConstr:
883 0 : cxt = gettext_noop("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"");
884 0 : break;
885 :
886 0 : default:
887 0 : return;
888 : }
889 :
890 16 : errcontext(cxt,
891 8 : ItemPointerGetBlockNumber(info->ctid),
892 8 : ItemPointerGetOffsetNumber(info->ctid),
893 8 : RelationGetRelationName(info->rel));
894 : }
895 : }
896 :
897 : /*
898 : * WaitForLockersMultiple
899 : * Wait until no transaction holds locks that conflict with the given
900 : * locktags at the given lockmode.
901 : *
902 : * To do this, obtain the current list of lockers, and wait on their VXIDs
903 : * until they are finished.
904 : *
905 : * Note we don't try to acquire the locks on the given locktags, only the
906 : * VXIDs and XIDs of their lock holders; if somebody grabs a conflicting lock
907 : * on the objects after we obtained our initial list of lockers, we will not
908 : * wait for them.
909 : */
910 : void
911 2388 : WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
912 : {
913 2388 : List *holders = NIL;
914 : ListCell *lc;
915 2388 : int total = 0;
916 2388 : int done = 0;
917 :
918 : /* Done if no locks to wait for */
919 2388 : if (locktags == NIL)
920 0 : return;
921 :
922 : /* Collect the transactions we need to wait on */
923 5128 : foreach(lc, locktags)
924 : {
925 2740 : LOCKTAG *locktag = lfirst(lc);
926 : int count;
927 :
928 2740 : holders = lappend(holders,
929 2740 : GetLockConflicts(locktag, lockmode,
930 : progress ? &count : NULL));
931 2740 : if (progress)
932 2600 : total += count;
933 : }
934 :
935 2388 : if (progress)
936 2248 : pgstat_progress_update_param(PROGRESS_WAITFOR_TOTAL, total);
937 :
938 : /*
939 : * Note: GetLockConflicts() never reports our own xid, hence we need not
940 : * check for that. Also, prepared xacts are reported and awaited.
941 : */
942 :
943 : /* Finally wait for each such transaction to complete */
944 5078 : foreach(lc, holders)
945 : {
946 2740 : VirtualTransactionId *lockholders = lfirst(lc);
947 :
948 3126 : while (VirtualTransactionIdIsValid(*lockholders))
949 : {
950 : /* If requested, publish who we're going to wait for. */
951 436 : if (progress)
952 : {
953 326 : PGPROC *holder = ProcNumberGetProc(lockholders->procNumber);
954 :
955 326 : if (holder)
956 324 : pgstat_progress_update_param(PROGRESS_WAITFOR_CURRENT_PID,
957 324 : holder->pid);
958 : }
959 436 : VirtualXactLock(*lockholders, true);
960 386 : lockholders++;
961 :
962 386 : if (progress)
963 326 : pgstat_progress_update_param(PROGRESS_WAITFOR_DONE, ++done);
964 : }
965 : }
966 2338 : if (progress)
967 : {
968 2248 : const int index[] = {
969 : PROGRESS_WAITFOR_TOTAL,
970 : PROGRESS_WAITFOR_DONE,
971 : PROGRESS_WAITFOR_CURRENT_PID
972 : };
973 2248 : const int64 values[] = {
974 : 0, 0, 0
975 : };
976 :
977 2248 : pgstat_progress_update_multi_param(3, index, values);
978 : }
979 :
980 2338 : list_free_deep(holders);
981 : }
982 :
983 : /*
984 : * WaitForLockers
985 : *
986 : * Same as WaitForLockersMultiple, for a single lock tag.
987 : */
988 : void
989 570 : WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
990 : {
991 : List *l;
992 :
993 570 : l = list_make1(&heaplocktag);
994 570 : WaitForLockersMultiple(l, lockmode, progress);
995 570 : list_free(l);
996 570 : }
997 :
998 :
999 : /*
1000 : * LockDatabaseObject
1001 : *
1002 : * Obtain a lock on a general object of the current database. Don't use
1003 : * this for shared objects (such as tablespaces). It's unwise to apply it
1004 : * to relations, also, since a lock taken this way will NOT conflict with
1005 : * locks taken via LockRelation and friends.
1006 : */
1007 : void
1008 324344 : LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
1009 : LOCKMODE lockmode)
1010 : {
1011 : LOCKTAG tag;
1012 :
1013 324344 : SET_LOCKTAG_OBJECT(tag,
1014 : MyDatabaseId,
1015 : classid,
1016 : objid,
1017 : objsubid);
1018 :
1019 324344 : (void) LockAcquire(&tag, lockmode, false, false);
1020 :
1021 : /* Make sure syscaches are up-to-date with any changes we waited for */
1022 324344 : AcceptInvalidationMessages();
1023 324344 : }
1024 :
1025 : /*
1026 : * ConditionalLockDatabaseObject
1027 : *
1028 : * As above, but only lock if we can get the lock without blocking.
1029 : * Returns true iff the lock was acquired.
1030 : */
1031 : bool
1032 0 : ConditionalLockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
1033 : LOCKMODE lockmode)
1034 : {
1035 : LOCKTAG tag;
1036 : LOCALLOCK *locallock;
1037 : LockAcquireResult res;
1038 :
1039 0 : SET_LOCKTAG_OBJECT(tag,
1040 : MyDatabaseId,
1041 : classid,
1042 : objid,
1043 : objsubid);
1044 :
1045 0 : res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
1046 : false);
1047 :
1048 0 : if (res == LOCKACQUIRE_NOT_AVAIL)
1049 0 : return false;
1050 :
1051 : /*
1052 : * Now that we have the lock, check for invalidation messages; see notes
1053 : * in LockRelationOid.
1054 : */
1055 0 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
1056 : {
1057 0 : AcceptInvalidationMessages();
1058 0 : MarkLockClear(locallock);
1059 : }
1060 :
1061 0 : return true;
1062 : }
1063 :
1064 : /*
1065 : * UnlockDatabaseObject
1066 : */
1067 : void
1068 1628 : UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
1069 : LOCKMODE lockmode)
1070 : {
1071 : LOCKTAG tag;
1072 :
1073 1628 : SET_LOCKTAG_OBJECT(tag,
1074 : MyDatabaseId,
1075 : classid,
1076 : objid,
1077 : objsubid);
1078 :
1079 1628 : LockRelease(&tag, lockmode, false);
1080 1628 : }
1081 :
1082 : /*
1083 : * LockSharedObject
1084 : *
1085 : * Obtain a lock on a shared-across-databases object.
1086 : */
1087 : void
1088 52912 : LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1089 : LOCKMODE lockmode)
1090 : {
1091 : LOCKTAG tag;
1092 :
1093 52912 : SET_LOCKTAG_OBJECT(tag,
1094 : InvalidOid,
1095 : classid,
1096 : objid,
1097 : objsubid);
1098 :
1099 52912 : (void) LockAcquire(&tag, lockmode, false, false);
1100 :
1101 : /* Make sure syscaches are up-to-date with any changes we waited for */
1102 52910 : AcceptInvalidationMessages();
1103 52910 : }
1104 :
1105 : /*
1106 : * ConditionalLockSharedObject
1107 : *
1108 : * As above, but only lock if we can get the lock without blocking.
1109 : * Returns true iff the lock was acquired.
1110 : */
1111 : bool
1112 6 : ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1113 : LOCKMODE lockmode)
1114 : {
1115 : LOCKTAG tag;
1116 : LOCALLOCK *locallock;
1117 : LockAcquireResult res;
1118 :
1119 6 : SET_LOCKTAG_OBJECT(tag,
1120 : InvalidOid,
1121 : classid,
1122 : objid,
1123 : objsubid);
1124 :
1125 6 : res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
1126 : false);
1127 :
1128 6 : if (res == LOCKACQUIRE_NOT_AVAIL)
1129 0 : return false;
1130 :
1131 : /*
1132 : * Now that we have the lock, check for invalidation messages; see notes
1133 : * in LockRelationOid.
1134 : */
1135 6 : if (res != LOCKACQUIRE_ALREADY_CLEAR)
1136 : {
1137 6 : AcceptInvalidationMessages();
1138 6 : MarkLockClear(locallock);
1139 : }
1140 :
1141 6 : return true;
1142 : }
1143 :
1144 : /*
1145 : * UnlockSharedObject
1146 : */
1147 : void
1148 1658 : UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1149 : LOCKMODE lockmode)
1150 : {
1151 : LOCKTAG tag;
1152 :
1153 1658 : SET_LOCKTAG_OBJECT(tag,
1154 : InvalidOid,
1155 : classid,
1156 : objid,
1157 : objsubid);
1158 :
1159 1658 : LockRelease(&tag, lockmode, false);
1160 1658 : }
1161 :
1162 : /*
1163 : * LockSharedObjectForSession
1164 : *
1165 : * Obtain a session-level lock on a shared-across-databases object.
1166 : * See LockRelationIdForSession for notes about session-level locks.
1167 : */
1168 : void
1169 42 : LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
1170 : LOCKMODE lockmode)
1171 : {
1172 : LOCKTAG tag;
1173 :
1174 42 : SET_LOCKTAG_OBJECT(tag,
1175 : InvalidOid,
1176 : classid,
1177 : objid,
1178 : objsubid);
1179 :
1180 42 : (void) LockAcquire(&tag, lockmode, true, false);
1181 42 : }
1182 :
1183 : /*
1184 : * UnlockSharedObjectForSession
1185 : */
1186 : void
1187 42 : UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
1188 : LOCKMODE lockmode)
1189 : {
1190 : LOCKTAG tag;
1191 :
1192 42 : SET_LOCKTAG_OBJECT(tag,
1193 : InvalidOid,
1194 : classid,
1195 : objid,
1196 : objsubid);
1197 :
1198 42 : LockRelease(&tag, lockmode, true);
1199 42 : }
1200 :
1201 : /*
1202 : * LockApplyTransactionForSession
1203 : *
1204 : * Obtain a session-level lock on a transaction being applied on a logical
1205 : * replication subscriber. See LockRelationIdForSession for notes about
1206 : * session-level locks.
1207 : */
1208 : void
1209 656 : LockApplyTransactionForSession(Oid suboid, TransactionId xid, uint16 objid,
1210 : LOCKMODE lockmode)
1211 : {
1212 : LOCKTAG tag;
1213 :
1214 656 : SET_LOCKTAG_APPLY_TRANSACTION(tag,
1215 : MyDatabaseId,
1216 : suboid,
1217 : xid,
1218 : objid);
1219 :
1220 656 : (void) LockAcquire(&tag, lockmode, true, false);
1221 650 : }
1222 :
1223 : /*
1224 : * UnlockApplyTransactionForSession
1225 : */
1226 : void
1227 640 : UnlockApplyTransactionForSession(Oid suboid, TransactionId xid, uint16 objid,
1228 : LOCKMODE lockmode)
1229 : {
1230 : LOCKTAG tag;
1231 :
1232 640 : SET_LOCKTAG_APPLY_TRANSACTION(tag,
1233 : MyDatabaseId,
1234 : suboid,
1235 : xid,
1236 : objid);
1237 :
1238 640 : LockRelease(&tag, lockmode, true);
1239 640 : }
1240 :
1241 : /*
1242 : * Append a description of a lockable object to buf.
1243 : *
1244 : * Ideally we would print names for the numeric values, but that requires
1245 : * getting locks on system tables, which might cause problems since this is
1246 : * typically used to report deadlock situations.
1247 : */
1248 : void
1249 80 : DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
1250 : {
1251 80 : switch ((LockTagType) tag->locktag_type)
1252 : {
1253 40 : case LOCKTAG_RELATION:
1254 40 : appendStringInfo(buf,
1255 40 : _("relation %u of database %u"),
1256 40 : tag->locktag_field2,
1257 40 : tag->locktag_field1);
1258 40 : break;
1259 0 : case LOCKTAG_RELATION_EXTEND:
1260 0 : appendStringInfo(buf,
1261 0 : _("extension of relation %u of database %u"),
1262 0 : tag->locktag_field2,
1263 0 : tag->locktag_field1);
1264 0 : break;
1265 0 : case LOCKTAG_DATABASE_FROZEN_IDS:
1266 0 : appendStringInfo(buf,
1267 0 : _("pg_database.datfrozenxid of database %u"),
1268 0 : tag->locktag_field1);
1269 0 : break;
1270 0 : case LOCKTAG_PAGE:
1271 0 : appendStringInfo(buf,
1272 0 : _("page %u of relation %u of database %u"),
1273 0 : tag->locktag_field3,
1274 0 : tag->locktag_field2,
1275 0 : tag->locktag_field1);
1276 0 : break;
1277 0 : case LOCKTAG_TUPLE:
1278 0 : appendStringInfo(buf,
1279 0 : _("tuple (%u,%u) of relation %u of database %u"),
1280 0 : tag->locktag_field3,
1281 0 : tag->locktag_field4,
1282 0 : tag->locktag_field2,
1283 0 : tag->locktag_field1);
1284 0 : break;
1285 6 : case LOCKTAG_TRANSACTION:
1286 6 : appendStringInfo(buf,
1287 6 : _("transaction %u"),
1288 6 : tag->locktag_field1);
1289 6 : break;
1290 16 : case LOCKTAG_VIRTUALTRANSACTION:
1291 16 : appendStringInfo(buf,
1292 16 : _("virtual transaction %d/%u"),
1293 16 : tag->locktag_field1,
1294 16 : tag->locktag_field2);
1295 16 : break;
1296 0 : case LOCKTAG_SPECULATIVE_TOKEN:
1297 0 : appendStringInfo(buf,
1298 0 : _("speculative token %u of transaction %u"),
1299 0 : tag->locktag_field2,
1300 0 : tag->locktag_field1);
1301 0 : break;
1302 0 : case LOCKTAG_OBJECT:
1303 0 : appendStringInfo(buf,
1304 0 : _("object %u of class %u of database %u"),
1305 0 : tag->locktag_field3,
1306 0 : tag->locktag_field2,
1307 0 : tag->locktag_field1);
1308 0 : break;
1309 0 : case LOCKTAG_USERLOCK:
1310 : /* reserved for old contrib code, now on pgfoundry */
1311 0 : appendStringInfo(buf,
1312 0 : _("user lock [%u,%u,%u]"),
1313 0 : tag->locktag_field1,
1314 0 : tag->locktag_field2,
1315 0 : tag->locktag_field3);
1316 0 : break;
1317 12 : case LOCKTAG_ADVISORY:
1318 12 : appendStringInfo(buf,
1319 12 : _("advisory lock [%u,%u,%u,%u]"),
1320 12 : tag->locktag_field1,
1321 12 : tag->locktag_field2,
1322 12 : tag->locktag_field3,
1323 12 : tag->locktag_field4);
1324 12 : break;
1325 6 : case LOCKTAG_APPLY_TRANSACTION:
1326 6 : appendStringInfo(buf,
1327 6 : _("remote transaction %u of subscription %u of database %u"),
1328 6 : tag->locktag_field3,
1329 6 : tag->locktag_field2,
1330 6 : tag->locktag_field1);
1331 6 : break;
1332 0 : default:
1333 0 : appendStringInfo(buf,
1334 0 : _("unrecognized locktag type %d"),
1335 0 : (int) tag->locktag_type);
1336 0 : break;
1337 : }
1338 80 : }
1339 :
1340 : /*
1341 : * GetLockNameFromTagType
1342 : *
1343 : * Given locktag type, return the corresponding lock name.
1344 : */
1345 : const char *
1346 14 : GetLockNameFromTagType(uint16 locktag_type)
1347 : {
1348 14 : if (locktag_type > LOCKTAG_LAST_TYPE)
1349 0 : return "???";
1350 14 : return LockTagTypeNames[locktag_type];
1351 : }
|