Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite06fda0

Browse files
committed
Add a function GetLockConflicts() to lock.c to report xacts holding
locks that would conflict with a specified lock request, withoutactually trying to get that lock. Use this instead of the former ad hocmethod of doing the first wait step in CREATE INDEX CONCURRENTLY.Fixes problem with undetected deadlock and in many cases will allow theindex creation to proceed sooner than it otherwise could've. Perdiscussion with Greg Stark.
1 parentca1fd0e commite06fda0

File tree

3 files changed

+129
-32
lines changed

3 files changed

+129
-32
lines changed

‎src/backend/commands/indexcmds.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.147 2006/08/25 04:06:48 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.148 2006/08/27 19:14:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -119,8 +119,11 @@ DefineIndex(RangeVar *heapRelation,
119119
Datumreloptions;
120120
IndexInfo*indexInfo;
121121
intnumberOfAttributes;
122+
List*old_xact_list;
123+
ListCell*lc;
122124
uint32ixcnt;
123125
LockRelIdheaprelid;
126+
LOCKTAGheaplocktag;
124127
Snapshotsnapshot;
125128
Relationpg_index;
126129
HeapTupleindexTuple;
@@ -466,33 +469,26 @@ DefineIndex(RangeVar *heapRelation,
466469
CommitTransactionCommand();
467470
StartTransactionCommand();
468471

469-
/* Establish transaction snapshot ... else GetLatestSnapshot complains */
470-
(void)GetTransactionSnapshot();
471-
472472
/*
473473
* Now we must wait until no running transaction could have the table open
474-
* with the old list of indexes. If we can take an exclusive lock then
475-
* there are none now and anybody who opens it later will get the new
476-
* index in their relcache entry. Alternatively, if our Xmin reaches our
477-
* own (new) transaction then we know no transactions that started before
478-
* the index was visible are left anyway.
474+
* with the old list of indexes. To do this, inquire which xacts currently
475+
* would conflict with ShareLock on the table -- ie, which ones have
476+
* a lock that permits writing the table. Then wait for each of these
477+
* xacts to commit or abort. Note we do not need to worry about xacts
478+
* that open the table for writing after this point; they will see the
479+
* new index when they open it.
480+
*
481+
* Note: GetLockConflicts() never reports our own xid,
482+
* hence we need not check for that.
479483
*/
480-
for (;;)
481-
{
482-
CHECK_FOR_INTERRUPTS();
484+
SET_LOCKTAG_RELATION(heaplocktag,heaprelid.dbId,heaprelid.relId);
485+
old_xact_list=GetLockConflicts(&heaplocktag,ShareLock);
483486

484-
if (ConditionalLockRelationOid(relationId,ExclusiveLock))
485-
{
486-
/* Release the lock right away to avoid blocking anyone */
487-
UnlockRelationOid(relationId,ExclusiveLock);
488-
break;
489-
}
490-
491-
if (TransactionIdEquals(GetLatestSnapshot()->xmin,
492-
GetTopTransactionId()))
493-
break;
487+
foreach(lc,old_xact_list)
488+
{
489+
TransactionIdxid=lfirst_xid(lc);
494490

495-
pg_usleep(1000000L);/* 1 sec */
491+
XactLockTableWait(xid);
496492
}
497493

498494
/*

‎src/backend/storage/lmgr/lock.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.171 2006/08/19 01:36:28 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.172 2006/08/27 19:14:34 tgl Exp $
1212
*
1313
* NOTES
1414
* A lock table is a shared memory hash table. When
@@ -1685,6 +1685,104 @@ LockReassignCurrentOwner(void)
16851685
}
16861686

16871687

1688+
/*
1689+
* GetLockConflicts
1690+
*Get a list of TransactionIds of xacts currently holding locks
1691+
*that would conflict with the specified lock/lockmode.
1692+
*xacts merely awaiting such a lock are NOT reported.
1693+
*
1694+
* Of course, the result could be out of date by the time it's returned,
1695+
* so use of this function has to be thought about carefully.
1696+
*
1697+
* Only top-level XIDs are reported. Note we never include the current xact
1698+
* in the result list, since an xact never blocks itself.
1699+
*/
1700+
List*
1701+
GetLockConflicts(constLOCKTAG*locktag,LOCKMODElockmode)
1702+
{
1703+
List*result=NIL;
1704+
LOCKMETHODIDlockmethodid=locktag->locktag_lockmethodid;
1705+
LockMethodlockMethodTable;
1706+
LOCK*lock;
1707+
LOCKMASKconflictMask;
1708+
SHM_QUEUE*procLocks;
1709+
PROCLOCK*proclock;
1710+
uint32hashcode;
1711+
LWLockIdpartitionLock;
1712+
1713+
if (lockmethodid <=0||lockmethodid >=lengthof(LockMethods))
1714+
elog(ERROR,"unrecognized lock method: %d",lockmethodid);
1715+
lockMethodTable=LockMethods[lockmethodid];
1716+
if (lockmode <=0||lockmode>lockMethodTable->numLockModes)
1717+
elog(ERROR,"unrecognized lock mode: %d",lockmode);
1718+
1719+
/*
1720+
* Look up the lock object matching the tag.
1721+
*/
1722+
hashcode=LockTagHashCode(locktag);
1723+
partitionLock=LockHashPartitionLock(hashcode);
1724+
1725+
LWLockAcquire(partitionLock,LW_SHARED);
1726+
1727+
lock= (LOCK*)hash_search_with_hash_value(LockMethodLockHash,
1728+
(void*)locktag,
1729+
hashcode,
1730+
HASH_FIND,
1731+
NULL);
1732+
if (!lock)
1733+
{
1734+
/*
1735+
* If the lock object doesn't exist, there is nothing holding a
1736+
* lock on this lockable object.
1737+
*/
1738+
LWLockRelease(partitionLock);
1739+
returnNIL;
1740+
}
1741+
1742+
/*
1743+
* Examine each existing holder (or awaiter) of the lock.
1744+
*/
1745+
conflictMask=lockMethodTable->conflictTab[lockmode];
1746+
1747+
procLocks=&(lock->procLocks);
1748+
1749+
proclock= (PROCLOCK*)SHMQueueNext(procLocks,procLocks,
1750+
offsetof(PROCLOCK,lockLink));
1751+
1752+
while (proclock)
1753+
{
1754+
if (conflictMask&proclock->holdMask)
1755+
{
1756+
PGPROC*proc=proclock->tag.myProc;
1757+
1758+
/* A backend never blocks itself */
1759+
if (proc!=MyProc)
1760+
{
1761+
/* Fetch xid just once - see GetNewTransactionId */
1762+
TransactionIdxid=proc->xid;
1763+
1764+
/*
1765+
* Race condition: during xact commit/abort we zero out
1766+
* PGPROC's xid before we mark its locks released. If we see
1767+
* zero in the xid field, assume the xact is in process of
1768+
* shutting down and act as though the lock is already
1769+
* released.
1770+
*/
1771+
if (TransactionIdIsValid(xid))
1772+
result=lappend_xid(result,xid);
1773+
}
1774+
}
1775+
1776+
proclock= (PROCLOCK*)SHMQueueNext(procLocks,&proclock->lockLink,
1777+
offsetof(PROCLOCK,lockLink));
1778+
}
1779+
1780+
LWLockRelease(partitionLock);
1781+
1782+
returnresult;
1783+
}
1784+
1785+
16881786
/*
16891787
* AtPrepare_Locks
16901788
*Do the preparatory work for a PREPARE: make 2PC state file records

‎src/include/storage/lock.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.97 2006/07/31 20:09:05 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.98 2006/08/27 19:14:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414
#ifndefLOCK_H_
1515
#defineLOCK_H_
1616

17+
#include"nodes/pg_list.h"
1718
#include"storage/itemptr.h"
1819
#include"storage/lwlock.h"
1920
#include"storage/shmem.h"
@@ -412,6 +413,7 @@ extern bool LockRelease(const LOCKTAG *locktag,
412413
externvoidLockReleaseAll(LOCKMETHODIDlockmethodid,boolallLocks);
413414
externvoidLockReleaseCurrentOwner(void);
414415
externvoidLockReassignCurrentOwner(void);
416+
externList*GetLockConflicts(constLOCKTAG*locktag,LOCKMODElockmode);
415417
externvoidAtPrepare_Locks(void);
416418
externvoidPostPrepare_Locks(TransactionIdxid);
417419
externintLockCheckConflicts(LockMethodlockMethodTable,
@@ -421,13 +423,6 @@ extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
421423
externvoidGrantAwaitedLock(void);
422424
externvoidRemoveFromWaitQueue(PGPROC*proc,uint32hashcode);
423425
externSizeLockShmemSize(void);
424-
externboolDeadLockCheck(PGPROC*proc);
425-
externvoidDeadLockReport(void);
426-
externvoidRememberSimpleDeadLock(PGPROC*proc1,
427-
LOCKMODElockmode,
428-
LOCK*lock,
429-
PGPROC*proc2);
430-
externvoidInitDeadLockChecking(void);
431426
externLockData*GetLockStatusData(void);
432427
externconstchar*GetLockmodeName(LOCKMETHODIDlockmethodid,LOCKMODEmode);
433428

@@ -438,6 +433,14 @@ extern void lock_twophase_postcommit(TransactionId xid, uint16 info,
438433
externvoidlock_twophase_postabort(TransactionIdxid,uint16info,
439434
void*recdata,uint32len);
440435

436+
externboolDeadLockCheck(PGPROC*proc);
437+
externvoidDeadLockReport(void);
438+
externvoidRememberSimpleDeadLock(PGPROC*proc1,
439+
LOCKMODElockmode,
440+
LOCK*lock,
441+
PGPROC*proc2);
442+
externvoidInitDeadLockChecking(void);
443+
441444
#ifdefLOCK_DEBUG
442445
externvoidDumpLocks(PGPROC*proc);
443446
externvoidDumpAllLocks(void);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp