pg_advisory_lock(key> bigint>)
void
- Obtain exclusive advisory lock
+ Obtain exclusive session level advisory lock
|
pg_advisory_lock(key1> int>, key2> int>)
void
- Obtain exclusive advisory lock
+ Obtain exclusive session level advisory lock
|
pg_advisory_lock_shared(key> bigint>)
void
- Obtain shared advisory lock
+ Obtain shared session level advisory lock
|
pg_advisory_lock_shared(key1> int>, key2> int>)
void
- Obtain shared advisory lock
+ Obtain shared session level advisory lock
|
pg_advisory_unlock(key> bigint>)
boolean
- Release an exclusive advisory lock
+ Release an exclusive session level advisory lock
|
pg_advisory_unlock(key1> int>, key2> int>)
boolean
- Release an exclusive advisory lock
+ Release an exclusive session level advisory lock
|
pg_advisory_unlock_all()
void
- Release all advisory locks held by the current session
+ Release all session level advisory locks held by the current session
|
pg_advisory_unlock_shared(key> bigint>)
boolean
- Release a shared advisory lock
+ Release a shared session level advisory lock
|
pg_advisory_unlock_shared(key1> int>, key2> int>)
boolean
- Release a shared advisory lock
+ Release a shared session level advisory lock
+
+ |
+
+
pg_advisory_xact_lock(key> bigint>)
+
+ void
+ Obtain exclusive transaction level advisory lock
+
+ |
+
+
pg_advisory_xact_lock(key1> int>, key2> int>)
+
+ void
+ Obtain exclusive transaction level advisory lock
+
+ |
+
+
pg_advisory_xact_lock_shared(key> bigint>)
+
+ void
+ Obtain shared transaction level advisory lock
+
+ |
+
+
pg_advisory_xact_lock_shared(key1> int>, key2> int>)
+
+ void
+ Obtain shared advisory lock for the current transaction
|
pg_try_advisory_lock(key> bigint>)
boolean
- Obtain exclusive advisory lock if available
+ Obtain exclusive session level advisory lock if available
|
pg_try_advisory_lock(key1> int>, key2> int>)
boolean
- Obtain exclusive advisory lock if available
+ Obtain exclusive session level advisory lock if available
|
pg_try_advisory_lock_shared(key> bigint>)
boolean
- Obtain shared advisory lock if available
+ Obtain shared session level advisory lock if available
|
pg_try_advisory_lock_shared(key1> int>, key2> int>)
boolean
- Obtain shared advisory lock if available
+ Obtain shared session level advisory lock if available
+
+ |
+
+
pg_try_advisory_xact_lock(key> bigint>)
+
+ boolean
+ Obtain exclusive transaction level advisory lock if available
+
+ |
+
+
pg_try_advisory_xact_lock(key1> int>, key2> int>)
+
+ boolean
+ Obtain exclusive transaction level advisory lock if available
+
+ |
+
+
pg_try_advisory_xact_lock_shared(key> bigint>)
+
+ boolean
+ Obtain shared transaction level advisory lock if available
+
+ |
+
+
pg_try_advisory_xact_lock_shared(key1> int>, key2> int>)
+
+ boolean
+ Obtain shared transaction level advisory lock if available
a shared rather than an exclusive lock.
+
+
+ pg_advisory_xact_lock> works the same as
+ pg_advisory_lock>, expect the lock is automatically released
+ at the end of the current transaction and can not be released explicitly.
+
+
+
+
pg_advisory_xact_lock_shared
+
+ pg_advisory_xact_lock_shared> works the same as
+ pg_advisory_lock_shared>, expect the lock is automatically released
+ at the end of the current transaction and can not be released explicitly.
+
+
+
+
pg_try_advisory_xact_lock
+
+ pg_try_advisory_xact_lock> works the same as
+ pg_try_advisory_lock>, expect the lock, if acquired,
+ is automatically released at the end of the current transaction and
+ can not be released explicitly.
+
+
+
+
pg_try_advisory_xact_lock_shared
+
+ pg_try_advisory_xact_lock_shared> works the same as
+ pg_try_advisory_lock_shared>, expect the lock, if acquired,
+ is automatically released at the end of the current transaction and
+ can not be released explicitly.
+
+
pg_advisory_unlock> will release a previously-acquired
- exclusive advisory lock. It
+ exclusive session level advisory lock. It
returns true> if the lock is successfully released.
If the lock was not held, it will return false>,
and in addition, an SQL warning will be raised by the server.
pg_advisory_unlock_shared> works the same as
pg_advisory_unlock>,
- except it releases a shared advisory lock.
+ except it releases a shared session level advisory lock.
- pg_advisory_unlock_all> will release all advisory locks
- held by the current session. (This function is implicitly invoked
+ pg_advisory_unlock_all> will release all session level advisory
+ locks held by the current session. (This function is implicitly invoked
at session end, even if the client disconnects ungracefully.)
called advisory locks>, because the system does not
enforce their use — it is up to the application to use them
correctly. Advisory locks can be useful for locking strategies
- that are an awkward fit for the MVCC model. Once acquired, an
- advisory lock is held until explicitly released or the session ends.
- Unlike standard locks, advisory locks do not
- honor transaction semantics: a lock acquired during a
- transaction that is later rolled back will still be held following the
+ that are an awkward fit for the MVCC model.
+
+ There are two different types of advisory locks in
+
PostgreSQL : session level and transaction level.
+ Once acquired, a session level advisory lock is held until explicitly
+ released or the session ends. Unlike standard locks, session level
+ advisory locks do not honor transaction semantics: a lock acquired during
+ a transaction that is later rolled back will still be held following the
rollback, and likewise an unlock is effective even if the calling
- transaction fails later. The same lock can be acquired multiple times by
- its owning process: for each lock request there must be a corresponding
- unlock request before the lock is actually released. (If a session
- already holds a given lock, additional requests will always succeed, even
- if other sessions are awaiting the lock.) Like all locks in
-
PostgreSQL , a complete list of advisory
- locks currently held by any session can be found in the
+ transaction fails later. The same session level lock can be acquired
+ multiple times by its owning process: for each lock request there must be
+ a corresponding unlock request before the lock is actually released. (If a
+ session already holds a given lock, additional requests will always succeed,
+ even if other sessions are awaiting the lock.) Transaction level locks on
+ the other hand behave more like regular locks; they are automatically
+ released at the end of the transaction, and can not be explicitly unlocked.
+ Session and transaction level locks share the same lock space, which means
+ that a transaction level lock will prevent another session from obtaining
+ a session level lock on that same resource and vice versa.
+ Like all locks in
PostgreSQL , a complete list of
+ advisory locks currently held by any session can be found in the
pg_locks
system view.
strategies typical of so called flat file> data management
systems.
While a flag stored in a table could be used for the same purpose,
- advisory locks are faster, avoid MVCC bloat, and ar e automatically
+ advisory locks are faster, avoid MVCC bloat, and can b e automatically
cleaned up by the server at the end of the session.
In certain cases using this advisory locking method, especially in queries
involving explicit ordering and LIMIT> clauses, care must be
----------
User locks are handled totally on the application side as long term
-cooperative locks which extend beyond the normal transaction boundaries.
+cooperative locks which may extend beyond the normal transaction boundaries.
Their purpose is to indicate to an application that someone is `working'
on an item. So it is possible to put an user lock on a tuple's oid,
retrieve the tuple, work on it for an hour and then update it and remove
User locks and normal locks are completely orthogonal and they don't
interfere with each other.
-User locks are always held as session locks, so that they are not released at
-transaction end. They must be released explicitly by the application --- but
-they are released automatically when a backend terminates.
+There are two types of user locks: session level and transaction level.
+Session level user locks are not released at transaction end. They must
+be released explicitly by the application --- but they are released
+automatically when a backend terminates. On the other hand, transaction
+level user locks are released automatically at the end of the transaction
+as like as other normal locks.
Locking during Hot Standby
--------------------------
static const LockMethodData user_lockmethod = {
AccessExclusiveLock, /* highest valid lock mode number */
- fals e,
+ tru e,
LockConflicts,
lock_mode_names,
#ifdef LOCK_DEBUG
static void RemoveLocalLock(LOCALLOCK *locallock);
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner);
+static void ReleaseLockForOwner(LOCALLOCK *locallock, ResourceOwner owner);
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
PROCLOCK *proclock, LockMethod lockMethodTable);
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock,
return TRUE;
}
+/*
+ * LockReleaseSession -- Release all session locks of the specified lock method
+ * that are held by the current process.
+ */
+void
+LockReleaseSession(LOCKMETHODID lockmethodid)
+{
+ HASH_SEQ_STATUS status;
+ LOCALLOCK *locallock;
+
+ if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
+
+ hash_seq_init(&status, LockMethodLocalHash);
+
+ while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
+ {
+ /* Ignore items that are not of the specified lock method */
+ if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
+ continue;
+
+ ReleaseLockForOwner(locallock, NULL);
+ }
+}
+
/*
* LockReleaseAll -- Release all locks of the specified lock method that
* are held by the current process.
{
HASH_SEQ_STATUS status;
LOCALLOCK *locallock;
- LOCALLOCKOWNER *lockOwners;
- int i;
hash_seq_init(&status, LockMethodLocalHash);
if (!LockMethods[LOCALLOCK_LOCKMETHOD(*locallock)]->transactional)
continue;
- /* Scan to see if there are any locks belonging to current owner */
- lockOwners = locallock->lockOwners;
- for (i = locallock->numLockOwners - 1; i >= 0; i--)
+ ReleaseLockForOwner(locallock, CurrentResourceOwner);
+ }
+}
+
+/*
+ * Subroutine to release a lock belonging to the 'owner' if found.
+ * 'owner' can be NULL to release a session lock.
+ */
+static void
+ReleaseLockForOwner(LOCALLOCK *locallock, ResourceOwner owner)
+{
+ int i;
+ LOCALLOCKOWNER *lockOwners;
+
+ /* Scan to see if there are any locks belonging to the owner */
+ lockOwners = locallock->lockOwners;
+ for (i = locallock->numLockOwners - 1; i >= 0; i--)
+ {
+ if (lockOwners[i].owner == owner)
{
- if (lockOwners[i].owner == CurrentResourceOwner)
+ Assert(lockOwners[i].nLocks > 0);
+ if (lockOwners[i].nLocks < locallock->nLocks)
{
- Assert(lockOwners[i].nLocks > 0);
- if (lockOwners[i].nLocks < locallock->nLocks)
- {
- /*
- * We will still hold this lock after forgetting this
- * ResourceOwner.
- */
- locallock->nLocks -= lockOwners[i].nLocks;
- /* compact out unused slot */
- locallock->numLockOwners--;
- if (i < locallock->numLockOwners)
- lockOwners[i] = lockOwners[locallock->numLockOwners];
- }
- else
- {
- Assert(lockOwners[i].nLocks == locallock->nLocks);
- /* We want to call LockRelease just once */
- lockOwners[i].nLocks = 1;
- locallock->nLocks = 1;
- if (!LockRelease(&locallock->tag.lock,
- locallock->tag.mode,
- false))
- elog(WARNING, "LockReleaseCurrentOwner: failed??");
- }
- break;
+ /*
+ * We will still hold this lock after forgetting this
+ * ResourceOwner.
+ */
+ locallock->nLocks -= lockOwners[i].nLocks;
+ /* compact out unused slot */
+ locallock->numLockOwners--;
+ if (i < locallock->numLockOwners)
+ lockOwners[i] = lockOwners[locallock->numLockOwners];
+ }
+ else
+ {
+ Assert(lockOwners[i].nLocks == locallock->nLocks);
+ /* We want to call LockRelease just once */
+ lockOwners[i].nLocks = 1;
+ locallock->nLocks = 1;
+ if (!LockRelease(&locallock->tag.lock,
+ locallock->tag.mode,
+ owner == NULL))
+ elog(WARNING, "ReleaseLockForOwner: failed??");
}
+ break;
}
}
}
* At subtransaction abort, we release all locks held by the subtransaction;
* this is implemented by retail releasing of the locks under control of
* the ResourceOwner mechanism.
- *
- * Note that user locks are not released in any case.
*/
void
ProcReleaseLocks(bool isCommit)
LockWaitCancel();
/* Release locks */
LockReleaseAll(DEFAULT_LOCKMETHOD, !isCommit);
+
+ /* Release transaction level advisory locks */
+ LockReleaseAll(USER_LOCKMETHOD, false);
}
PG_RETURN_VOID();
}
+/*
+ * pg_advisory_xact_lock(int8) - acquire xact scoped
+ * exclusive lock on an int8 key
+ */
+Datum
+pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
+{
+ int64 key = PG_GETARG_INT64(0);
+ LOCKTAG tag;
+
+ SET_LOCKTAG_INT64(tag, key);
+
+ (void) LockAcquire(&tag, ExclusiveLock, false, false);
+
+ PG_RETURN_VOID();
+}
+
/*
* pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
*/
PG_RETURN_VOID();
}
+/*
+ * pg_advisory_xact_lock_shared(int8) - acquire xact scoped
+ * share lock on an int8 key
+ */
+Datum
+pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
+{
+ int64 key = PG_GETARG_INT64(0);
+ LOCKTAG tag;
+
+ SET_LOCKTAG_INT64(tag, key);
+
+ (void) LockAcquire(&tag, ShareLock, false, false);
+
+ PG_RETURN_VOID();
+}
+
/*
* pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
*
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}
+/*
+ * pg_try_advisory_xact_lock(int8) - acquire xact scoped
+ * exclusive lock on an int8 key, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
+{
+ int64 key = PG_GETARG_INT64(0);
+ LOCKTAG tag;
+ LockAcquireResult res;
+
+ SET_LOCKTAG_INT64(tag, key);
+
+ res = LockAcquire(&tag, ExclusiveLock, false, true);
+
+ PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
/*
* pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
*
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}
+/*
+ * pg_try_advisory_xact_lock_shared(int8) - acquire xact scoped
+ * share lock on an int8 key, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
+{
+ int64 key = PG_GETARG_INT64(0);
+ LOCKTAG tag;
+ LockAcquireResult res;
+
+ SET_LOCKTAG_INT64(tag, key);
+
+ res = LockAcquire(&tag, ShareLock, false, true);
+
+ PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
/*
* pg_advisory_unlock(int8) - release exclusive lock on an int8 key
*
PG_RETURN_VOID();
}
+/*
+ * pg_advisory_xact_lock(int4, int4) - acquire xact scoped
+ * exclusive lock on 2 int4 keys
+ */
+Datum
+pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
+{
+ int32 key1 = PG_GETARG_INT32(0);
+ int32 key2 = PG_GETARG_INT32(1);
+ LOCKTAG tag;
+
+ SET_LOCKTAG_INT32(tag, key1, key2);
+
+ (void) LockAcquire(&tag, ExclusiveLock, false, false);
+
+ PG_RETURN_VOID();
+}
+
/*
* pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
*/
PG_RETURN_VOID();
}
+/*
+ * pg_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
+ * share lock on 2 int4 keys
+ */
+Datum
+pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
+{
+ int32 key1 = PG_GETARG_INT32(0);
+ int32 key2 = PG_GETARG_INT32(1);
+ LOCKTAG tag;
+
+ SET_LOCKTAG_INT32(tag, key1, key2);
+
+ (void) LockAcquire(&tag, ShareLock, false, false);
+
+ PG_RETURN_VOID();
+}
+
/*
* pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
*
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}
+/*
+ * pg_try_advisory_xact_lock(int4, int4) - acquire xact scoped
+ * exclusive lock on 2 int4 keys, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
+{
+ int32 key1 = PG_GETARG_INT32(0);
+ int32 key2 = PG_GETARG_INT32(1);
+ LOCKTAG tag;
+ LockAcquireResult res;
+
+ SET_LOCKTAG_INT32(tag, key1, key2);
+
+ res = LockAcquire(&tag, ExclusiveLock, false, true);
+
+ PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
/*
* pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
*
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}
+/*
+ * pg_try_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
+ * share lock on 2 int4 keys, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
+{
+ int32 key1 = PG_GETARG_INT32(0);
+ int32 key2 = PG_GETARG_INT32(1);
+ LOCKTAG tag;
+ LockAcquireResult res;
+
+ SET_LOCKTAG_INT32(tag, key1, key2);
+
+ res = LockAcquire(&tag, ShareLock, false, true);
+
+ PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
/*
* pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
*
Datum
pg_advisory_unlock_all(PG_FUNCTION_ARGS)
{
- LockReleaseAll(USER_LOCKMETHOD, true );
+ LockReleaseSession(USER_LOCKMETHOD );
PG_RETURN_VOID();
}
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 20110217 1
+#define CATALOG_VERSION_NO 20110218 1
#endif
/* userlock replacements */
DATA(insert OID = 2880 ( pg_advisory_lock PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_lock_int8 _null_ _null_ _null_ ));
+DESCR("obtain exclusive a4dvisory lock");
+DATA(insert OID = 3089 ( pg_advisory_xact_lock PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_int8 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock");
DATA(insert OID = 2881 ( pg_advisory_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_lock_shared_int8 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock");
+DATA(insert OID = 3090 ( pg_advisory_xact_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "20" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_shared_int8 _null_ _null_ _null_ ));
+DESCR("obtain shared advisory lock");
DATA(insert OID = 2882 ( pg_try_advisory_lock PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_try_advisory_lock_int8 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock if available");
+DATA(insert OID = 3091 ( pg_try_advisory_xact_lock PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_int8 _null_ _null_ _null_ ));
+DESCR("obtain exclusive advisory lock if available");
DATA(insert OID = 2883 ( pg_try_advisory_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_try_advisory_lock_shared_int8 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock if available");
+DATA(insert OID = 3092 ( pg_try_advisory_xact_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_shared_int8 _null_ _null_ _null_ ));
+DESCR("obtain shared advisory lock if available");
DATA(insert OID = 2884 ( pg_advisory_unlock PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_advisory_unlock_int8 _null_ _null_ _null_ ));
DESCR("release exclusive advisory lock");
DATA(insert OID = 2885 ( pg_advisory_unlock_shared PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "20" _null_ _null_ _null_ _null_ pg_advisory_unlock_shared_int8 _null_ _null_ _null_ ));
DESCR("release shared advisory lock");
DATA(insert OID = 2886 ( pg_advisory_lock PGNSP PGUID 12 1 0 0 f f f t f v 2 0 2278 "23 23" _null_ _null_ _null_ _null_ pg_advisory_lock_int4 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock");
+DATA(insert OID = 3093 ( pg_advisory_xact_lock PGNSP PGUID 12 1 0 0 f f f t f v 2 0 2278 "23 23" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_int4 _null_ _null_ _null_ ));
+DESCR("obtain exclusive advisory lock");
DATA(insert OID = 2887 ( pg_advisory_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 2 0 2278 "23 23" _null_ _null_ _null_ _null_ pg_advisory_lock_shared_int4 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock");
+DATA(insert OID = 3094 ( pg_advisory_xact_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 2 0 2278 "23 23" _null_ _null_ _null_ _null_ pg_advisory_xact_lock_shared_int4 _null_ _null_ _null_ ));
+DESCR("obtain shared advisory lock");
DATA(insert OID = 2888 ( pg_try_advisory_lock PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_try_advisory_lock_int4 _null_ _null_ _null_ ));
DESCR("obtain exclusive advisory lock if available");
+DATA(insert OID = 3095 ( pg_try_advisory_xact_lock PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_int4 _null_ _null_ _null_ ));
+DESCR("obtain exclusive advisory lock if available");
DATA(insert OID = 2889 ( pg_try_advisory_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_try_advisory_lock_shared_int4 _null_ _null_ _null_ ));
DESCR("obtain shared advisory lock if available");
+DATA(insert OID = 3096 ( pg_try_advisory_xact_lock_shared PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_shared_int4 _null_ _null_ _null_ ));
+DESCR("obtain shared advisory lock if available");
DATA(insert OID = 2890 ( pg_advisory_unlock PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_advisory_unlock_int4 _null_ _null_ _null_ ));
DESCR("release exclusive advisory lock");
DATA(insert OID = 2891 ( pg_advisory_unlock_shared PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_advisory_unlock_shared_int4 _null_ _null_ _null_ ));
bool report_memory_error);
extern bool LockRelease(const LOCKTAG *locktag,
LOCKMODE lockmode, bool sessionLock);
+extern void LockReleaseSession(LOCKMETHODID lockmethodid);
extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
extern void LockReleaseCurrentOwner(void);
extern void LockReassignCurrentOwner(void);
/* lockfuncs.c */
extern Datum pg_lock_status(PG_FUNCTION_ARGS);
extern Datum pg_advisory_lock_int8(PG_FUNCTION_ARGS);
+extern Datum pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS);
extern Datum pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS);
+extern Datum pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS);
extern Datum pg_try_advisory_lock_int8(PG_FUNCTION_ARGS);
+extern Datum pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS);
extern Datum pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS);
+extern Datum pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS);
extern Datum pg_advisory_unlock_int8(PG_FUNCTION_ARGS);
extern Datum pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS);
extern Datum pg_advisory_lock_int4(PG_FUNCTION_ARGS);
+extern Datum pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS);
extern Datum pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS);
+extern Datum pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS);
extern Datum pg_try_advisory_lock_int4(PG_FUNCTION_ARGS);
+extern Datum pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS);
extern Datum pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS);
+extern Datum pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS);
extern Datum pg_advisory_unlock_int4(PG_FUNCTION_ARGS);
extern Datum pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS);
extern Datum pg_advisory_unlock_all(PG_FUNCTION_ARGS);
--- /dev/null
+--
+-- ADVISORY LOCKS
+--
+BEGIN;
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+ pg_advisory_xact_lock | pg_advisory_xact_lock_shared | pg_advisory_xact_lock | pg_advisory_xact_lock_shared
+-----------------------+------------------------------+-----------------------+------------------------------
+ | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+-- pg_advisory_unlock_all() shouldn't release xact locks
+SELECT pg_advisory_unlock_all();
+ pg_advisory_unlock_all
+------------------------
+
+(1 row)
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 4
+(1 row)
+
+-- can't unlock xact locks
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock_shared(2, 2);
+WARNING: you don't own a lock of type ExclusiveLock
+WARNING: you don't own a lock of type ShareLock
+WARNING: you don't own a lock of type ExclusiveLock
+WARNING: you don't own a lock of type ShareLock
+ pg_advisory_unlock | pg_advisory_unlock_shared | pg_advisory_unlock | pg_advisory_unlock_shared
+--------------------+---------------------------+--------------------+---------------------------
+ f | f | f | f
+(1 row)
+
+-- automatically release xact locks at commit
+COMMIT;
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
+BEGIN;
+-- holding both session and xact locks on the same objects, xact first
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+ pg_advisory_xact_lock | pg_advisory_xact_lock_shared | pg_advisory_xact_lock | pg_advisory_xact_lock_shared
+-----------------------+------------------------------+-----------------------+------------------------------
+ | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2);
+ pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock | pg_advisory_lock_shared
+------------------+-------------------------+------------------+-------------------------
+ | | |
+(1 row)
+
+ROLLBACK;
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+-- unlocking session locks
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock(1),
+ pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
+ pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
+WARNING: you don't own a lock of type ExclusiveLock
+WARNING: you don't own a lock of type ShareLock
+WARNING: you don't own a lock of type ExclusiveLock
+WARNING: you don't own a lock of type ShareLock
+ pg_advisory_unlock | pg_advisory_unlock | pg_advisory_unlock_shared | pg_advisory_unlock_shared | pg_advisory_unlock | pg_advisory_unlock | pg_advisory_unlock_shared | pg_advisory_unlock_shared
+--------------------+--------------------+---------------------------+---------------------------+--------------------+--------------------+---------------------------+---------------------------
+ t | f | t | f | t | f | t | f
+(1 row)
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
+BEGIN;
+-- holding both session and xact locks on the same objects, session first
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2);
+ pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock | pg_advisory_lock_shared
+------------------+-------------------------+------------------+-------------------------
+ | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+ pg_advisory_xact_lock | pg_advisory_xact_lock_shared | pg_advisory_xact_lock | pg_advisory_xact_lock_shared
+-----------------------+------------------------------+-----------------------+------------------------------
+ | | |
+(1 row)
+
+ROLLBACK;
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+-- releasing all session locks
+SELECT pg_advisory_unlock_all();
+ pg_advisory_unlock_all
+------------------------
+
+(1 row)
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
+BEGIN;
+-- grabbing txn locks multiple times
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock(1),
+ pg_advisory_xact_lock_shared(2), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock(1, 1),
+ pg_advisory_xact_lock_shared(2, 2), pg_advisory_xact_lock_shared(2, 2);
+ pg_advisory_xact_lock | pg_advisory_xact_lock | pg_advisory_xact_lock_shared | pg_advisory_xact_lock_shared | pg_advisory_xact_lock | pg_advisory_xact_lock | pg_advisory_xact_lock_shared | pg_advisory_xact_lock_shared
+-----------------------+-----------------------+------------------------------+------------------------------+-----------------------+-----------------------+------------------------------+------------------------------
+ | | | | | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+COMMIT;
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
+-- grabbing session locks multiple times
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock(1),
+ pg_advisory_lock_shared(2), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock(1, 1),
+ pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
+ pg_advisory_lock | pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock_shared | pg_advisory_lock | pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock_shared
+------------------+------------------+-------------------------+-------------------------+------------------+------------------+-------------------------+-------------------------
+ | | | | | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock(1),
+ pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
+ pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
+ pg_advisory_unlock | pg_advisory_unlock | pg_advisory_unlock_shared | pg_advisory_unlock_shared | pg_advisory_unlock | pg_advisory_unlock | pg_advisory_unlock_shared | pg_advisory_unlock_shared
+--------------------+--------------------+---------------------------+---------------------------+--------------------+--------------------+---------------------------+---------------------------
+ t | t | t | t | t | t | t | t
+(1 row)
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
+-- .. and releasing them all at once
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock(1),
+ pg_advisory_lock_shared(2), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock(1, 1),
+ pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
+ pg_advisory_lock | pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock_shared | pg_advisory_lock | pg_advisory_lock | pg_advisory_lock_shared | pg_advisory_lock_shared
+------------------+------------------+-------------------------+-------------------------+------------------+------------------+-------------------------+-------------------------
+ | | | | | | |
+(1 row)
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+ locktype | classid | objid | objsubid | mode | granted
+----------+---------+-------+----------+---------------+---------
+ advisory | 0 | 1 | 1 | ExclusiveLock | t
+ advisory | 0 | 2 | 1 | ShareLock | t
+ advisory | 1 | 1 | 2 | ExclusiveLock | t
+ advisory | 2 | 2 | 2 | ShareLock | t
+(4 rows)
+
+SELECT pg_advisory_unlock_all();
+ pg_advisory_unlock_all
+------------------------
+
+(1 row)
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+ count
+-------
+ 0
+(1 row)
+
# ----------
# Another group of parallel tests
# ----------
-test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps
+test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock
# ----------
# Another group of parallel tests
test: window
test: xmlmap
test: functional_deps
+test: advisory_lock
test: plancache
test: limit
test: plpgsql
--- /dev/null
+--
+-- ADVISORY LOCKS
+--
+
+BEGIN;
+
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+
+-- pg_advisory_unlock_all() shouldn't release xact locks
+SELECT pg_advisory_unlock_all();
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+
+-- can't unlock xact locks
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock_shared(2, 2);
+
+
+-- automatically release xact locks at commit
+COMMIT;
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+
+BEGIN;
+
+-- holding both session and xact locks on the same objects, xact first
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2);
+
+ROLLBACK;
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+
+-- unlocking session locks
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock(1),
+ pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
+ pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+
+BEGIN;
+
+-- holding both session and xact locks on the same objects, session first
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
+
+ROLLBACK;
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+
+-- releasing all session locks
+SELECT pg_advisory_unlock_all();
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+
+BEGIN;
+
+-- grabbing txn locks multiple times
+
+SELECT
+ pg_advisory_xact_lock(1), pg_advisory_xact_lock(1),
+ pg_advisory_xact_lock_shared(2), pg_advisory_xact_lock_shared(2),
+ pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock(1, 1),
+ pg_advisory_xact_lock_shared(2, 2), pg_advisory_xact_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+COMMIT;
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+-- grabbing session locks multiple times
+
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock(1),
+ pg_advisory_lock_shared(2), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock(1, 1),
+ pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+SELECT
+ pg_advisory_unlock(1), pg_advisory_unlock(1),
+ pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2),
+ pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
+ pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+
+-- .. and releasing them all at once
+
+SELECT
+ pg_advisory_lock(1), pg_advisory_lock(1),
+ pg_advisory_lock_shared(2), pg_advisory_lock_shared(2),
+ pg_advisory_lock(1, 1), pg_advisory_lock(1, 1),
+ pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
+
+SELECT locktype, classid, objid, objsubid, mode, granted
+ FROM pg_locks WHERE locktype = 'advisory'
+ ORDER BY classid, objid, objsubid;
+
+SELECT pg_advisory_unlock_all();
+
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';