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