mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Extend the pg_locks system view so that it can fully display all lock
types, as per recent discussion.
This commit is contained in:
parent
4e7d6f5349
commit
a9c4c9cd52
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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_ ));
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user