1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-25 13:17:41 +03:00

Implement sharable row-level locks, and use them for foreign key references

to eliminate unnecessary deadlocks.  This commit adds SELECT ... FOR SHARE
paralleling SELECT ... FOR UPDATE.  The implementation uses a new SLRU
data structure (managed much like pg_subtrans) to represent multiple-
transaction-ID sets.  When more than one transaction is holding a shared
lock on a particular row, we create a MultiXactId representing that set
of transactions and store its ID in the row's XMAX.  This scheme allows
an effectively unlimited number of row locks, just as we did before,
while not costing any extra overhead except when a shared lock actually
has to be shared.   Still TODO: use the regular lock manager to control
the grant order when multiple backends are waiting for a row lock.

Alvaro Herrera and Tom Lane.
This commit is contained in:
Tom Lane
2005-04-28 21:47:18 +00:00
parent d902e7d63b
commit bedb78d386
55 changed files with 2802 additions and 439 deletions

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.99 2005/04/14 20:03:27 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.100 2005/04/28 21:47:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -123,6 +123,12 @@ extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
/* heapam.c */
typedef enum
{
LockTupleShared,
LockTupleExclusive
} LockTupleMode;
extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
extern Relation conditional_relation_open(Oid relationId, LOCKMODE lockmode, bool nowait);
extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
@@ -155,8 +161,8 @@ extern HTSU_Result heap_delete(Relation relation, ItemPointer tid, ItemPointer c
CommandId cid, Snapshot crosscheck, bool wait);
extern HTSU_Result heap_update(Relation relation, ItemPointer otid, HeapTuple tup,
ItemPointer ctid, CommandId cid, Snapshot crosscheck, bool wait);
extern HTSU_Result heap_mark4update(Relation relation, HeapTuple tup,
Buffer *userbuf, CommandId cid);
extern HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tup,
Buffer *userbuf, CommandId cid, LockTupleMode mode);
extern Oid simple_heap_insert(Relation relation, HeapTuple tup);
extern void simple_heap_delete(Relation relation, ItemPointer tid);

View File

@@ -1,4 +1,4 @@
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
*
* htup.h
* POSTGRES heap tuple definitions.
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/htup.h,v 1.73 2005/03/28 01:50:34 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/htup.h,v 1.74 2005/04/28 21:47:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -93,11 +93,11 @@ typedef struct HeapTupleFields
{
TransactionId t_xmin; /* inserting xact ID */
CommandId t_cmin; /* inserting command ID */
TransactionId t_xmax; /* deleting xact ID */
TransactionId t_xmax; /* deleting or locking xact ID */
union
{
CommandId t_cmax; /* deleting command ID */
CommandId t_cmax; /* deleting or locking command ID */
TransactionId t_xvac; /* VACUUM FULL xact ID */
} t_field4;
} HeapTupleFields;
@@ -152,12 +152,16 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
* attribute(s) */
#define HEAP_HASEXTENDED 0x000C /* the two above combined */
#define HEAP_HASOID 0x0010 /* has an object-id field */
/* 0x0020, 0x0040 and 0x0080 are unused */
/* 0x0020 is presently unused */
#define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */
#define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker */
/* if either LOCK bit is set, xmax hasn't deleted the tuple, only locked it */
#define HEAP_IS_LOCKED (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_SHARED_LOCK)
#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
#define HEAP_MARKED_FOR_UPDATE 0x1000 /* marked for UPDATE */
#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */
#define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */
#define HEAP_MOVED_OFF 0x4000 /* moved to another place by
* VACUUM FULL */
@@ -406,7 +410,8 @@ typedef HeapTupleData *HeapTuple;
#define XLOG_HEAP_MOVE 0x30
#define XLOG_HEAP_CLEAN 0x40
#define XLOG_HEAP_NEWPAGE 0x50
/* opcodes 0x60, 0x70 still free */
#define XLOG_HEAP_LOCK 0x60
/* opcode 0x70 still free */
#define XLOG_HEAP_OPMASK 0x70
/*
* When we insert 1st item on new page in INSERT/UPDATE
@@ -496,4 +501,13 @@ typedef struct xl_heap_newpage
#define SizeOfHeapNewpage (offsetof(xl_heap_newpage, blkno) + sizeof(BlockNumber))
/* This is what we need to know about lock */
typedef struct xl_heap_lock
{
xl_heaptid target; /* locked tuple id */
bool shared_lock; /* shared or exclusive row lock? */
} xl_heap_lock;
#define SizeOfHeapLock (offsetof(xl_heap_lock, shared_lock) + sizeof(bool))
#endif /* HTUP_H */

View File

@@ -0,0 +1,37 @@
/*
* multixact.h
*
* PostgreSQL multi-transaction-log manager
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/multixact.h,v 1.1 2005/04/28 21:47:17 tgl Exp $
*/
#ifndef MULTIXACT_H
#define MULTIXACT_H
#define InvalidMultiXactId ((MultiXactId) 0)
#define FirstMultiXactId ((MultiXactId) 1)
#define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId)
extern void MultiXactIdWait(MultiXactId multi);
extern MultiXactId MultiXactIdExpand(MultiXactId multi, bool isMulti,
TransactionId xid);
extern bool MultiXactIdIsRunning(MultiXactId multi);
extern void MultiXactIdSetOldestMember(void);
extern void AtEOXact_MultiXact(void);
extern int MultiXactShmemSize(void);
extern void MultiXactShmemInit(void);
extern void BootStrapMultiXact(void);
extern void StartupMultiXact(void);
extern void ShutdownMultiXact(void);
extern MultiXactId MultiXactGetCheckptMulti(bool is_shutdown);
extern void CheckPointMultiXact(void);
extern void MultiXactSetNextMXact(MultiXactId nextMulti);
extern void MultiXactAdvanceNextMXact(MultiXactId minMulti);
#endif /* MULTIXACT_H */

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.59 2004/12/31 22:03:21 pgsql Exp $
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.60 2005/04/28 21:47:17 tgl Exp $
*/
#ifndef XLOG_H
#define XLOG_H
@@ -133,6 +133,7 @@ extern void ShutdownXLOG(int code, Datum arg);
extern void InitXLOGAccess(void);
extern void CreateCheckPoint(bool shutdown, bool force);
extern void XLogPutNextOid(Oid nextOid);
extern void XLogPutNextMultiXactId(MultiXactId multi);
extern XLogRecPtr GetRedoRecPtr(void);
#endif /* XLOG_H */