Extend the pg_locks system view so that it can fully display all lock

types, as per recent discussion.
This commit is contained in:
Tom Lane 2005-05-17 21:46:11 +00:00
parent 4e7d6f5349
commit a9c4c9cd52
7 changed files with 207 additions and 52 deletions

View File

@ -19,9 +19,9 @@
#define SET_LOCKTAG_USERLOCK(locktag,id1,id2) \
((locktag).locktag_field1 = (id1), \
(locktag).locktag_field2 = (id2), \
(locktag).locktag_field3 = MyDatabaseId, \
((locktag).locktag_field1 = MyDatabaseId, \
(locktag).locktag_field2 = (id1), \
(locktag).locktag_field3 = (id2), \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_USERLOCK)

View File

@ -1,6 +1,6 @@
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.101 2005/05/06 14:28:53 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.102 2005/05/17 21:46:09 tgl Exp $
-->
<chapter id="catalogs">
@ -4040,15 +4040,18 @@
lockable object may
appear many times, if multiple transactions are holding or waiting
for locks on it. However, an object that currently has no locks on it
will not appear at all. A lockable object is either a relation (e.g., a
table) or a transaction ID.
will not appear at all.
</para>
<para>
Note that this view includes only table-level
locks, not row-level ones. If a transaction is waiting for a
row-level lock, it will appear in the view as waiting for the
transaction ID of the current holder of that row lock.
There are several distinct types of lockable objects:
whole relations (e.g., tables), individual pages of relations,
individual tuples of relations,
transaction IDs,
and general database objects (identified by class OID and object OID,
in the same way as in <structname>pg_description</structname> or
<structname>pg_depend</structname>). Also, the right to extend a
relation is represented as a separate lockable object.
</para>
<table>
@ -4065,12 +4068,18 @@
</thead>
<tbody>
<row>
<entry><structfield>relation</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
<entry><structfield>locktype</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>
OID of the locked relation, or NULL if the lockable object
is a transaction ID
type of the lockable object:
<literal>relation</>,
<literal>extend</>,
<literal>page</>,
<literal>tuple</>,
<literal>transaction</>,
<literal>object</>, or
<literal>userlock</>
</entry>
</row>
<row>
@ -4078,9 +4087,35 @@
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
<entry>
OID of the database in which the locked relation exists, or
zero if the locked relation is a globally-shared table, or
NULL if the lockable object is a transaction ID
OID of the database in which the object exists, or
zero if the object is a globally-shared object, or
NULL if the object is a transaction ID
</entry>
</row>
<row>
<entry><structfield>relation</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
<entry>
OID of the relation, or NULL if the object is not
a relation or part of a relation
</entry>
</row>
<row>
<entry><structfield>page</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>
page number within the relation, or NULL if the object
is not a tuple or relation page
</entry>
</row>
<row>
<entry><structfield>tuple</structfield></entry>
<entry><type>smallint</type></entry>
<entry></entry>
<entry>
tuple number within the page, or NULL if the object is not a tuple
</entry>
</row>
<row>
@ -4088,14 +4123,43 @@
<entry><type>xid</type></entry>
<entry></entry>
<entry>
ID of a transaction, or NULL if the lockable object is a relation
ID of a transaction, or NULL if the object is not a transaction ID
</entry>
</row>
<row>
<entry><structfield>classid</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
<entry>
OID of the system catalog containing the object, or NULL if the
object is not a general database object
</entry>
</row>
<row>
<entry><structfield>objid</structfield></entry>
<entry><type>oid</type></entry>
<entry>any OID column</entry>
<entry>
OID of the object within its system catalog, or NULL if the
object is not a general database object
</entry>
</row>
<row>
<entry><structfield>objsubid</structfield></entry>
<entry><type>smallint</type></entry>
<entry></entry>
<entry>
For a table column, this is the column number (the
<structfield>classid</> and <structfield>objid</> refer to the
table itself). For all other object types, this column is
zero. NULL if the object is not a general database object
</entry>
</row>
<row>
<entry><structfield>pid</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>process ID of a server process holding or awaiting this
<entry>process ID of the server process holding or awaiting this
lock</entry>
</row>
<row>
@ -4133,6 +4197,21 @@
terminates and releases its locks.
</para>
<para>
Although tuples are a lockable type of object,
information about row-level locks is stored on disk, not in memory,
and therefore row-level locks normally do not appear in this view.
If a transaction is waiting for a
row-level lock, it will usually appear in the view as waiting for the
transaction ID of the current holder of that row lock.
</para>
<para>
If user-defined locks are in use, they are displayed using the columns
for general database objects. However, the actual meaning of the lock
fields in such cases is up to the user.
</para>
<para>
When the <structname>pg_locks</structname> view is accessed, the
internal lock manager data structures are momentarily locked, and

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.12 2005/05/09 11:31:32 neilc Exp $
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.13 2005/05/17 21:46:09 tgl Exp $
*/
CREATE VIEW pg_user AS
@ -261,8 +261,10 @@ CREATE VIEW pg_stat_database AS
CREATE VIEW pg_locks AS
SELECT *
FROM pg_lock_status() AS L(relation oid, database oid,
transaction xid, pid int4, mode text, granted boolean);
FROM pg_lock_status() AS L
(locktype text, database oid, relation oid, page int4, tuple int2,
transaction xid, classid oid, objid oid, objsubid int2,
pid int4, mode text, granted boolean);
CREATE VIEW pg_settings AS
SELECT *

View File

@ -6,7 +6,7 @@
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.17 2005/04/29 22:28:24 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.18 2005/05/17 21:46:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,6 +20,17 @@
#include "utils/builtins.h"
/* This must match enum LockTagType! */
static const char * const LockTagTypeNames[] = {
"relation",
"extend",
"page",
"tuple",
"transaction",
"object",
"userlock"
};
/* Working status for pg_lock_status */
typedef struct
{
@ -53,18 +64,30 @@ pg_lock_status(PG_FUNCTION_ARGS)
/* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */
tupdesc = CreateTemplateTupleDesc(6, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
OIDOID, -1, 0);
tupdesc = CreateTemplateTupleDesc(12, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "transaction",
XIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pid",
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "relation",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "page",
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "mode",
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple",
INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "transaction",
XIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 7, "classid",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 8, "objid",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objsubid",
INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "pid",
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "mode",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "granted",
TupleDescInitEntry(tupdesc, (AttrNumber) 12, "granted",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
@ -93,8 +116,10 @@ pg_lock_status(PG_FUNCTION_ARGS)
PGPROC *proc;
bool granted;
LOCKMODE mode = 0;
Datum values[6];
char nulls[6];
const char *locktypename;
char tnbuf[32];
Datum values[12];
char nulls[12];
HeapTuple tuple;
Datum result;
@ -155,30 +180,79 @@ pg_lock_status(PG_FUNCTION_ARGS)
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
if (lock->tag.locktag_type <= LOCKTAG_USERLOCK)
locktypename = LockTagTypeNames[lock->tag.locktag_type];
else
{
snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
(int) lock->tag.locktag_type);
locktypename = tnbuf;
}
values[0] = DirectFunctionCall1(textin,
CStringGetDatum(locktypename));
switch (lock->tag.locktag_type)
{
case LOCKTAG_RELATION:
case LOCKTAG_RELATION_EXTEND:
case LOCKTAG_PAGE:
case LOCKTAG_TUPLE:
values[0] = ObjectIdGetDatum(lock->tag.locktag_field2);
values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
nulls[2] = 'n';
values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
nulls[3] = 'n';
nulls[4] = 'n';
nulls[5] = 'n';
nulls[6] = 'n';
nulls[7] = 'n';
nulls[8] = 'n';
break;
case LOCKTAG_PAGE:
values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
values[3] = UInt32GetDatum(lock->tag.locktag_field3);
nulls[4] = 'n';
nulls[5] = 'n';
nulls[6] = 'n';
nulls[7] = 'n';
nulls[8] = 'n';
break;
case LOCKTAG_TUPLE:
values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
values[3] = UInt32GetDatum(lock->tag.locktag_field3);
values[4] = UInt16GetDatum(lock->tag.locktag_field4);
nulls[5] = 'n';
nulls[6] = 'n';
nulls[7] = 'n';
nulls[8] = 'n';
break;
case LOCKTAG_TRANSACTION:
nulls[0] = 'n';
values[5] = TransactionIdGetDatum(lock->tag.locktag_field1);
nulls[1] = 'n';
values[2] = TransactionIdGetDatum(lock->tag.locktag_field1);
nulls[2] = 'n';
nulls[3] = 'n';
nulls[4] = 'n';
nulls[6] = 'n';
nulls[7] = 'n';
nulls[8] = 'n';
break;
case LOCKTAG_OBJECT:
case LOCKTAG_USERLOCK:
default: /* treat unknown locktags like OBJECT */
values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
values[6] = ObjectIdGetDatum(lock->tag.locktag_field2);
values[7] = ObjectIdGetDatum(lock->tag.locktag_field3);
values[8] = Int16GetDatum(lock->tag.locktag_field4);
nulls[2] = 'n';
nulls[3] = 'n';
nulls[4] = 'n';
nulls[5] = 'n';
break;
default:
/* XXX Ignore all other lock types for now */
continue;
}
values[3] = Int32GetDatum(proc->pid);
values[4] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
values[5] = BoolGetDatum(granted);
values[9] = Int32GetDatum(proc->pid);
values[10] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
values[11] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.267 2005/05/09 11:31:34 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.268 2005/05/17 21:46:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200505091
#define CATALOG_VERSION_NO 200505171
#endif

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/catalog/pg_proc.h,v 1.361 2005/05/09 11:31:34 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.362 2005/05/17 21:46:10 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -2999,7 +2999,7 @@ DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 f f f f v 3 25 "25 25 16" _
DESCR("SET X as a function");
DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 f f t t s 0 2249 "" _null_ _null_ _null_ show_all_settings - _null_ ));
DESCR("SHOW ALL as a function");
DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 f f f t v 0 2249 "" _null_ _null_ _null_ pg_lock_status - _null_ ));
DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 f f t t v 0 2249 "" _null_ _null_ _null_ pg_lock_status - _null_ ));
DESCR("view system lock information");
DATA(insert OID = 2079 ( pg_table_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" _null_ _null_ _null_ pg_table_is_visible - _null_ ));

View File

@ -1278,7 +1278,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
pg_locks | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l."transaction", l.classid, l.objid, l.objsubid, l.pid, l."mode", l.granted FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, "transaction" xid, classid oid, objid oid, objsubid smallint, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start, pg_stat_get_backend_start(s.backendid) AS backend_start, pg_stat_get_backend_client_addr(s.backendid) AS client_addr, pg_stat_get_backend_client_port(s.backendid) AS client_port FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));