524 lines
15 KiB
Plaintext
524 lines
15 KiB
Plaintext
<!--
|
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/lock.sgml,v 1.33 2002/05/30 20:45:18 tgl Exp $
|
|
PostgreSQL documentation
|
|
-->
|
|
|
|
<refentry id="SQL-LOCK">
|
|
<refmeta>
|
|
<refentrytitle id="sql-lock-title">LOCK</refentrytitle>
|
|
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
|
</refmeta>
|
|
<refnamediv>
|
|
<refname>
|
|
LOCK
|
|
</refname>
|
|
<refpurpose>
|
|
explicitly lock a table
|
|
</refpurpose>
|
|
</refnamediv>
|
|
<refsynopsisdiv>
|
|
<refsynopsisdivinfo>
|
|
<date>2001-07-09</date>
|
|
</refsynopsisdivinfo>
|
|
<synopsis>
|
|
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...]
|
|
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] IN <replaceable class="PARAMETER">lockmode</replaceable> MODE
|
|
|
|
where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
|
|
|
|
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE |
|
|
SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
|
|
</synopsis>
|
|
|
|
<refsect2 id="R2-SQL-LOCK-1">
|
|
<refsect2info>
|
|
<date>1999-06-09</date>
|
|
</refsect2info>
|
|
|
|
<title>
|
|
Inputs
|
|
</title>
|
|
<para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><replaceable class="PARAMETER">name</replaceable></term>
|
|
<listitem>
|
|
<para>
|
|
The name (optionally schema-qualified) of an existing table to lock.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ACCESS SHARE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
This is the least restrictive lock mode. It conflicts only with
|
|
ACCESS EXCLUSIVE mode. It is used to protect a table from being
|
|
modified by concurrent <command>ALTER TABLE</command>,
|
|
<command>DROP TABLE</command> and <command>VACUUM FULL</command>
|
|
commands.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The <command>SELECT</command> command acquires a
|
|
lock of this mode on referenced tables. In general, any query
|
|
that only reads a table and does not modify it will acquire
|
|
this lock mode.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ROW SHARE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with EXCLUSIVE and ACCESS EXCLUSIVE lock modes.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The <command>SELECT FOR UPDATE</command> command acquires a
|
|
lock of this mode on the target table(s) (in addition to
|
|
<literal>ACCESS SHARE</literal> locks on any other tables
|
|
that are referenced but not selected <option>FOR UPDATE</option>).
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ROW EXCLUSIVE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE and
|
|
ACCESS EXCLUSIVE modes.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The commands <command>UPDATE</command>,
|
|
<command>DELETE</command>, and <command>INSERT</command>
|
|
acquire this lock mode on the target table (in addition to
|
|
<literal>ACCESS SHARE</literal> locks on any other referenced
|
|
tables). In general, this lock mode will be acquired by any
|
|
query that modifies the data in a table.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>SHARE UPDATE EXCLUSIVE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE,
|
|
EXCLUSIVE and
|
|
ACCESS EXCLUSIVE modes. This mode protects a table against
|
|
concurrent schema changes and VACUUMs.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Acquired by <command>VACUUM</command> (without
|
|
<option>FULL</option>).
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>SHARE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE,
|
|
SHARE ROW EXCLUSIVE, EXCLUSIVE and
|
|
ACCESS EXCLUSIVE modes. This mode protects a table against
|
|
concurrent data changes.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Acquired by <command>CREATE INDEX</command>.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>SHARE ROW EXCLUSIVE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE,
|
|
SHARE ROW EXCLUSIVE, EXCLUSIVE and ACCESS EXCLUSIVE modes.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
This lock mode is not automatically acquired by any
|
|
<productname>PostgreSQL</productname> command.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>EXCLUSIVE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE,
|
|
SHARE, SHARE ROW EXCLUSIVE,
|
|
EXCLUSIVE and ACCESS EXCLUSIVE modes.
|
|
This mode allows only concurrent ACCESS SHARE, i.e., only reads
|
|
from the table can proceed in parallel with a transaction holding
|
|
this lock mode.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
This lock mode is not automatically acquired by any
|
|
<productname>PostgreSQL</productname> command.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ACCESS EXCLUSIVE MODE</term>
|
|
<listitem>
|
|
<para>
|
|
Conflicts with all lock modes. This mode guarantees that the
|
|
holder is the only transaction accessing the table in any way.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Acquired by <command>ALTER TABLE</command>,
|
|
<command>DROP TABLE</command>, and <command>VACUUM FULL</command>
|
|
statements.
|
|
This is also the default lock mode for <command>LOCK TABLE</command>
|
|
statements that do not specify a mode explicitly.
|
|
</para>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</refsect2>
|
|
|
|
<refsect2 id="R2-SQL-LOCK-2">
|
|
<refsect2info>
|
|
<date>1998-09-24</date>
|
|
</refsect2info>
|
|
<title>
|
|
Outputs
|
|
</title>
|
|
<para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><computeroutput>
|
|
LOCK TABLE
|
|
</computeroutput></term>
|
|
<listitem>
|
|
<para>
|
|
The lock was successfully acquired.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><computeroutput>
|
|
ERROR <replaceable class="PARAMETER">name</replaceable>: Table does not exist.
|
|
</computeroutput></term>
|
|
<listitem>
|
|
<para>
|
|
Message returned if <replaceable class="PARAMETER">name</replaceable>
|
|
does not exist.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</refsect2>
|
|
</refsynopsisdiv>
|
|
|
|
<refsect1 id="R1-SQL-LOCK-1">
|
|
<refsect1info>
|
|
<date>1998-09-24</date>
|
|
</refsect1info>
|
|
<title>
|
|
Description
|
|
</title>
|
|
|
|
<para>
|
|
<command>LOCK TABLE</command> obtains a table-level lock, waiting if
|
|
necessary for any conflicting locks to be released. Once obtained,
|
|
the lock is held for the remainder of the current transaction.
|
|
(There is no <command>UNLOCK TABLE</command> command; locks are always
|
|
released at transaction end.)
|
|
</para>
|
|
|
|
<para>
|
|
When acquiring locks automatically for commands that reference tables,
|
|
<productname>PostgreSQL</productname> always uses the least restrictive
|
|
lock mode possible. <command>LOCK TABLE</command>
|
|
provides for cases when you might need more restrictive locking.
|
|
</para>
|
|
|
|
<para>
|
|
For example, suppose an application runs a transaction at READ COMMITTED
|
|
isolation level and needs to ensure that data in a table remains stable
|
|
for the duration of the
|
|
transaction. To achieve this you could obtain SHARE lock mode over the
|
|
table before querying. This will prevent concurrent data changes
|
|
and ensure subsequent reads of the table see a stable
|
|
view of committed data, because SHARE lock mode conflicts with the ROW
|
|
EXCLUSIVE lock acquired by writers, and your
|
|
<command>LOCK TABLE <replaceable class="PARAMETER">name</replaceable> IN SHARE MODE</command>
|
|
statement will wait until any concurrent holders of ROW EXCLUSIVE mode
|
|
commit or roll back. Thus, once you obtain the lock, there are no
|
|
uncommitted writes outstanding; furthermore none can begin until you
|
|
release the lock.
|
|
|
|
<note>
|
|
<para>
|
|
To achieve a similar effect when running a transaction
|
|
at the SERIALIZABLE isolation level, you have to execute the
|
|
<command>LOCK TABLE</>
|
|
statement before executing any DML statement. A serializable
|
|
transaction's view of data will be frozen when its first DML statement
|
|
begins. A later <command>LOCK</> will still prevent concurrent writes
|
|
--- but it
|
|
won't ensure that what the transaction reads corresponds to the latest
|
|
committed values.
|
|
</para>
|
|
</note>
|
|
</para>
|
|
|
|
<para>
|
|
If a transaction of this sort is going to
|
|
change the data in the table, then it should use SHARE ROW EXCLUSIVE lock
|
|
mode instead of SHARE mode. This ensures that only one transaction of
|
|
this type runs at a time. Without this, a deadlock is possible: two
|
|
transactions might both acquire SHARE mode, and then be unable to also
|
|
acquire ROW EXCLUSIVE mode to actually perform their updates. (Note that
|
|
a transaction's own locks never conflict, so a transaction can acquire
|
|
ROW EXCLUSIVE mode when it holds SHARE mode --- but not if anyone else
|
|
holds SHARE mode.)
|
|
</para>
|
|
|
|
<para>
|
|
Two general rules may be followed to prevent deadlock conditions:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Transactions have to acquire locks on the same objects in the same order.
|
|
</para>
|
|
|
|
<para>
|
|
For example, if one application updates row R1 and than updates
|
|
row R2 (in the same transaction) then the second application shouldn't
|
|
update row R2 if it's going to update row R1 later (in a single transaction).
|
|
Instead, it should update rows R1 and R2 in the same order as the first
|
|
application.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If multiple lock modes are involved for a single object,
|
|
then transactions should always acquire the most restrictive mode first.
|
|
</para>
|
|
|
|
<para>
|
|
An example for this rule was given previously when discussing the
|
|
use of SHARE ROW EXCLUSIVE mode rather than SHARE mode.
|
|
</para>
|
|
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> does detect deadlocks and will
|
|
rollback at least one waiting transaction to resolve the deadlock.
|
|
If it is not practical to code an application to follow the above rules
|
|
strictly, an alternative solution is to be prepared to retry transactions
|
|
when they are aborted by deadlocks.
|
|
</para>
|
|
|
|
<para>
|
|
When locking multiple tables, the command <literal>LOCK a, b;</> is
|
|
equivalent to <literal>LOCK a; LOCK b;</>. The tables are locked one-by-one
|
|
in the order specified in the
|
|
<command>LOCK</command> command.
|
|
</para>
|
|
|
|
<refsect2 id="R2-SQL-LOCK-3">
|
|
<refsect2info>
|
|
<date>1999-06-08</date>
|
|
</refsect2info>
|
|
<title>
|
|
Notes
|
|
</title>
|
|
|
|
<para>
|
|
<literal>LOCK ... IN ACCESS SHARE MODE</> requires <literal>SELECT</>
|
|
privileges on the target table. All other forms of <command>LOCK</>
|
|
require <literal>UPDATE</> and/or <literal>DELETE</> privileges.
|
|
</para>
|
|
|
|
<para>
|
|
<command>LOCK</command> is useful only inside a transaction block
|
|
(<command>BEGIN</>...<command>COMMIT</>), since the lock is dropped
|
|
as soon as the transaction ends. A <command>LOCK</> command appearing
|
|
outside any transaction block forms a self-contained transaction, so the
|
|
lock will be dropped as soon as it is obtained.
|
|
</para>
|
|
|
|
<para>
|
|
<acronym>RDBMS</acronym> locking uses the following standard terminology:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>EXCLUSIVE</term>
|
|
<listitem>
|
|
<para>
|
|
An exclusive lock prevents other locks of the same type from being
|
|
granted.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>SHARE</term>
|
|
<listitem>
|
|
<para>
|
|
A shared lock allows others to also hold the same type of lock,
|
|
but prevents the corresponding EXCLUSIVE lock from being granted.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ACCESS</term>
|
|
<listitem>
|
|
<para>
|
|
Locks table schema.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>ROW</term>
|
|
<listitem>
|
|
<para>
|
|
Locks individual rows.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> does not follow this terminology
|
|
exactly. <command>LOCK TABLE</> only deals with table-level locks, and
|
|
so the mode names involving ROW are all misnomers. These mode names
|
|
should generally be read as indicating the intention of the user to
|
|
acquire row-level locks within the locked table. Also,
|
|
ROW EXCLUSIVE mode does not follow this naming convention accurately,
|
|
since it is a sharable table lock. Keep in mind that all the lock modes
|
|
have identical semantics so far as <command>LOCK TABLE</> is concerned,
|
|
differing only in the rules about which modes conflict with which.
|
|
</para>
|
|
|
|
</refsect2>
|
|
</refsect1>
|
|
|
|
<refsect1 id="R1-SQL-LOCK-2">
|
|
<title>
|
|
Usage
|
|
</title>
|
|
|
|
<para>
|
|
Obtain a SHARE lock on a primary key table when going to perform
|
|
inserts into a foreign key table:
|
|
|
|
<programlisting>
|
|
BEGIN WORK;
|
|
LOCK TABLE films IN SHARE MODE;
|
|
SELECT id FROM films
|
|
WHERE name = 'Star Wars: Episode I - The Phantom Menace';
|
|
-- Do ROLLBACK if record was not returned
|
|
INSERT INTO films_user_comments VALUES
|
|
(_id_, 'GREAT! I was waiting for it for so long!');
|
|
COMMIT WORK;
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Take a SHARE ROW EXCLUSIVE lock on a primary key table when going to perform
|
|
a delete operation:
|
|
|
|
<programlisting>
|
|
BEGIN WORK;
|
|
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
|
|
DELETE FROM films_user_comments WHERE id IN
|
|
(SELECT id FROM films WHERE rating < 5);
|
|
DELETE FROM films WHERE rating < 5;
|
|
COMMIT WORK;
|
|
</programlisting>
|
|
</para>
|
|
</refsect1>
|
|
|
|
<refsect1 id="R1-SQL-LOCK-3">
|
|
<title>
|
|
Compatibility
|
|
</title>
|
|
|
|
<refsect2 id="R2-SQL-LOCK-4">
|
|
<refsect2info>
|
|
<date>1998-09-24</date>
|
|
</refsect2info>
|
|
<title>
|
|
SQL92
|
|
</title>
|
|
<para>
|
|
There is no <command>LOCK TABLE</command> in <acronym>SQL92</acronym>,
|
|
which instead uses <command>SET TRANSACTION</command> to specify
|
|
concurrency levels on transactions. We support that too; see
|
|
<xref linkend="SQL-SET-TRANSACTION" endterm="SQL-SET-TRANSACTION-TITLE"> for details.
|
|
</para>
|
|
|
|
<para>
|
|
Except for ACCESS SHARE, ACCESS EXCLUSIVE, and SHARE UPDATE EXCLUSIVE lock
|
|
modes, the <productname>PostgreSQL</productname> lock modes and the
|
|
<command>LOCK TABLE</command> syntax are compatible with those
|
|
present in <productname>Oracle</productname>(TM).
|
|
</para>
|
|
</refsect2>
|
|
</refsect1>
|
|
</refentry>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:nil
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"../reference.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
-->
|