Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
lmgr.c
Go to the documentation of this file.
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 */
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 */
55{
60
61static 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 */
69void
71{
72 Assert(RelationIsValid(relation));
74
75 relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
76
77 if (relation->rd_rel->relisshared)
79 else
81}
82
83/*
84 * SetLocktagRelationOid
85 * Set up a locktag for a relation, given only relation OID
86 */
87static inline void
89{
90 Oid dbid;
91
92 if (IsSharedRelation(relid))
93 dbid = InvalidOid;
94 else
95 dbid = MyDatabaseId;
96
97 SET_LOCKTAG_RELATION(*tag, dbid, relid);
98}
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 */
106void
108{
109 LOCKTAG tag;
110 LOCALLOCK *locallock;
112
113 SetLocktagRelationOid(&tag, relid);
114
115 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 if (res != LOCKACQUIRE_ALREADY_CLEAR)
135 {
137 MarkLockClear(locallock);
138 }
139}
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 */
150bool
152{
153 LOCKTAG tag;
154 LOCALLOCK *locallock;
156
157 SetLocktagRelationOid(&tag, relid);
158
159 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
160 false);
161
162 if (res == LOCKACQUIRE_NOT_AVAIL)
163 return false;
164
165 /*
166 * Now that we have the lock, check for invalidation messages; see notes
167 * in LockRelationOid.
168 */
169 if (res != LOCKACQUIRE_ALREADY_CLEAR)
170 {
172 MarkLockClear(locallock);
173 }
174
175 return true;
176}
177
178/*
179 * LockRelationId
180 *
181 * Lock, given a LockRelId. Same as LockRelationOid but take LockRelId as an
182 * input.
183 */
184void
186{
187 LOCKTAG tag;
188 LOCALLOCK *locallock;
190
191 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
192
193 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 if (res != LOCKACQUIRE_ALREADY_CLEAR)
201 {
203 MarkLockClear(locallock);
204 }
205}
206
207/*
208 * UnlockRelationId
209 *
210 * Unlock, given a LockRelId. This is preferred over UnlockRelationOid
211 * for speed reasons.
212 */
213void
215{
216 LOCKTAG tag;
217
218 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
219
220 LockRelease(&tag, lockmode, false);
221}
222
223/*
224 * UnlockRelationOid
225 *
226 * Unlock, given only a relation Oid. Use UnlockRelationId if you can.
227 */
228void
230{
231 LOCKTAG tag;
232
233 SetLocktagRelationOid(&tag, relid);
234
235 LockRelease(&tag, lockmode, false);
236}
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 */
245void
246LockRelation(Relation relation, LOCKMODE lockmode)
247{
248 LOCKTAG tag;
249 LOCALLOCK *locallock;
251
253 relation->rd_lockInfo.lockRelId.dbId,
254 relation->rd_lockInfo.lockRelId.relId);
255
256 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 if (res != LOCKACQUIRE_ALREADY_CLEAR)
264 {
266 MarkLockClear(locallock);
267 }
268}
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 */
277bool
279{
280 LOCKTAG tag;
281 LOCALLOCK *locallock;
283
285 relation->rd_lockInfo.lockRelId.dbId,
286 relation->rd_lockInfo.lockRelId.relId);
287
288 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
289 false);
290
291 if (res == LOCKACQUIRE_NOT_AVAIL)
292 return false;
293
294 /*
295 * Now that we have the lock, check for invalidation messages; see notes
296 * in LockRelationOid.
297 */
298 if (res != LOCKACQUIRE_ALREADY_CLEAR)
299 {
301 MarkLockClear(locallock);
302 }
303
304 return true;
305}
306
307/*
308 * UnlockRelation
309 *
310 * This is a convenience routine for unlocking a relation without also
311 * closing it.
312 */
313void
315{
316 LOCKTAG tag;
317
319 relation->rd_lockInfo.lockRelId.dbId,
320 relation->rd_lockInfo.lockRelId.relId);
321
322 LockRelease(&tag, lockmode, false);
323}
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 */
333bool
334CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
335{
336 LOCKTAG tag;
337
339 relation->rd_lockInfo.lockRelId.dbId,
340 relation->rd_lockInfo.lockRelId.relId);
341
342 return LockHeldByMe(&tag, lockmode, orstronger);
343}
344
345/*
346 * CheckRelationOidLockedByMe
347 *
348 * Like the above, but takes an OID as argument.
349 */
350bool
351CheckRelationOidLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger)
352{
353 LOCKTAG tag;
354
355 SetLocktagRelationOid(&tag, relid);
356
357 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 */
366bool
368{
369 LOCKTAG tag;
370
372 relation->rd_lockInfo.lockRelId.dbId,
373 relation->rd_lockInfo.lockRelId.relId);
374
375 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 */
390void
392{
393 LOCKTAG tag;
394
395 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
396
397 (void) LockAcquire(&tag, lockmode, true, false);
398}
399
400/*
401 * UnlockRelationIdForSession
402 */
403void
405{
406 LOCKTAG tag;
407
408 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
409
410 LockRelease(&tag, lockmode, true);
411}
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 */
423void
425{
426 LOCKTAG tag;
427
429 relation->rd_lockInfo.lockRelId.dbId,
430 relation->rd_lockInfo.lockRelId.relId);
431
432 (void) LockAcquire(&tag, lockmode, false, false);
433}
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 */
441bool
443{
444 LOCKTAG tag;
445
447 relation->rd_lockInfo.lockRelId.dbId,
448 relation->rd_lockInfo.lockRelId.relId);
449
450 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 */
458int
460{
461 LOCKTAG tag;
462
464 relation->rd_lockInfo.lockRelId.dbId,
465 relation->rd_lockInfo.lockRelId.relId);
466
467 return LockWaiterCount(&tag);
468}
469
470/*
471 * UnlockRelationForExtension
472 */
473void
475{
476 LOCKTAG tag;
477
479 relation->rd_lockInfo.lockRelId.dbId,
480 relation->rd_lockInfo.lockRelId.relId);
481
482 LockRelease(&tag, lockmode, false);
483}
484
485/*
486 * LockDatabaseFrozenIds
487 *
488 * This allows one backend per database to execute vac_update_datfrozenxid().
489 */
490void
492{
493 LOCKTAG tag;
494
496
497 (void) LockAcquire(&tag, lockmode, false, false);
498}
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 */
506void
507LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
508{
509 LOCKTAG tag;
510
512 relation->rd_lockInfo.lockRelId.dbId,
513 relation->rd_lockInfo.lockRelId.relId,
514 blkno);
515
516 (void) LockAcquire(&tag, lockmode, false, false);
517}
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 */
525bool
527{
528 LOCKTAG tag;
529
531 relation->rd_lockInfo.lockRelId.dbId,
532 relation->rd_lockInfo.lockRelId.relId,
533 blkno);
534
535 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
536}
537
538/*
539 * UnlockPage
540 */
541void
542UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
543{
544 LOCKTAG tag;
545
547 relation->rd_lockInfo.lockRelId.dbId,
548 relation->rd_lockInfo.lockRelId.relId,
549 blkno);
550
551 LockRelease(&tag, lockmode, false);
552}
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 */
561void
562LockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
563{
564 LOCKTAG tag;
565
567 relation->rd_lockInfo.lockRelId.dbId,
568 relation->rd_lockInfo.lockRelId.relId,
571
572 (void) LockAcquire(&tag, lockmode, false, false);
573}
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 */
581bool
583 bool logLockFailure)
584{
585 LOCKTAG tag;
586
588 relation->rd_lockInfo.lockRelId.dbId,
589 relation->rd_lockInfo.lockRelId.relId,
592
593 return (LockAcquireExtended(&tag, lockmode, false, true, true, NULL,
594 logLockFailure) != LOCKACQUIRE_NOT_AVAIL);
595}
596
597/*
598 * UnlockTuple
599 */
600void
601UnlockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
602{
603 LOCKTAG tag;
604
606 relation->rd_lockInfo.lockRelId.dbId,
607 relation->rd_lockInfo.lockRelId.relId,
610
611 LockRelease(&tag, lockmode, false);
612}
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 */
621void
623{
624 LOCKTAG tag;
625
626 SET_LOCKTAG_TRANSACTION(tag, xid);
627
628 (void) LockAcquire(&tag, ExclusiveLock, false, false);
629}
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 */
638void
640{
641 LOCKTAG tag;
642
643 SET_LOCKTAG_TRANSACTION(tag, xid);
644
645 LockRelease(&tag, ExclusiveLock, false);
646}
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 */
662void
665{
666 LOCKTAG tag;
669 bool first = true;
670
671 /*
672 * If an operation is specified, set up our verbose error context
673 * callback.
674 */
675 if (oper != XLTW_None)
676 {
679
680 info.rel = rel;
681 info.ctid = ctid;
682 info.oper = oper;
683
685 callback.arg = &info;
686 callback.previous = error_context_stack;
688 }
689
690 for (;;)
691 {
694
695 SET_LOCKTAG_TRANSACTION(tag, xid);
696
697 (void) LockAcquire(&tag, ShareLock, false, false);
698
699 LockRelease(&tag, ShareLock, false);
700
702 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 if (!first)
720 {
722 pg_usleep(1000L);
723 }
724 first = false;
726 }
727
728 if (oper != XLTW_None)
729 error_context_stack = callback.previous;
730}
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 */
738bool
740{
741 LOCKTAG tag;
742 bool first = true;
743
744 for (;;)
745 {
748
749 SET_LOCKTAG_TRANSACTION(tag, xid);
750
751 if (LockAcquireExtended(&tag, ShareLock, false, true, true, NULL,
752 logLockFailure)
754 return false;
755
756 LockRelease(&tag, ShareLock, false);
757
759 break;
760
761 /* See XactLockTableWait about this case */
762 if (!first)
763 {
765 pg_usleep(1000L);
766 }
767 first = false;
769 }
770
771 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 */
785uint32
787{
788 LOCKTAG tag;
789
791
792 /*
793 * Check for wrap-around. Zero means no token is held, so don't use that.
794 */
797
799
800 (void) LockAcquire(&tag, ExclusiveLock, false, false);
801
803}
804
805/*
806 * SpeculativeInsertionLockRelease
807 *
808 * Delete the lock showing that the given transaction is speculatively
809 * inserting a tuple.
810 */
811void
813{
814 LOCKTAG tag;
815
817
818 LockRelease(&tag, ExclusiveLock, false);
819}
820
821/*
822 * SpeculativeInsertionWait
823 *
824 * Wait for the specified transaction to finish or abort the insertion of a
825 * tuple.
826 */
827void
829{
830 LOCKTAG tag;
831
833
835 Assert(token != 0);
836
837 (void) LockAcquire(&tag, ShareLock, false, false);
838 LockRelease(&tag, ShareLock, false);
839}
840
841/*
842 * XactLockTableWaitErrorCb
843 * Error context callback for transaction lock waits.
844 */
845static void
847{
849
850 /*
851 * We would like to print schema name too, but that would require a
852 * syscache lookup.
853 */
854 if (info->oper != XLTW_None &&
856 {
857 const char *cxt;
858
859 switch (info->oper)
860 {
861 case XLTW_Update:
862 cxt = gettext_noop("while updating tuple (%u,%u) in relation \"%s\"");
863 break;
864 case XLTW_Delete:
865 cxt = gettext_noop("while deleting tuple (%u,%u) in relation \"%s\"");
866 break;
867 case XLTW_Lock:
868 cxt = gettext_noop("while locking tuple (%u,%u) in relation \"%s\"");
869 break;
870 case XLTW_LockUpdated:
871 cxt = gettext_noop("while locking updated version (%u,%u) of tuple in relation \"%s\"");
872 break;
873 case XLTW_InsertIndex:
874 cxt = gettext_noop("while inserting index tuple (%u,%u) in relation \"%s\"");
875 break;
877 cxt = gettext_noop("while checking uniqueness of tuple (%u,%u) in relation \"%s\"");
878 break;
880 cxt = gettext_noop("while rechecking updated tuple (%u,%u) in relation \"%s\"");
881 break;
883 cxt = gettext_noop("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"");
884 break;
885
886 default:
887 return;
888 }
889
890 errcontext(cxt,
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 */
910void
912{
913 List *holders = NIL;
914 ListCell *lc;
915 int total = 0;
916 int done = 0;
917
918 /* Done if no locks to wait for */
919 if (locktags == NIL)
920 return;
921
922 /* Collect the transactions we need to wait on */
923 foreach(lc, locktags)
924 {
925 LOCKTAG *locktag = lfirst(lc);
926 int count;
927
928 holders = lappend(holders,
929 GetLockConflicts(locktag, lockmode,
930 progress ? &count : NULL));
931 if (progress)
932 total += count;
933 }
934
935 if (progress)
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 foreach(lc, holders)
945 {
946 VirtualTransactionId *lockholders = lfirst(lc);
947
948 while (VirtualTransactionIdIsValid(*lockholders))
949 {
950 /* If requested, publish who we're going to wait for. */
951 if (progress)
952 {
953 PGPROC *holder = ProcNumberGetProc(lockholders->procNumber);
954
955 if (holder)
957 holder->pid);
958 }
959 VirtualXactLock(*lockholders, true);
960 lockholders++;
961
962 if (progress)
964 }
965 }
966 if (progress)
967 {
968 const int index[] = {
972 };
973 const int64 values[] = {
974 0, 0, 0
975 };
976
978 }
979
980 list_free_deep(holders);
981}
982
983/*
984 * WaitForLockers
985 *
986 * Same as WaitForLockersMultiple, for a single lock tag.
987 */
988void
989WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
990{
991 List *l;
992
993 l = list_make1(&heaplocktag);
994 WaitForLockersMultiple(l, lockmode, progress);
995 list_free(l);
996}
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 */
1007void
1008LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
1009 LOCKMODE lockmode)
1010{
1011 LOCKTAG tag;
1012
1015 classid,
1016 objid,
1017 objsubid);
1018
1019 (void) LockAcquire(&tag, lockmode, false, false);
1020
1021 /* Make sure syscaches are up-to-date with any changes we waited for */
1023}
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 */
1031bool
1033 LOCKMODE lockmode)
1034{
1035 LOCKTAG tag;
1036 LOCALLOCK *locallock;
1038
1041 classid,
1042 objid,
1043 objsubid);
1044
1045 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
1046 false);
1047
1048 if (res == LOCKACQUIRE_NOT_AVAIL)
1049 return false;
1050
1051 /*
1052 * Now that we have the lock, check for invalidation messages; see notes
1053 * in LockRelationOid.
1054 */
1055 if (res != LOCKACQUIRE_ALREADY_CLEAR)
1056 {
1058 MarkLockClear(locallock);
1059 }
1060
1061 return true;
1062}
1063
1064/*
1065 * UnlockDatabaseObject
1066 */
1067void
1068UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
1069 LOCKMODE lockmode)
1070{
1071 LOCKTAG tag;
1072
1075 classid,
1076 objid,
1077 objsubid);
1078
1079 LockRelease(&tag, lockmode, false);
1080}
1081
1082/*
1083 * LockSharedObject
1084 *
1085 * Obtain a lock on a shared-across-databases object.
1086 */
1087void
1088LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1089 LOCKMODE lockmode)
1090{
1091 LOCKTAG tag;
1092
1094 InvalidOid,
1095 classid,
1096 objid,
1097 objsubid);
1098
1099 (void) LockAcquire(&tag, lockmode, false, false);
1100
1101 /* Make sure syscaches are up-to-date with any changes we waited for */
1103}
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 */
1111bool
1113 LOCKMODE lockmode)
1114{
1115 LOCKTAG tag;
1116 LOCALLOCK *locallock;
1118
1120 InvalidOid,
1121 classid,
1122 objid,
1123 objsubid);
1124
1125 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
1126 false);
1127
1128 if (res == LOCKACQUIRE_NOT_AVAIL)
1129 return false;
1130
1131 /*
1132 * Now that we have the lock, check for invalidation messages; see notes
1133 * in LockRelationOid.
1134 */
1135 if (res != LOCKACQUIRE_ALREADY_CLEAR)
1136 {
1138 MarkLockClear(locallock);
1139 }
1140
1141 return true;
1142}
1143
1144/*
1145 * UnlockSharedObject
1146 */
1147void
1148UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1149 LOCKMODE lockmode)
1150{
1151 LOCKTAG tag;
1152
1154 InvalidOid,
1155 classid,
1156 objid,
1157 objsubid);
1158
1159 LockRelease(&tag, lockmode, false);
1160}
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 */
1168void
1169LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
1170 LOCKMODE lockmode)
1171{
1172 LOCKTAG tag;
1173
1175 InvalidOid,
1176 classid,
1177 objid,
1178 objsubid);
1179
1180 (void) LockAcquire(&tag, lockmode, true, false);
1181}
1182
1183/*
1184 * UnlockSharedObjectForSession
1185 */
1186void
1188 LOCKMODE lockmode)
1189{
1190 LOCKTAG tag;
1191
1193 InvalidOid,
1194 classid,
1195 objid,
1196 objsubid);
1197
1198 LockRelease(&tag, lockmode, true);
1199}
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 */
1208void
1210 LOCKMODE lockmode)
1211{
1212 LOCKTAG tag;
1213
1216 suboid,
1217 xid,
1218 objid);
1219
1220 (void) LockAcquire(&tag, lockmode, true, false);
1221}
1222
1223/*
1224 * UnlockApplyTransactionForSession
1225 */
1226void
1228 LOCKMODE lockmode)
1229{
1230 LOCKTAG tag;
1231
1234 suboid,
1235 xid,
1236 objid);
1237
1238 LockRelease(&tag, lockmode, true);
1239}
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 */
1248void
1250{
1251 switch ((LockTagType) tag->locktag_type)
1252 {
1253 case LOCKTAG_RELATION:
1255 _("relation %u of database %u"),
1256 tag->locktag_field2,
1257 tag->locktag_field1);
1258 break;
1261 _("extension of relation %u of database %u"),
1262 tag->locktag_field2,
1263 tag->locktag_field1);
1264 break;
1267 _("pg_database.datfrozenxid of database %u"),
1268 tag->locktag_field1);
1269 break;
1270 case LOCKTAG_PAGE:
1272 _("page %u of relation %u of database %u"),
1273 tag->locktag_field3,
1274 tag->locktag_field2,
1275 tag->locktag_field1);
1276 break;
1277 case LOCKTAG_TUPLE:
1279 _("tuple (%u,%u) of relation %u of database %u"),
1280 tag->locktag_field3,
1281 tag->locktag_field4,
1282 tag->locktag_field2,
1283 tag->locktag_field1);
1284 break;
1287 _("transaction %u"),
1288 tag->locktag_field1);
1289 break;
1292 _("virtual transaction %d/%u"),
1293 tag->locktag_field1,
1294 tag->locktag_field2);
1295 break;
1298 _("speculative token %u of transaction %u"),
1299 tag->locktag_field2,
1300 tag->locktag_field1);
1301 break;
1302 case LOCKTAG_OBJECT:
1304 _("object %u of class %u of database %u"),
1305 tag->locktag_field3,
1306 tag->locktag_field2,
1307 tag->locktag_field1);
1308 break;
1309 case LOCKTAG_USERLOCK:
1310 /* reserved for old contrib code, now on pgfoundry */
1312 _("user lock [%u,%u,%u]"),
1313 tag->locktag_field1,
1314 tag->locktag_field2,
1315 tag->locktag_field3);
1316 break;
1317 case LOCKTAG_ADVISORY:
1319 _("advisory lock [%u,%u,%u,%u]"),
1320 tag->locktag_field1,
1321 tag->locktag_field2,
1322 tag->locktag_field3,
1323 tag->locktag_field4);
1324 break;
1327 _("remote transaction %u of subscription %u of database %u"),
1328 tag->locktag_field3,
1329 tag->locktag_field2,
1330 tag->locktag_field1);
1331 break;
1332 default:
1334 _("unrecognized locktag type %d"),
1335 (int) tag->locktag_type);
1336 break;
1337 }
1338}
1339
1340/*
1341 * GetLockNameFromTagType
1342 *
1343 * Given locktag type, return the corresponding lock name.
1344 */
1345const char *
1347{
1348 if (locktag_type > LOCKTAG_LAST_TYPE)
1349 return "???";
1350 return LockTagTypeNames[locktag_type];
1351}
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define gettext_noop(x)
Definition: c.h:1196
int64_t int64
Definition: c.h:536
uint16_t uint16
Definition: c.h:538
uint32_t uint32
Definition: c.h:539
uint32 TransactionId
Definition: c.h:658
#define OidIsValid(objectId)
Definition: c.h:775
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:304
ErrorContextCallback * error_context_stack
Definition: elog.c:95
#define _(x)
Definition: elog.c:91
#define errcontext
Definition: elog.h:198
Oid MyDatabaseId
Definition: globals.c:94
Assert(PointerIsAligned(start, uint64))
void AcceptInvalidationMessages(void)
Definition: inval.c:930
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition: itemptr.h:83
List * lappend(List *list, void *datum)
Definition: list.c:339
void list_free(List *list)
Definition: list.c:1546
void list_free_deep(List *list)
Definition: list.c:1560
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:151
void UnlockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
Definition: lmgr.c:601
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1088
bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
Definition: lmgr.c:526
bool ConditionalLockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode, bool logLockFailure)
Definition: lmgr.c:582
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:229
void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1008
void UnlockRelation(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:314
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1249
void SpeculativeInsertionWait(TransactionId xid, uint32 token)
Definition: lmgr.c:828
bool ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1112
void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1187
void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:911
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:391
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:70
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
void LockRelation(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:246
void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:214
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
Definition: lmgr.c:989
bool ConditionalXactLockTableWait(TransactionId xid, bool logLockFailure)
Definition: lmgr.c:739
void XactLockTableDelete(TransactionId xid)
Definition: lmgr.c:639
void XactLockTableInsert(TransactionId xid)
Definition: lmgr.c:622
uint32 SpeculativeInsertionLockAcquire(TransactionId xid)
Definition: lmgr.c:786
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:424
bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:334
void UnlockApplyTransactionForSession(Oid suboid, TransactionId xid, uint16 objid, LOCKMODE lockmode)
Definition: lmgr.c:1227
void SpeculativeInsertionLockRelease(TransactionId xid)
Definition: lmgr.c:812
static void XactLockTableWaitErrorCb(void *arg)
Definition: lmgr.c:846
void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
Definition: lmgr.c:507
bool ConditionalLockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:442
bool CheckRelationOidLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger)
Definition: lmgr.c:351
static void SetLocktagRelationOid(LOCKTAG *tag, Oid relid)
Definition: lmgr.c:88
void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
Definition: lmgr.c:542
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:404
bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:278
static uint32 speculativeInsertionToken
Definition: lmgr.c:45
void LockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
Definition: lmgr.c:562
bool ConditionalLockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1032
void LockDatabaseFrozenIds(LOCKMODE lockmode)
Definition: lmgr.c:491
struct XactLockTableWaitInfo XactLockTableWaitInfo
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:474
const char * GetLockNameFromTagType(uint16 locktag_type)
Definition: lmgr.c:1346
void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1148
void XactLockTableWait(TransactionId xid, Relation rel, const ItemPointerData *ctid, XLTW_Oper oper)
Definition: lmgr.c:663
void LockApplyTransactionForSession(Oid suboid, TransactionId xid, uint16 objid, LOCKMODE lockmode)
Definition: lmgr.c:1209
void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1169
void LockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:185
bool LockHasWaitersRelation(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:367
void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1068
int RelationExtensionLockWaiterCount(Relation relation)
Definition: lmgr.c:459
XLTW_Oper
Definition: lmgr.h:25
@ XLTW_FetchUpdated
Definition: lmgr.h:33
@ XLTW_None
Definition: lmgr.h:26
@ XLTW_Lock
Definition: lmgr.h:29
@ XLTW_Delete
Definition: lmgr.h:28
@ XLTW_InsertIndex
Definition: lmgr.h:31
@ XLTW_LockUpdated
Definition: lmgr.h:30
@ XLTW_RecheckExclusionConstr
Definition: lmgr.h:34
@ XLTW_Update
Definition: lmgr.h:27
@ XLTW_InsertIndexUnique
Definition: lmgr.h:32
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition: lock.c:809
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition: lock.c:643
int LockWaiterCount(const LOCKTAG *locktag)
Definition: lock.c:4856
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:2102
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition: lock.c:4745
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition: lock.c:3069
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
Definition: lock.c:836
bool LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:696
void MarkLockClear(LOCALLOCK *locallock)
Definition: lock.c:1920
#define SET_LOCKTAG_DATABASE_FROZEN_IDS(locktag, dboid)
Definition: lock.h:201
#define SET_LOCKTAG_RELATION_EXTEND(locktag, dboid, reloid)
Definition: lock.h:192
LockTagType
Definition: lock.h:138
@ LOCKTAG_OBJECT
Definition: lock.h:147
@ LOCKTAG_RELATION_EXTEND
Definition: lock.h:140
@ LOCKTAG_RELATION
Definition: lock.h:139
@ LOCKTAG_TUPLE
Definition: lock.h:143
@ LOCKTAG_SPECULATIVE_TOKEN
Definition: lock.h:146
@ LOCKTAG_APPLY_TRANSACTION
Definition: lock.h:150
@ LOCKTAG_USERLOCK
Definition: lock.h:148
@ LOCKTAG_DATABASE_FROZEN_IDS
Definition: lock.h:141
@ LOCKTAG_VIRTUALTRANSACTION
Definition: lock.h:145
@ LOCKTAG_TRANSACTION
Definition: lock.h:144
@ LOCKTAG_PAGE
Definition: lock.h:142
@ LOCKTAG_ADVISORY
Definition: lock.h:149
#define SET_LOCKTAG_APPLY_TRANSACTION(locktag, dboid, suboid, xid, objid)
Definition: lock.h:284
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:69
#define SET_LOCKTAG_TRANSACTION(locktag, xid)
Definition: lock.h:228
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:183
#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag, xid, token)
Definition: lock.h:249
#define LOCKTAG_LAST_TYPE
Definition: lock.h:154
#define SET_LOCKTAG_PAGE(locktag, dboid, reloid, blocknum)
Definition: lock.h:210
#define SET_LOCKTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
Definition: lock.h:219
#define SET_LOCKTAG_OBJECT(locktag, dboid, classoid, objoid, objsubid)
Definition: lock.h:264
LockAcquireResult
Definition: lock.h:502
@ LOCKACQUIRE_ALREADY_CLEAR
Definition: lock.h:506
@ LOCKACQUIRE_NOT_AVAIL
Definition: lock.h:503
int LOCKMODE
Definition: lockdefs.h:26
#define ExclusiveLock
Definition: lockdefs.h:42
#define ShareLock
Definition: lockdefs.h:40
const char *const LockTagTypeNames[]
Definition: lockfuncs.c:28
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:371
void * arg
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
static char * buf
Definition: pg_test_fsync.c:72
static int progress
Definition: pgbench.c:262
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3100
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1402
#define PROGRESS_WAITFOR_DONE
Definition: progress.h:120
#define PROGRESS_WAITFOR_TOTAL
Definition: progress.h:119
#define PROGRESS_WAITFOR_CURRENT_PID
Definition: progress.h:121
#define RelationGetRelid(relation)
Definition: rel.h:514
#define RelationGetRelationName(relation)
Definition: rel.h:548
#define RelationIsValid(relation)
Definition: rel.h:489
void pg_usleep(long microsec)
Definition: signal.c:53
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
Definition: lock.h:167
uint8 locktag_type
Definition: lock.h:172
uint32 locktag_field3
Definition: lock.h:170
uint32 locktag_field1
Definition: lock.h:168
uint16 locktag_field4
Definition: lock.h:171
uint32 locktag_field2
Definition: lock.h:169
Definition: pg_list.h:54
LockRelId lockRelId
Definition: rel.h:46
Definition: rel.h:39
Oid relId
Definition: rel.h:40
Oid dbId
Definition: rel.h:41
Definition: proc.h:179
int pid
Definition: proc.h:199
LockInfoData rd_lockInfo
Definition: rel.h:114
Form_pg_class rd_rel
Definition: rel.h:111
ProcNumber procNumber
Definition: lock.h:63
const ItemPointerData * ctid
Definition: lmgr.c:58
XLTW_Oper oper
Definition: lmgr.c:56
Relation rel
Definition: lmgr.c:57
Definition: type.h:96
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:162
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:441