pg_locks pl LEFT JOIN pg_stat_activity psa
ON pl.pid = psa.pid;
</programlisting>
Also, if you are using prepared transactions, the
<structfield>virtualtransaction</structfield> column can be joined to the
<structfield>transaction</structfield> column of the <link
linkend="view-pg-prepared-xacts"><structname>pg_prepared_xacts</structname></link>
view to get more information on prepared transactions that hold locks.
(A prepared transaction can never be waiting for a lock,
but it continues to hold the locks it acquired while running.)
For example:
<programlisting>
SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
ON pl.virtualtransaction = '-1/' || ppx.transaction;
</programlisting>
</para>
<para>
While it is possible to obtain information about which processes block
which other processes by joining <structname>pg_locks</structname> against
itself, this is very difficult to get right in detail. Such a query would
have to encode knowledge about which lock modes conflict with which
others. Worse, the <structname>pg_locks</structname> view does not expose
information about which processes are ahead of which others in lock wait
queues, nor information about which processes are parallel workers running
on behalf of which other client sessions. It is better to use
the <function>pg_blocking_pids()</function> function
(see <xref linkend="functions-info-session-table"/>) to identify which
process(es) a waiting process is blocked behind.
</para>
<para>
The <structname>pg_locks</structname> view displays data from both the
regular lock manager and the predicate lock manager, which are
separate systems; in addition, the regular lock manager subdivides its
locks into regular and <firstterm>fast-path</firstterm> locks.
This data is not guaranteed to be entirely consistent.
When the view is queried,
data on fast-path locks (with <structfield>fastpath</structfield> = <literal>true</literal>)
is gathered from each backend one at a time, without freezing the state of
the entire lock manager, so it is possible for locks to be taken or
released while information is gathered. Note, however, that these locks are
known not to conflict with any other lock currently in place. After
all backends have been queried for fast-path locks, the remainder of the
regular lock manager is locked as a unit, and a consistent snapshot of all
remaining locks is collected as an atomic action. After unlocking the
regular lock manager, the predicate lock manager is similarly locked and all
predicate locks are collected as an atomic action. Thus, with the exception
of fast-path locks, each lock manager will deliver a consistent set of
results, but as we do not lock both lock managers simultaneously, it is
possible for locks to be taken or released after we interrogate the regular
lock manager and before we interrogate the predicate lock manager.
</para>
<para>
Locking the regular and/or predicate lock manager could have some
impact on database performance if this view is very frequently accessed.
The locks are held only for the minimum amount of time necessary to
obtain data from the lock managers, but this does not completely eliminate
the possibility of a performance impact.
</para>
</sect1>
<sect1 id="view-pg-matviews">
<title><structname>pg_matviews</structname></title>
<indexterm zone="view-pg-matviews">
<primary>pg_matviews</primary>
</indexterm>
<indexterm zone="view-pg-matviews">
<primary>materialized views</primary>
</indexterm>
<para>
The view <structname>pg_matviews</structname> provides access to
useful information about each materialized view in the database.
</para>
<table>
<title><structname>pg_matviews</structname> Columns</title>
<tgroup cols="1">
<thead>
<row>
<entry role="catalog_table_entry"><para role="column_definition">