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