2000-03-31 05:27:42 +02:00
|
|
|
<!--
|
2004-12-24 00:07:38 +01:00
|
|
|
$PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.46 2004/12/23 23:07:38 tgl Exp $
|
2000-03-31 05:27:42 +02:00
|
|
|
-->
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<chapter id="mvcc">
|
2002-08-05 21:43:31 +02:00
|
|
|
<title>Concurrency Control</title>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
|
|
|
<primary>concurrency</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
2002-11-11 21:14:04 +01:00
|
|
|
<para>
|
2002-11-15 04:11:18 +01:00
|
|
|
This chapter describes the behavior of the
|
|
|
|
<productname>PostgreSQL</productname> database system when two or
|
|
|
|
more sessions try to access the same data at the same time. The
|
|
|
|
goals in that situation are to allow efficient access for all
|
|
|
|
sessions while maintaining strict data integrity. Every developer
|
|
|
|
of database applications should be familiar with the topics covered
|
|
|
|
in this chapter.
|
2002-11-11 21:14:04 +01:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="mvcc-intro">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Introduction</title>
|
|
|
|
|
2003-08-31 19:32:24 +02:00
|
|
|
<indexterm>
|
|
|
|
<primary>MVCC</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2002-11-11 21:14:04 +01:00
|
|
|
Unlike traditional database systems which use locks for concurrency control,
|
2001-11-21 06:53:41 +01:00
|
|
|
<productname>PostgreSQL</productname>
|
2002-11-11 21:14:04 +01:00
|
|
|
maintains data consistency by using a multiversion model
|
|
|
|
(Multiversion Concurrency Control, <acronym>MVCC</acronym>).
|
1999-05-27 17:49:08 +02:00
|
|
|
This means that while querying a database each transaction sees
|
1999-05-26 19:27:39 +02:00
|
|
|
a snapshot of data (a <firstterm>database version</firstterm>)
|
|
|
|
as it was some
|
1999-05-27 17:49:08 +02:00
|
|
|
time ago, regardless of the current state of the underlying data.
|
1999-05-26 19:27:39 +02:00
|
|
|
This protects the transaction from viewing inconsistent data that
|
|
|
|
could be caused by (other) concurrent transaction updates on the same
|
|
|
|
data rows, providing <firstterm>transaction isolation</firstterm>
|
|
|
|
for each database session.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2003-02-19 05:06:28 +01:00
|
|
|
The main advantage to using the <acronym>MVCC</acronym> model of
|
|
|
|
concurrency control rather than locking is that in
|
|
|
|
<acronym>MVCC</acronym> locks acquired for querying (reading) data
|
|
|
|
do not conflict with locks acquired for writing data, and so
|
2002-11-15 04:11:18 +01:00
|
|
|
reading never blocks writing and writing never blocks reading.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
2002-05-30 22:45:18 +02:00
|
|
|
|
|
|
|
<para>
|
|
|
|
Table- and row-level locking facilities are also available in
|
|
|
|
<productname>PostgreSQL</productname> for applications that cannot
|
2002-11-15 04:11:18 +01:00
|
|
|
adapt easily to <acronym>MVCC</acronym> behavior. However, proper
|
|
|
|
use of <acronym>MVCC</acronym> will generally provide better
|
|
|
|
performance than locks.
|
2002-05-30 22:45:18 +02:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</sect1>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="transaction-iso">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Transaction Isolation</title>
|
|
|
|
|
2003-08-31 19:32:24 +02:00
|
|
|
<indexterm>
|
|
|
|
<primary>transaction isolation</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2002-12-18 21:40:24 +01:00
|
|
|
The <acronym>SQL</acronym> standard defines four levels of
|
|
|
|
transaction isolation in terms of three phenomena that must be
|
|
|
|
prevented between concurrent transactions. These undesirable
|
|
|
|
phenomena are:
|
1999-05-26 19:27:39 +02:00
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-11-11 21:14:04 +01:00
|
|
|
dirty read
|
|
|
|
<indexterm><primary>dirty read</primary></indexterm>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
A transaction reads data written by a concurrent uncommitted transaction.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-11-11 21:14:04 +01:00
|
|
|
nonrepeatable read
|
|
|
|
<indexterm><primary>nonrepeatable read</primary></indexterm>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
A transaction re-reads data it has previously read and finds that data
|
2000-10-11 19:38:36 +02:00
|
|
|
has been modified by another transaction (that committed since the
|
|
|
|
initial read).
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
phantom read
|
2002-11-11 21:14:04 +01:00
|
|
|
<indexterm><primary>phantom read</primary></indexterm>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
A transaction re-executes a query returning a set of rows that satisfy a
|
2000-10-11 19:38:36 +02:00
|
|
|
search condition and finds that the set of rows satisfying the condition
|
|
|
|
has changed due to another recently-committed transaction.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
</variablelist>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
2003-08-31 19:32:24 +02:00
|
|
|
<primary>transaction isolation level</primary>
|
2001-05-13 00:51:36 +02:00
|
|
|
</indexterm>
|
2001-10-09 20:46:00 +02:00
|
|
|
The four transaction isolation levels and the corresponding
|
|
|
|
behaviors are described in <xref linkend="mvcc-isolevel-table">.
|
2002-11-11 21:14:04 +01:00
|
|
|
</para>
|
1999-05-27 17:49:08 +02:00
|
|
|
|
2001-10-09 20:46:00 +02:00
|
|
|
<table tocentry="1" id="mvcc-isolevel-table">
|
|
|
|
<title><acronym>SQL</acronym> Transaction Isolation Levels</title>
|
1999-05-27 17:49:08 +02:00
|
|
|
<tgroup cols="4">
|
|
|
|
<thead>
|
|
|
|
<row>
|
1999-07-06 19:19:42 +02:00
|
|
|
<entry>
|
2001-04-20 17:52:33 +02:00
|
|
|
Isolation Level
|
1999-07-06 19:19:42 +02:00
|
|
|
</entry>
|
1999-05-27 17:49:08 +02:00
|
|
|
<entry>
|
|
|
|
Dirty Read
|
|
|
|
</entry>
|
|
|
|
<entry>
|
2002-11-11 21:14:04 +01:00
|
|
|
Nonrepeatable Read
|
1999-05-27 17:49:08 +02:00
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Phantom Read
|
|
|
|
</entry>
|
|
|
|
</row>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<row>
|
|
|
|
<entry>
|
|
|
|
Read uncommitted
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
</row>
|
|
|
|
|
|
|
|
<row>
|
|
|
|
<entry>
|
|
|
|
Read committed
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
</row>
|
|
|
|
|
|
|
|
<row>
|
|
|
|
<entry>
|
|
|
|
Repeatable read
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Possible
|
|
|
|
</entry>
|
|
|
|
</row>
|
|
|
|
|
|
|
|
<row>
|
|
|
|
<entry>
|
|
|
|
Serializable
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Not possible
|
|
|
|
</entry>
|
|
|
|
</row>
|
|
|
|
</tbody>
|
|
|
|
</tgroup>
|
|
|
|
</table>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2000-10-11 19:38:36 +02:00
|
|
|
<para>
|
2004-12-24 00:07:38 +01:00
|
|
|
In <productname>PostgreSQL</productname>, you can request any of the
|
|
|
|
four standard transaction isolation levels. But internally, there are
|
|
|
|
only two distinct isolation levels, which correspond to the levels Read
|
2003-11-06 23:08:15 +01:00
|
|
|
Committed and Serializable. When you select the level Read
|
|
|
|
Uncommitted you really get Read Committed, and when you select
|
|
|
|
Repeatable Read you really get Serializable, so the actual
|
|
|
|
isolation level may be stricter than what you select. This is
|
|
|
|
permitted by the SQL standard: the four isolation levels only
|
|
|
|
define which phenomena must not happen, they do not define which
|
2003-12-14 00:59:07 +01:00
|
|
|
phenomena must happen. The reason that <productname>PostgreSQL</>
|
|
|
|
only provides two isolation levels is that this is the only
|
2004-12-24 00:07:38 +01:00
|
|
|
sensible way to map the standard isolation levels to the multiversion
|
2003-12-14 00:59:07 +01:00
|
|
|
concurrency control architecture. The behavior of the available
|
|
|
|
isolation levels is detailed in the following subsections.
|
2003-11-06 23:08:15 +01:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
To set the transaction isolation level of a transaction, use the
|
|
|
|
command <xref linkend="sql-set-transaction">.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
2002-11-11 21:14:04 +01:00
|
|
|
<sect2 id="xact-read-committed">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Read Committed Isolation Level</title>
|
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
2003-08-31 19:32:24 +02:00
|
|
|
<primary>transaction isolation level</primary>
|
2001-05-13 00:51:36 +02:00
|
|
|
<secondary>read committed</secondary>
|
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
1999-05-27 17:49:08 +02:00
|
|
|
<firstterm>Read Committed</firstterm>
|
2001-11-21 06:53:41 +01:00
|
|
|
is the default isolation level in <productname>PostgreSQL</productname>.
|
2000-10-11 19:38:36 +02:00
|
|
|
When a transaction runs on this isolation level,
|
|
|
|
a <command>SELECT</command> query sees only data committed before the
|
2002-05-30 22:45:18 +02:00
|
|
|
query began; it never sees either uncommitted data or changes committed
|
2001-03-28 22:46:34 +02:00
|
|
|
during query execution by concurrent transactions. (However, the
|
2000-10-11 19:38:36 +02:00
|
|
|
<command>SELECT</command> does see the effects of previous updates
|
2002-05-30 22:45:18 +02:00
|
|
|
executed within its own transaction, even though they are not yet
|
|
|
|
committed.) In effect, a <command>SELECT</command> query
|
|
|
|
sees a snapshot of the database as of the instant that that query
|
2003-03-13 02:30:29 +01:00
|
|
|
begins to run. Notice that two successive <command>SELECT</command> commands can
|
2002-05-30 22:45:18 +02:00
|
|
|
see different data, even though they are within a single transaction, if
|
|
|
|
other transactions
|
2001-03-28 22:46:34 +02:00
|
|
|
commit changes during execution of the first <command>SELECT</command>.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-11-11 21:14:04 +01:00
|
|
|
<command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT
|
2002-05-30 22:45:18 +02:00
|
|
|
FOR UPDATE</command> commands behave the same as <command>SELECT</command>
|
|
|
|
in terms of searching for target rows: they will only find target rows
|
2003-03-13 02:30:29 +01:00
|
|
|
that were committed as of the command start time. However, such a target
|
2002-05-30 22:45:18 +02:00
|
|
|
row may have already been updated (or deleted or marked for update) by
|
|
|
|
another concurrent transaction by the time it is found. In this case, the
|
|
|
|
would-be updater will wait for the first updating transaction to commit or
|
|
|
|
roll back (if it is still in progress). If the first updater rolls back,
|
|
|
|
then its effects are negated and the second updater can proceed with
|
|
|
|
updating the originally found row. If the first updater commits, the
|
|
|
|
second updater will ignore the row if the first updater deleted it,
|
|
|
|
otherwise it will attempt to apply its operation to the updated version of
|
2003-03-13 02:30:29 +01:00
|
|
|
the row. The search condition of the command (the <literal>WHERE</> clause) is
|
2002-05-30 22:45:18 +02:00
|
|
|
re-evaluated to see if the updated version of the row still matches the
|
|
|
|
search condition. If so, the second updater proceeds with its operation,
|
|
|
|
starting from the updated version of the row.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2003-03-13 02:30:29 +01:00
|
|
|
Because of the above rule, it is possible for an updating command to see an
|
|
|
|
inconsistent snapshot: it can see the effects of concurrent updating
|
|
|
|
commands that affected the same rows it is trying to update, but it
|
|
|
|
does not see effects of those commands on other rows in the database.
|
|
|
|
This behavior makes Read Committed mode unsuitable for commands that
|
2002-05-30 22:45:18 +02:00
|
|
|
involve complex search conditions. However, it is just right for simpler
|
|
|
|
cases. For example, consider updating bank balances with transactions
|
|
|
|
like
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
BEGIN;
|
|
|
|
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 12345;
|
|
|
|
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 7534;
|
|
|
|
COMMIT;
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
If two such transactions concurrently try to change the balance of account
|
|
|
|
12345, we clearly want the second transaction to start from the updated
|
2003-03-13 02:30:29 +01:00
|
|
|
version of the account's row. Because each command is affecting only a
|
2002-05-30 22:45:18 +02:00
|
|
|
predetermined row, letting it see the updated version of the row does
|
|
|
|
not create any troublesome inconsistency.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2003-03-13 02:30:29 +01:00
|
|
|
Since in Read Committed mode each new command starts with a new snapshot
|
2002-05-30 22:45:18 +02:00
|
|
|
that includes all transactions committed up to that instant, subsequent
|
2003-03-13 02:30:29 +01:00
|
|
|
commands in the same transaction will see the effects of the committed
|
2002-05-30 22:45:18 +02:00
|
|
|
concurrent transaction in any case. The point at issue here is whether
|
2003-03-13 02:30:29 +01:00
|
|
|
or not within a <emphasis>single</> command we see an absolutely consistent
|
2002-05-30 22:45:18 +02:00
|
|
|
view of the database.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The partial transaction isolation provided by Read Committed mode is
|
|
|
|
adequate for many applications, and this mode is fast and simple to use.
|
2000-10-11 19:38:36 +02:00
|
|
|
However, for applications that do complex queries and updates, it may
|
|
|
|
be necessary to guarantee a more rigorously consistent view of the
|
2002-05-30 22:45:18 +02:00
|
|
|
database than the Read Committed mode provides.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
2002-11-11 21:14:04 +01:00
|
|
|
</sect2>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2002-11-11 21:14:04 +01:00
|
|
|
<sect2 id="xact-serializable">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Serializable Isolation Level</title>
|
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
2003-08-31 19:32:24 +02:00
|
|
|
<primary>transaction isolation level</primary>
|
2003-03-13 02:30:29 +01:00
|
|
|
<secondary>serializable</secondary>
|
2001-05-13 00:51:36 +02:00
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2003-03-13 02:30:29 +01:00
|
|
|
The level <firstterm>Serializable</firstterm> provides the strictest transaction
|
2000-10-11 19:38:36 +02:00
|
|
|
isolation. This level emulates serial transaction execution,
|
|
|
|
as if transactions had been executed one after another, serially,
|
|
|
|
rather than concurrently. However, applications using this level must
|
|
|
|
be prepared to retry transactions due to serialization failures.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
1999-06-05 04:47:13 +02:00
|
|
|
When a transaction is on the serializable level,
|
2000-10-11 19:38:36 +02:00
|
|
|
a <command>SELECT</command> query sees only data committed before the
|
2002-05-30 22:45:18 +02:00
|
|
|
transaction began; it never sees either uncommitted data or changes
|
2001-03-28 22:46:34 +02:00
|
|
|
committed
|
|
|
|
during transaction execution by concurrent transactions. (However, the
|
2000-10-11 19:38:36 +02:00
|
|
|
<command>SELECT</command> does see the effects of previous updates
|
2002-05-30 22:45:18 +02:00
|
|
|
executed within its own transaction, even though they are not yet
|
2001-03-28 22:46:34 +02:00
|
|
|
committed.) This is different from Read Committed in that the
|
|
|
|
<command>SELECT</command>
|
|
|
|
sees a snapshot as of the start of the transaction, not as of the start
|
2002-11-11 21:14:04 +01:00
|
|
|
of the current query within the transaction. Thus, successive
|
2003-03-13 02:30:29 +01:00
|
|
|
<command>SELECT</command> commands within a single transaction always see the same
|
2002-05-30 22:45:18 +02:00
|
|
|
data.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-11-11 21:14:04 +01:00
|
|
|
<command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT
|
2002-05-30 22:45:18 +02:00
|
|
|
FOR UPDATE</command> commands behave the same as <command>SELECT</command>
|
|
|
|
in terms of searching for target rows: they will only find target rows
|
|
|
|
that were committed as of the transaction start time. However, such a
|
|
|
|
target
|
|
|
|
row may have already been updated (or deleted or marked for update) by
|
|
|
|
another concurrent transaction by the time it is found. In this case, the
|
|
|
|
serializable transaction will wait for the first updating transaction to commit or
|
|
|
|
roll back (if it is still in progress). If the first updater rolls back,
|
|
|
|
then its effects are negated and the serializable transaction can proceed
|
|
|
|
with updating the originally found row. But if the first updater commits
|
|
|
|
(and actually updated or deleted the row, not just selected it for update)
|
|
|
|
then the serializable transaction will be rolled back with the message
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2001-11-28 21:49:10 +01:00
|
|
|
<screen>
|
2003-09-13 00:17:24 +02:00
|
|
|
ERROR: could not serialize access due to concurrent update
|
2001-11-28 21:49:10 +01:00
|
|
|
</screen>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
|
|
|
because a serializable transaction cannot modify rows changed by
|
|
|
|
other transactions after the serializable transaction began.
|
|
|
|
</para>
|
|
|
|
|
2000-10-11 19:38:36 +02:00
|
|
|
<para>
|
|
|
|
When the application receives this error message, it should abort
|
|
|
|
the current transaction and then retry the whole transaction from
|
|
|
|
the beginning. The second time through, the transaction sees the
|
|
|
|
previously-committed change as part of its initial view of the database,
|
|
|
|
so there is no logical conflict in using the new version of the row
|
|
|
|
as the starting point for the new transaction's update.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2003-03-13 02:30:29 +01:00
|
|
|
Note that only updating transactions may need to be retried; read-only
|
2002-05-30 22:45:18 +02:00
|
|
|
transactions will never have serialization conflicts.
|
2000-10-11 19:38:36 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
The Serializable mode provides a rigorous guarantee that each
|
|
|
|
transaction sees a wholly consistent view of the database. However,
|
|
|
|
the application has to be prepared to retry transactions when concurrent
|
|
|
|
updates make it impossible to sustain the illusion of serial execution.
|
|
|
|
Since the cost of redoing complex transactions may be significant,
|
|
|
|
this mode is recommended only when updating transactions contain logic
|
|
|
|
sufficiently complex that they may give wrong answers in Read
|
|
|
|
Committed mode. Most commonly, Serializable mode is necessary when
|
2003-03-13 02:30:29 +01:00
|
|
|
a transaction executes several successive commands that must see
|
2002-05-30 22:45:18 +02:00
|
|
|
identical views of the database.
|
2000-10-11 19:38:36 +02:00
|
|
|
</para>
|
2004-08-15 00:18:23 +02:00
|
|
|
|
|
|
|
<sect3 id="mvcc-serializability">
|
|
|
|
<title>Serializable Isolation versus True Serializability</title>
|
|
|
|
|
|
|
|
<indexterm>
|
|
|
|
<primary>serializability</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
|
|
|
<indexterm>
|
|
|
|
<primary>predicate locking</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The intuitive meaning (and mathematical definition) of
|
|
|
|
<quote>serializable</> execution is that any two successfully committed
|
|
|
|
concurrent transactions will appear to have executed strictly serially,
|
2004-11-15 07:32:15 +01:00
|
|
|
one after the other — although which one appeared to occur first may
|
2004-08-15 00:18:23 +02:00
|
|
|
not be predictable in advance. It is important to realize that forbidding
|
|
|
|
the undesirable behaviors listed in <xref linkend="mvcc-isolevel-table">
|
|
|
|
is not sufficient to guarantee true serializability, and in fact
|
|
|
|
<productname>PostgreSQL</productname>'s Serializable mode <emphasis>does
|
|
|
|
not guarantee serializable execution in this sense</>. As an example,
|
|
|
|
consider a table <structname>mytab</>, initially containing
|
|
|
|
<screen>
|
|
|
|
class | value
|
|
|
|
-------+-------
|
|
|
|
1 | 10
|
|
|
|
1 | 20
|
|
|
|
2 | 100
|
|
|
|
2 | 200
|
|
|
|
</screen>
|
|
|
|
Suppose that serializable transaction A computes
|
|
|
|
<screen>
|
|
|
|
SELECT SUM(value) FROM mytab WHERE class = 1;
|
|
|
|
</screen>
|
|
|
|
and then inserts the result (30) as the <structfield>value</> in a
|
|
|
|
new row with <structfield>class</> = 2. Concurrently, serializable
|
|
|
|
transaction B computes
|
|
|
|
<screen>
|
|
|
|
SELECT SUM(value) FROM mytab WHERE class = 2;
|
|
|
|
</screen>
|
|
|
|
and obtains the result 300, which it inserts in a new row with
|
|
|
|
<structfield>class</> = 1. Then both transactions commit. None of
|
|
|
|
the listed undesirable behaviors have occurred, yet we have a result
|
|
|
|
that could not have occurred in either order serially. If A had
|
|
|
|
executed before B, B would have computed the sum 330, not 300, and
|
|
|
|
similarly the other order would have resulted in a different sum
|
|
|
|
computed by A.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
To guarantee true mathematical serializability, it is necessary for
|
|
|
|
a database system to enforce <firstterm>predicate locking</>, which
|
|
|
|
means that a transaction cannot insert or modify a row that would
|
|
|
|
have matched the <literal>WHERE</> condition of a query in another concurrent
|
|
|
|
transaction. For example, once transaction A has executed the query
|
|
|
|
<literal>SELECT ... WHERE class = 1</>, a predicate-locking system
|
|
|
|
would forbid transaction B from inserting any new row with class 1
|
|
|
|
until A has committed.
|
|
|
|
<footnote>
|
|
|
|
<para>
|
|
|
|
Essentially, a predicate-locking system prevents phantom reads
|
|
|
|
by restricting what is written, whereas MVCC prevents them by
|
|
|
|
restricting what is read.
|
|
|
|
</para>
|
|
|
|
</footnote>
|
|
|
|
Such a locking system is complex to
|
|
|
|
implement and extremely expensive in execution, since every session must
|
|
|
|
be aware of the details of every query executed by every concurrent
|
|
|
|
transaction. And this large expense is mostly wasted, since in
|
|
|
|
practice most applications do not do the sorts of things that could
|
|
|
|
result in problems. (Certainly the example above is rather contrived
|
|
|
|
and unlikely to represent real software.) Accordingly,
|
|
|
|
<productname>PostgreSQL</productname> does not implement predicate
|
|
|
|
locking, and so far as we are aware no other production DBMS does either.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
In those cases where the possibility of nonserializable execution
|
|
|
|
is a real hazard, problems can be prevented by appropriate use of
|
|
|
|
explicit locking. Further discussion appears in the following
|
|
|
|
sections.
|
|
|
|
</para>
|
|
|
|
</sect3>
|
2002-11-11 21:14:04 +01:00
|
|
|
</sect2>
|
|
|
|
</sect1>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2002-05-30 22:45:18 +02:00
|
|
|
<sect1 id="explicit-locking">
|
|
|
|
<title>Explicit Locking</title>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2001-05-13 00:51:36 +02:00
|
|
|
<indexterm>
|
2003-08-31 19:32:24 +02:00
|
|
|
<primary>lock</primary>
|
2001-05-13 00:51:36 +02:00
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
<productname>PostgreSQL</productname> provides various lock modes
|
2002-11-15 04:11:18 +01:00
|
|
|
to control concurrent access to data in tables. These modes can
|
|
|
|
be used for application-controlled locking in situations where
|
|
|
|
<acronym>MVCC</acronym> does not give the desired behavior. Also,
|
|
|
|
most <productname>PostgreSQL</productname> commands automatically
|
|
|
|
acquire locks of appropriate modes to ensure that referenced
|
|
|
|
tables are not dropped or modified in incompatible ways while the
|
|
|
|
command executes. (For example, <command>ALTER TABLE</> cannot be
|
|
|
|
executed concurrently with other operations on the same table.)
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
2003-10-18 00:38:20 +02:00
|
|
|
<para>
|
|
|
|
To examine a list of the currently outstanding locks in a database
|
|
|
|
server, use the <structname>pg_locks</structname> system view
|
|
|
|
(<xref linkend="view-pg-locks">). For more
|
|
|
|
information on monitoring the status of the lock manager
|
|
|
|
subsystem, refer to <xref linkend="monitoring">.
|
|
|
|
</para>
|
|
|
|
|
2002-05-30 22:45:18 +02:00
|
|
|
<sect2 id="locking-tables">
|
|
|
|
<title>Table-Level Locks</title>
|
|
|
|
|
2003-08-31 19:32:24 +02:00
|
|
|
<indexterm zone="locking-tables">
|
|
|
|
<primary>LOCK</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
2002-03-27 03:36:51 +01:00
|
|
|
<para>
|
|
|
|
The list below shows the available lock modes and the contexts in
|
2002-05-30 22:45:18 +02:00
|
|
|
which they are used automatically by
|
2004-08-15 00:18:23 +02:00
|
|
|
<productname>PostgreSQL</productname>. You can also acquire any
|
|
|
|
of these locks explicitly with the command <xref linkend="sql-lock">.
|
2002-05-30 22:45:18 +02:00
|
|
|
Remember that all of these lock modes are table-level locks,
|
|
|
|
even if the name contains the word
|
2003-03-13 02:30:29 +01:00
|
|
|
<quote>row</quote>; the names of the lock modes are historical.
|
2002-05-30 22:45:18 +02:00
|
|
|
To some extent the names reflect the typical usage of each lock
|
2004-11-15 07:32:15 +01:00
|
|
|
mode — but the semantics are all the same. The only real difference
|
2002-05-30 22:45:18 +02:00
|
|
|
between one lock mode and another is the set of lock modes with
|
|
|
|
which each conflicts. Two transactions cannot hold locks of conflicting
|
|
|
|
modes on the same table at the same time. (However, a transaction
|
2003-03-13 02:30:29 +01:00
|
|
|
never conflicts with itself. For example, it may acquire
|
2002-05-30 22:45:18 +02:00
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock and later acquire
|
2002-08-17 15:04:19 +02:00
|
|
|
<literal>ACCESS SHARE</literal> lock on the same table.) Non-conflicting
|
2002-05-30 22:45:18 +02:00
|
|
|
lock modes may be held concurrently by many transactions. Notice in
|
|
|
|
particular that some lock modes are self-conflicting (for example,
|
2003-03-13 02:30:29 +01:00
|
|
|
an <literal>ACCESS EXCLUSIVE</literal> lock cannot be held by more than one
|
2002-05-30 22:45:18 +02:00
|
|
|
transaction at a time) while others are not self-conflicting (for example,
|
2003-03-13 02:30:29 +01:00
|
|
|
an <literal>ACCESS SHARE</literal> lock can be held by multiple transactions).
|
|
|
|
Once acquired, a lock is held till end of transaction.
|
2002-03-27 03:36:51 +01:00
|
|
|
</para>
|
2002-08-17 15:04:19 +02:00
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<variablelist>
|
2002-03-27 03:36:51 +01:00
|
|
|
<title>Table-level lock modes</title>
|
1999-05-26 19:27:39 +02:00
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>ACCESS SHARE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
Conflicts with the <literal>ACCESS EXCLUSIVE</literal> lock
|
|
|
|
mode only.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2003-02-19 05:06:28 +01:00
|
|
|
The commands <command>SELECT</command> and
|
|
|
|
<command>ANALYZE</command> acquire 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.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>ROW SHARE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
Conflicts with the <literal>EXCLUSIVE</literal> and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
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>).
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>ROW EXCLUSIVE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Conflicts with the <literal>SHARE</literal>, <literal>SHARE ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
2002-05-30 22:45:18 +02:00
|
|
|
|
|
|
|
<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
|
2003-03-13 02:30:29 +01:00
|
|
|
command that modifies the data in a table.
|
2002-05-30 22:45:18 +02:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
2001-07-10 00:18:34 +02:00
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>SHARE UPDATE EXCLUSIVE</literal>
|
2001-07-10 00:18:34 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Conflicts with the <literal>SHARE UPDATE EXCLUSIVE</literal>,
|
|
|
|
<literal>SHARE</literal>, <literal>SHARE ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
2002-05-30 22:45:18 +02:00
|
|
|
This mode protects a table against
|
2002-09-21 20:32:54 +02:00
|
|
|
concurrent schema changes and <command>VACUUM</> runs.
|
2002-05-30 22:45:18 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Acquired by <command>VACUUM</command> (without <option>FULL</option>).
|
2001-07-10 00:18:34 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>SHARE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Conflicts with the <literal>ROW EXCLUSIVE</literal>,
|
|
|
|
<literal>SHARE UPDATE EXCLUSIVE</literal>, <literal>SHARE ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
2002-05-30 22:45:18 +02:00
|
|
|
This mode protects a table against concurrent data changes.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Acquired by <command>CREATE INDEX</command>.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>SHARE ROW EXCLUSIVE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Conflicts with the <literal>ROW EXCLUSIVE</literal>,
|
|
|
|
<literal>SHARE UPDATE EXCLUSIVE</literal>,
|
|
|
|
<literal>SHARE</literal>, <literal>SHARE ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
2002-05-30 22:45:18 +02:00
|
|
|
|
|
|
|
<para>
|
|
|
|
This lock mode is not automatically acquired by any
|
|
|
|
<productname>PostgreSQL</productname> command.
|
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-05-30 22:45:18 +02:00
|
|
|
<literal>EXCLUSIVE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Conflicts with the <literal>ROW SHARE</literal>, <literal>ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>SHARE UPDATE
|
|
|
|
EXCLUSIVE</literal>, <literal>SHARE</literal>, <literal>SHARE
|
|
|
|
ROW EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal> lock modes.
|
2003-03-13 02:30:29 +01:00
|
|
|
This mode allows only concurrent <literal>ACCESS SHARE</literal> locks,
|
2002-05-30 22:45:18 +02:00
|
|
|
i.e., only reads from the table can proceed in parallel with a
|
|
|
|
transaction holding this lock mode.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
This lock mode is not automatically acquired by any
|
|
|
|
<productname>PostgreSQL</productname> command.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-03-27 03:36:51 +01:00
|
|
|
<literal>ACCESS EXCLUSIVE</literal>
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
Conflicts with locks of all modes (<literal>ACCESS
|
2002-03-27 03:36:51 +01:00
|
|
|
SHARE</literal>, <literal>ROW SHARE</literal>, <literal>ROW
|
|
|
|
EXCLUSIVE</literal>, <literal>SHARE UPDATE
|
|
|
|
EXCLUSIVE</literal>, <literal>SHARE</literal>, <literal>SHARE
|
|
|
|
ROW EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
|
|
|
|
<literal>ACCESS EXCLUSIVE</literal>).
|
2002-05-30 22:45:18 +02:00
|
|
|
This mode guarantees that the
|
|
|
|
holder is the only transaction accessing the table in any way.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Acquired by the <command>ALTER TABLE</command>, <command>DROP
|
2003-02-19 05:06:28 +01:00
|
|
|
TABLE</command>, <command>REINDEX</command>,
|
|
|
|
<command>CLUSTER</command>, and <command>VACUUM FULL</command>
|
|
|
|
commands. This is also the default lock mode for <command>LOCK
|
|
|
|
TABLE</command> statements that do not specify a mode explicitly.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
</variablelist>
|
2000-10-11 20:29:52 +02:00
|
|
|
|
2003-03-13 02:30:29 +01:00
|
|
|
<tip>
|
2000-10-11 20:29:52 +02:00
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
Only an <literal>ACCESS EXCLUSIVE</literal> lock blocks a
|
|
|
|
<command>SELECT</command> (without <option>FOR UPDATE</option>)
|
|
|
|
statement.
|
2000-10-11 20:29:52 +02:00
|
|
|
</para>
|
2003-03-13 02:30:29 +01:00
|
|
|
</tip>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2002-05-30 22:45:18 +02:00
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2 id="locking-rows">
|
|
|
|
<title>Row-Level Locks</title>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
In addition to table-level locks, there are row-level locks.
|
2002-05-30 22:45:18 +02:00
|
|
|
A row-level lock on a specific row is automatically acquired when the
|
|
|
|
row is updated (or deleted or marked for update). The lock is held
|
|
|
|
until the transaction commits or rolls back.
|
2003-02-19 05:06:28 +01:00
|
|
|
Row-level locks do not affect data
|
2002-05-30 22:45:18 +02:00
|
|
|
querying; they block <emphasis>writers to the same row</emphasis>
|
|
|
|
only. To acquire a row-level lock on a row without actually
|
|
|
|
modifying the row, select the row with <command>SELECT FOR
|
|
|
|
UPDATE</command>. Note that once a particular row-level lock is
|
|
|
|
acquired, the transaction may update the row multiple times without
|
|
|
|
fear of conflicts.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-03-27 03:36:51 +01:00
|
|
|
<productname>PostgreSQL</productname> doesn't remember any
|
2002-05-30 22:45:18 +02:00
|
|
|
information about modified rows in memory, so it has no limit to
|
2002-03-27 03:36:51 +01:00
|
|
|
the number of rows locked at one time. However, locking a row
|
|
|
|
may cause a disk write; thus, for example, <command>SELECT FOR
|
|
|
|
UPDATE</command> will modify selected rows to mark them and so
|
|
|
|
will result in disk writes.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-05-30 22:45:18 +02:00
|
|
|
In addition to table and row locks, page-level share/exclusive locks are
|
|
|
|
used to control read/write access to table pages in the shared buffer
|
2003-03-13 02:30:29 +01:00
|
|
|
pool. These locks are released immediately after a row is fetched or
|
2002-12-18 21:40:24 +01:00
|
|
|
updated. Application developers normally need not be concerned with
|
2002-05-30 22:45:18 +02:00
|
|
|
page-level locks, but we mention them for completeness.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2 id="locking-deadlocks">
|
|
|
|
<title>Deadlocks</title>
|
|
|
|
|
2003-08-31 19:32:24 +02:00
|
|
|
<indexterm zone="locking-deadlocks">
|
|
|
|
<primary>deadlock</primary>
|
|
|
|
</indexterm>
|
|
|
|
|
2002-05-30 22:45:18 +02:00
|
|
|
<para>
|
2003-09-20 22:12:05 +02:00
|
|
|
The use of explicit locking can increase the likelihood of
|
2002-12-18 21:40:24 +01:00
|
|
|
<firstterm>deadlocks</>, wherein two (or more) transactions each
|
|
|
|
hold locks that the other wants. For example, if transaction 1
|
|
|
|
acquires an exclusive lock on table A and then tries to acquire
|
|
|
|
an exclusive lock on table B, while transaction 2 has already
|
|
|
|
exclusive-locked table B and now wants an exclusive lock on table
|
|
|
|
A, then neither one can proceed.
|
|
|
|
<productname>PostgreSQL</productname> automatically detects
|
|
|
|
deadlock situations and resolves them by aborting one of the
|
|
|
|
transactions involved, allowing the other(s) to complete.
|
|
|
|
(Exactly which transaction will be aborted is difficult to
|
|
|
|
predict and should not be relied on.)
|
2002-05-30 22:45:18 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-12-18 21:40:24 +01:00
|
|
|
Note that deadlocks can also occur as the result of row-level
|
|
|
|
locks (and thus, they can occur even if explicit locking is not
|
|
|
|
used). Consider the case in which there are two concurrent
|
|
|
|
transactions modifying a table. The first transaction executes:
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 11111;
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
This acquires a row-level lock on the row with the specified
|
|
|
|
account number. Then, the second transaction executes:
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
|
|
|
|
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
The first <command>UPDATE</command> statement successfully
|
|
|
|
acquires a row-level lock on the specified row, so it succeeds in
|
|
|
|
updating that row. However, the second <command>UPDATE</command>
|
|
|
|
statement finds that the row it is attempting to update has
|
|
|
|
already been locked, so it waits for the transaction that
|
|
|
|
acquired the lock to complete. Transaction two is now waiting on
|
|
|
|
transaction one to complete before it continues execution. Now,
|
|
|
|
transaction one executes:
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
Transaction one attempts to acquire a row-level lock on the
|
|
|
|
specified row, but it cannot: transaction two already holds such
|
|
|
|
a lock. So it waits for transaction two to complete. Thus,
|
|
|
|
transaction one is blocked on transaction two, and transaction
|
|
|
|
two is blocked on transaction one: a deadlock
|
|
|
|
condition. <productname>PostgreSQL</productname> will detect this
|
|
|
|
situation and abort one of the transactions.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The best defense against deadlocks is generally to avoid them by
|
|
|
|
being certain that all applications using a database acquire
|
2004-08-15 00:18:23 +02:00
|
|
|
locks on multiple objects in a consistent order. In the example
|
|
|
|
above, if both transactions
|
2002-12-18 21:40:24 +01:00
|
|
|
had updated the rows in the same order, no deadlock would have
|
|
|
|
occurred. One should also ensure that the first lock acquired on
|
|
|
|
an object in a transaction is the highest mode that will be
|
|
|
|
needed for that object. If it is not feasible to verify this in
|
|
|
|
advance, then deadlocks may be handled on-the-fly by retrying
|
2002-05-30 22:45:18 +02:00
|
|
|
transactions that are aborted due to deadlock.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
So long as no deadlock situation is detected, a transaction seeking
|
|
|
|
either a table-level or row-level lock will wait indefinitely for
|
|
|
|
conflicting locks to be released. This means it is a bad idea for
|
|
|
|
applications to hold transactions open for long periods of time
|
|
|
|
(e.g., while waiting for user input).
|
|
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<sect1 id="applevel-consistency">
|
2002-11-11 21:14:04 +01:00
|
|
|
<title>Data Consistency Checks at the Application Level</title>
|
2002-05-30 22:45:18 +02:00
|
|
|
|
|
|
|
<para>
|
|
|
|
Because readers in <productname>PostgreSQL</productname>
|
2003-02-19 05:06:28 +01:00
|
|
|
do not lock data, regardless of
|
2002-05-30 22:45:18 +02:00
|
|
|
transaction isolation level, data read by one transaction can be
|
|
|
|
overwritten by another concurrent transaction. In other words,
|
|
|
|
if a row is returned by <command>SELECT</command> it doesn't mean that
|
|
|
|
the row is still current at the instant it is returned (i.e., sometime
|
|
|
|
after the current query began). The row might have been modified or
|
|
|
|
deleted by an already-committed transaction that committed after this one
|
|
|
|
started.
|
|
|
|
Even if the row is still valid <quote>now</quote>, it could be changed or
|
|
|
|
deleted
|
|
|
|
before the current transaction does a commit or rollback.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Another way to think about it is that each
|
|
|
|
transaction sees a snapshot of the database contents, and concurrently
|
|
|
|
executing transactions may very well see different snapshots. So the
|
2004-08-15 00:18:23 +02:00
|
|
|
whole concept of <quote>now</quote> is somewhat ill-defined anyway.
|
2002-05-30 22:45:18 +02:00
|
|
|
This is not normally
|
|
|
|
a big problem if the client applications are isolated from each other,
|
|
|
|
but if the clients can communicate via channels outside the database
|
|
|
|
then serious confusion may ensue.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
To ensure the current validity of a row and protect it against
|
2003-11-04 10:55:39 +01:00
|
|
|
concurrent updates one must use <command>SELECT FOR
|
|
|
|
UPDATE</command> or an appropriate <command>LOCK TABLE</command>
|
|
|
|
statement. (<command>SELECT FOR UPDATE</command> locks just the
|
|
|
|
returned rows against concurrent updates, while <command>LOCK
|
|
|
|
TABLE</command> locks the whole table.) This should be taken into
|
|
|
|
account when porting applications to
|
2002-05-30 22:45:18 +02:00
|
|
|
<productname>PostgreSQL</productname> from other environments.
|
2003-11-04 10:55:39 +01:00
|
|
|
(Before version 6.5 <productname>PostgreSQL</productname> used
|
|
|
|
read locks, and so this above consideration is also relevant when
|
|
|
|
upgrading from <productname>PostgreSQL</productname> versions
|
|
|
|
prior to 6.5.)
|
2002-05-30 22:45:18 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2004-08-15 00:18:23 +02:00
|
|
|
Global validity checks require extra thought under <acronym>MVCC</acronym>.
|
|
|
|
For example, a banking application might wish to check that the sum of
|
2002-05-30 22:45:18 +02:00
|
|
|
all credits in one table equals the sum of debits in another table,
|
|
|
|
when both tables are being actively updated. Comparing the results of two
|
2003-03-13 02:30:29 +01:00
|
|
|
successive <literal>SELECT sum(...)</literal> commands will not work reliably under
|
2002-05-30 22:45:18 +02:00
|
|
|
Read Committed mode, since the second query will likely include the results
|
|
|
|
of transactions not counted by the first. Doing the two sums in a
|
|
|
|
single serializable transaction will give an accurate picture of the
|
|
|
|
effects of transactions that committed before the serializable transaction
|
2004-11-15 07:32:15 +01:00
|
|
|
started — but one might legitimately wonder whether the answer is still
|
2002-05-30 22:45:18 +02:00
|
|
|
relevant by the time it is delivered. If the serializable transaction
|
|
|
|
itself applied some changes before trying to make the consistency check,
|
|
|
|
the usefulness of the check becomes even more debatable, since now it
|
|
|
|
includes some but not all post-transaction-start changes. In such cases
|
|
|
|
a careful person might wish to lock all tables needed for the check,
|
|
|
|
in order to get an indisputable picture of current reality. A
|
|
|
|
<literal>SHARE</> mode (or higher) lock guarantees that there are no
|
|
|
|
uncommitted changes in the locked table, other than those of the current
|
|
|
|
transaction.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Note also that if one is
|
2004-08-15 00:18:23 +02:00
|
|
|
relying on explicit locking to prevent concurrent changes, one should use
|
2002-05-30 22:45:18 +02:00
|
|
|
Read Committed mode, or in Serializable mode be careful to obtain the
|
2004-08-15 00:18:23 +02:00
|
|
|
lock(s) before performing queries. A lock obtained by a
|
2002-05-30 22:45:18 +02:00
|
|
|
serializable transaction guarantees that no other transactions modifying
|
2003-03-13 02:30:29 +01:00
|
|
|
the table are still running, but if the snapshot seen by the
|
2002-05-30 22:45:18 +02:00
|
|
|
transaction predates obtaining the lock, it may predate some now-committed
|
|
|
|
changes in the table. A serializable transaction's snapshot is actually
|
2003-03-13 02:30:29 +01:00
|
|
|
frozen at the start of its first query or data-modification command
|
|
|
|
(<literal>SELECT</>, <literal>INSERT</>,
|
2002-11-11 21:14:04 +01:00
|
|
|
<literal>UPDATE</>, or <literal>DELETE</>), so
|
2004-08-15 00:18:23 +02:00
|
|
|
it's possible to obtain locks explicitly before the snapshot is
|
2002-05-30 22:45:18 +02:00
|
|
|
frozen.
|
2000-10-11 19:38:36 +02:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</sect1>
|
|
|
|
|
2001-05-17 23:50:18 +02:00
|
|
|
<sect1 id="locking-indexes">
|
|
|
|
<title>Locking and Indexes</title>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2003-08-31 19:32:24 +02:00
|
|
|
<indexterm zone="locking-indexes">
|
|
|
|
<primary>index</primary>
|
|
|
|
<secondary>locks</secondary>
|
|
|
|
</indexterm>
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<para>
|
2001-11-21 06:53:41 +01:00
|
|
|
Though <productname>PostgreSQL</productname>
|
2000-10-11 19:38:36 +02:00
|
|
|
provides nonblocking read/write access to table
|
|
|
|
data, nonblocking read/write access is not currently offered for every
|
|
|
|
index access method implemented
|
2001-11-21 06:53:41 +01:00
|
|
|
in <productname>PostgreSQL</productname>.
|
1999-05-26 19:27:39 +02:00
|
|
|
The various index types are handled as follows:
|
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-11-11 21:14:04 +01:00
|
|
|
B-tree indexes
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-11-11 21:14:04 +01:00
|
|
|
Short-term share/exclusive page-level locks are used for
|
|
|
|
read/write access. Locks are released immediately after each
|
2003-03-13 02:30:29 +01:00
|
|
|
index row is fetched or inserted. B-tree indexes provide
|
2002-11-11 21:14:04 +01:00
|
|
|
the highest concurrency without deadlock conditions.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-11-11 21:14:04 +01:00
|
|
|
<acronym>GiST</acronym> and R-tree indexes
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2002-11-11 21:14:04 +01:00
|
|
|
Share/exclusive index-level locks are used for read/write access.
|
2003-03-13 02:30:29 +01:00
|
|
|
Locks are released after the command is done.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2002-11-11 21:14:04 +01:00
|
|
|
Hash indexes
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2004-08-15 00:18:23 +02:00
|
|
|
Share/exclusive hash-bucket-level locks are used for read/write
|
|
|
|
access. Locks are released after the whole bucket is processed.
|
|
|
|
Bucket-level locks provide better concurrency than index-level
|
|
|
|
ones, but deadlock is possible since the locks are held longer
|
|
|
|
than one index operation.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
</variablelist>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-12-18 21:40:24 +01:00
|
|
|
In short, B-tree indexes offer the best performance for concurrent
|
|
|
|
applications; since they also have more features than hash
|
|
|
|
indexes, they are the recommended index type for concurrent
|
|
|
|
applications that need to index scalar data. When dealing with
|
|
|
|
non-scalar data, B-trees obviously cannot be used; in that
|
|
|
|
situation, application developers should be aware of the
|
|
|
|
relatively poor concurrent performance of GiST and R-tree
|
|
|
|
indexes.
|
2003-01-11 01:00:03 +01:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
|
|
Local variables:
|
2000-03-31 05:27:42 +02:00
|
|
|
mode:sgml
|
1999-05-26 19:27:39 +02:00
|
|
|
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
|
2000-03-31 05:27:42 +02:00
|
|
|
sgml-local-catalogs:("/usr/lib/sgml/catalog")
|
1999-05-26 19:27:39 +02:00
|
|
|
sgml-local-ecat-files:nil
|
|
|
|
End:
|
|
|
|
-->
|