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

Commit3a694bb

Browse files
committed
Restructure LOCKTAG as per discussions of a couple months ago.
Essentially, we shoehorn in a lockable-object-type field by takinga byte away from the lockmethodid, which can surely fit in one byteinstead of two. This allows less artificial definitions of all theother fields of LOCKTAG; we can get rid of the special pg_xactlockpseudo-relation, and also support locks on individual tuples andgeneral database objects (including shared objects). None of thosepossibilities are actually exploited just yet, however.I removed pg_xactlock from pg_class, but did not force initdb forthat change. At this point, relkind 's' (SPECIAL) is unused andcould be removed entirely.
1 parent32d3b47 commit3a694bb

File tree

14 files changed

+345
-253
lines changed

14 files changed

+345
-253
lines changed

‎contrib/userlock/README.user_locks

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,21 @@ It could also be done with a begin/end block but in this case the entire
3535
table would be locked by Postgres and it is not acceptable to do this for
3636
a long period because other transactions would block completely.
3737

38-
The generic user locks use two values, group and id, to identify a lock,
39-
which correspond to ip_posid and ip_blkid of an ItemPointerData.
40-
Group is a 16 bit value while id is a 32 bit integer which could also be
41-
an oid.The oid user lock functions, which take only anoid as argument,
42-
use a group equal to 0.
38+
The generic user locks use two values, group and id, to identify a lock.
39+
Each of these are 32-bit integers.
40+
41+
The oid user lock functions, which take only anOID as argument, store the
42+
OID as "id" with a group equal to 0.
4343

4444
The meaning of group and id is defined by the application. The user
4545
lock code just takes two numbers and tells you if the corresponding
4646
entity has been successfully locked. What this means is up to you.
4747

4848
My suggestion is that you use the group to identify an area of your
4949
application and the id to identify an object in this area.
50-
Or you can just lock the oid of the tuples which are by definition unique.
50+
51+
In all cases, user locks are local to individual databases within an
52+
installation.
5153

5254
Note also that a process can acquire more than one lock on the same entity
5355
and it must release the lock the corresponding number of times. This can

‎contrib/userlock/user_locks.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@
1818
#include"user_locks.h"
1919

2020

21+
#defineSET_LOCKTAG_USERLOCK(locktag,id1,id2) \
22+
((locktag).locktag_field1 = (id1), \
23+
(locktag).locktag_field2 = (id2), \
24+
(locktag).locktag_field3 = MyDatabaseId, \
25+
(locktag).locktag_field4 = 0, \
26+
(locktag).locktag_type = LOCKTAG_USERLOCK)
27+
28+
2129
int
2230
user_lock(uint32id1,uint32id2,LOCKMODElockmode)
2331
{
2432
LOCKTAGtag;
2533

26-
memset(&tag,0,sizeof(LOCKTAG));
27-
tag.dbId=MyDatabaseId;
28-
tag.relId=0;
29-
tag.objId.blkno= (BlockNumber)id2;
30-
tag.offnum= (OffsetNumber) (id1&0xffff);
34+
SET_LOCKTAG_USERLOCK(tag,id1,id2);
3135

3236
returnLockAcquire(USER_LOCKMETHOD,&tag,InvalidTransactionId,
3337
lockmode, true);
@@ -38,11 +42,7 @@ user_unlock(uint32 id1, uint32 id2, LOCKMODE lockmode)
3842
{
3943
LOCKTAGtag;
4044

41-
memset(&tag,0,sizeof(LOCKTAG));
42-
tag.dbId=MyDatabaseId;
43-
tag.relId=0;
44-
tag.objId.blkno= (BlockNumber)id2;
45-
tag.offnum= (OffsetNumber) (id1&0xffff);
45+
SET_LOCKTAG_USERLOCK(tag,id1,id2);
4646

4747
returnLockRelease(USER_LOCKMETHOD,&tag,InvalidTransactionId,lockmode);
4848
}
@@ -77,13 +77,3 @@ user_unlock_all(void)
7777
{
7878
returnLockReleaseAll(USER_LOCKMETHOD, true);
7979
}
80-
81-
/* end of file */
82-
83-
/*
84-
* Local Variables:
85-
*tab-width: 4
86-
*c-indent-level: 4
87-
*c-basic-offset: 4
88-
* End:
89-
*/

‎contrib/userlock/user_locks.h

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
#ifndefUSER_LOCKS_H
22
#defineUSER_LOCKS_H
33

4-
intuser_lock(unsignedintid1,unsignedintid2,LOCKMODElockmode);
5-
intuser_unlock(unsignedintid1,unsignedintid2,LOCKMODElockmode);
6-
intuser_write_lock(unsignedintid1,unsignedintid2);
7-
intuser_write_unlock(unsignedintid1,unsignedintid2);
8-
intuser_write_lock_oid(Oidoid);
9-
intuser_write_unlock_oid(Oidoid);
10-
intuser_unlock_all(void);
11-
#endif
4+
externintuser_lock(uint32id1,uint32id2,LOCKMODElockmode);
5+
externintuser_unlock(uint32id1,uint32id2,LOCKMODElockmode);
6+
externintuser_write_lock(uint32id1,uint32id2);
7+
externintuser_write_unlock(uint32id1,uint32id2);
8+
externintuser_write_lock_oid(Oidoid);
9+
externintuser_write_unlock_oid(Oidoid);
10+
externintuser_unlock_all(void);
1211

13-
/*
14-
* Local Variables:
15-
*tab-width: 4
16-
*c-indent-level: 4
17-
*c-basic-offset: 4
18-
* End:
19-
*/
12+
#endif

‎src/backend/access/heap/hio.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.54 2004/12/31 21:59:16 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.55 2005/04/29 22:28:23 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -79,11 +79,6 @@ RelationPutHeapTuple(Relation relation,
7979
*happen if space is freed in that page after heap_update finds there's not
8080
*enough there).In that case, the page will be pinned and locked only once.
8181
*
82-
*Note that we use LockPage(rel, 0) to lock relation for extension.
83-
*We can do this as long as in all other places we use page-level locking
84-
*for indices only. Alternatively, we could define pseudo-table as
85-
*we do for transactions with XactLockTable.
86-
*
8782
*ereport(ERROR) is allowed here, so this routine *must* be called
8883
*before any (unlogged) changes are made in buffer pool.
8984
*/
@@ -235,7 +230,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
235230
needLock= !RELATION_IS_LOCAL(relation);
236231

237232
if (needLock)
238-
LockPage(relation,0,ExclusiveLock);
233+
LockRelationForExtension(relation,ExclusiveLock);
239234

240235
/*
241236
* XXX This does an lseek - rather expensive - but at the moment it is
@@ -251,7 +246,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
251246
* extend the relation some more.
252247
*/
253248
if (needLock)
254-
UnlockPage(relation,0,ExclusiveLock);
249+
UnlockRelationForExtension(relation,ExclusiveLock);
255250

256251
/*
257252
* We can be certain that locking the otherBuffer first is OK, since

‎src/backend/access/nbtree/nbtpage.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.82 2005/03/22 06:17:03 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.83 2005/04/29 22:28:24 tgl Exp $
1313
*
1414
*NOTES
1515
* Postgres btree pages look like ordinary relation pages.The opaque
@@ -487,7 +487,7 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
487487
needLock= !RELATION_IS_LOCAL(rel);
488488

489489
if (needLock)
490-
LockPage(rel,0,ExclusiveLock);
490+
LockRelationForExtension(rel,ExclusiveLock);
491491

492492
buf=ReadBuffer(rel,P_NEW);
493493

@@ -496,7 +496,7 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
496496
* to extend the relation some more.
497497
*/
498498
if (needLock)
499-
UnlockPage(rel,0,ExclusiveLock);
499+
UnlockRelationForExtension(rel,ExclusiveLock);
500500

501501
/* Acquire appropriate buffer lock on new page */
502502
LockBuffer(buf,access);

‎src/backend/storage/lmgr/README

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.15 2004/08/27 17:07:41 tgl Exp $
1+
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.16 2005/04/29 22:28:24 tgl Exp $
22

33

44
LOCKING OVERVIEW
@@ -74,30 +74,14 @@ The lock manager's LOCK objects contain:
7474

7575
tag -
7676
The key fields that are used for hashing locks in the shared memory
77-
lock hash table. This is declared as a separate struct to ensure that
78-
we always zero out the correct number of bytes. It is critical that
79-
any alignment-padding bytes the compiler might insert in the struct
80-
be zeroed out, else the hash computation will be random.
81-
82-
tag.relId -
83-
Uniquely identifies the relation that the lock corresponds to.
84-
85-
tag.dbId -
86-
Uniquely identifies the database in which the relation lives. If
87-
this is a shared system relation (e.g. pg_database) the dbId must
88-
be set to 0.
89-
90-
tag.objId -
91-
Uniquely identifies the block/page within the relation and the
92-
tuple within the block. If we are setting a table level lock
93-
both the blockId and tupleId (in an item pointer this is called
94-
the position) are set to invalid, if it is a page level lock the
95-
blockId is valid, while the tupleId is still invalid. Finally if
96-
this is a tuple level lock (we currently never do this) then both
97-
the blockId and tupleId are set to valid specifications. This is
98-
how we get the appearance of a multi-level lock table while using
99-
only a single table (see Gray's paper on 2 phase locking if
100-
you are puzzled about how multi-level lock tables work).
77+
lock hash table. The contents of the tag essentially define an
78+
individual lockable object. See include/storage/lock.h for details
79+
about the supported types of lockable objects. This is declared as
80+
a separate struct to ensure that we always zero out the correct number
81+
of bytes. It is critical that any alignment-padding bytes the compiler
82+
might insert in the struct be zeroed out, else the hash computation
83+
will be random. (Currently, we are careful to define struct LOCKTAG
84+
so that there are no padding bytes.)
10185

10286
grantMask -
10387
This bitmask indicates what types of locks are currently held on the

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

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.33 2005/02/22 04:36:49 momjian Exp $
15+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.34 2005/04/29 22:28:24 tgl Exp $
1616
*
1717
*Interface:
1818
*
@@ -836,16 +836,82 @@ PrintLockQueue(LOCK *lock, const char *info)
836836
}
837837
#endif
838838

839+
/*
840+
* Append a description of a lockable object to buf.
841+
*
842+
* XXX probably this should be exported from lmgr.c or some such place.
843+
*/
844+
staticvoid
845+
DescribeLockTag(StringInfobuf,constLOCKTAG*lock)
846+
{
847+
switch (lock->locktag_type)
848+
{
849+
caseLOCKTAG_RELATION:
850+
appendStringInfo(buf,
851+
_("relation %u of database %u"),
852+
lock->locktag_field2,
853+
lock->locktag_field1);
854+
break;
855+
caseLOCKTAG_RELATION_EXTEND:
856+
appendStringInfo(buf,
857+
_("extension of relation %u of database %u"),
858+
lock->locktag_field2,
859+
lock->locktag_field1);
860+
break;
861+
caseLOCKTAG_PAGE:
862+
appendStringInfo(buf,
863+
_("page %u of relation %u of database %u"),
864+
lock->locktag_field3,
865+
lock->locktag_field2,
866+
lock->locktag_field1);
867+
break;
868+
caseLOCKTAG_TUPLE:
869+
appendStringInfo(buf,
870+
_("tuple (%u,%u) of relation %u of database %u"),
871+
lock->locktag_field3,
872+
lock->locktag_field4,
873+
lock->locktag_field2,
874+
lock->locktag_field1);
875+
break;
876+
caseLOCKTAG_TRANSACTION:
877+
appendStringInfo(buf,
878+
_("transaction %u"),
879+
lock->locktag_field1);
880+
break;
881+
caseLOCKTAG_OBJECT:
882+
appendStringInfo(buf,
883+
_("object %u of class %u of database %u"),
884+
lock->locktag_field3,
885+
lock->locktag_field2,
886+
lock->locktag_field1);
887+
break;
888+
caseLOCKTAG_USERLOCK:
889+
appendStringInfo(buf,
890+
_("user lock [%u,%u]"),
891+
lock->locktag_field1,
892+
lock->locktag_field2);
893+
break;
894+
default:
895+
appendStringInfo(buf,
896+
_("unknown locktag type %d"),
897+
lock->locktag_type);
898+
break;
899+
}
900+
}
901+
839902
/*
840903
* Report a detected deadlock, with available details.
841904
*/
842905
void
843906
DeadLockReport(void)
844907
{
845908
StringInfoDatabuf;
909+
StringInfoDatabuf2;
846910
inti;
847911

848912
initStringInfo(&buf);
913+
initStringInfo(&buf2);
914+
849915
for (i=0;i<nDeadlockDetails;i++)
850916
{
851917
DEADLOCK_INFO*info=&deadlockDetails[i];
@@ -860,27 +926,18 @@ DeadLockReport(void)
860926
if (i>0)
861927
appendStringInfoChar(&buf,'\n');
862928

863-
if (info->locktag.relId==XactLockTableId&&info->locktag.dbId==0)
864-
{
865-
/* Lock is for transaction ID */
866-
appendStringInfo(&buf,
867-
_("Process %d waits for %s on transaction %u; blocked by process %d."),
868-
info->pid,
869-
GetLockmodeName(info->lockmode),
870-
info->locktag.objId.xid,
871-
nextpid);
872-
}
873-
else
874-
{
875-
/* Lock is for a relation */
876-
appendStringInfo(&buf,
877-
_("Process %d waits for %s on relation %u of database %u; blocked by process %d."),
878-
info->pid,
879-
GetLockmodeName(info->lockmode),
880-
info->locktag.relId,
881-
info->locktag.dbId,
882-
nextpid);
883-
}
929+
/* reset buf2 to hold next object description */
930+
buf2.len=0;
931+
buf2.data[0]='\0';
932+
933+
DescribeLockTag(&buf2,&info->locktag);
934+
935+
appendStringInfo(&buf,
936+
_("Process %d waits for %s on %s; blocked by process %d."),
937+
info->pid,
938+
GetLockmodeName(info->lockmode),
939+
buf2.data,
940+
nextpid);
884941
}
885942
ereport(ERROR,
886943
(errcode(ERRCODE_T_R_DEADLOCK_DETECTED),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp