2000-03-31 05:27:42 +02:00
|
|
|
<!--
|
2001-03-28 22:46:34 +02:00
|
|
|
$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.12 2001/03/28 20:46:34 tgl Exp $
|
2000-03-31 05:27:42 +02:00
|
|
|
-->
|
|
|
|
|
1999-05-26 19:27:39 +02:00
|
|
|
<chapter id="mvcc">
|
|
|
|
<title>Multi-Version Concurrency Control</title>
|
|
|
|
|
|
|
|
<abstract>
|
|
|
|
<para>
|
|
|
|
Multi-Version Concurrency Control
|
|
|
|
(MVCC)
|
|
|
|
is an advanced technique for improving database performance in a
|
|
|
|
multi-user environment.
|
2000-12-22 22:51:58 +01:00
|
|
|
Vadim Mikheev (<email>vadim@krs.ru</email>) provided
|
1999-05-26 19:27:39 +02:00
|
|
|
the implementation for <productname>Postgres</productname>.
|
|
|
|
</para>
|
|
|
|
</abstract>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="mvcc-intro">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Introduction</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Unlike most other database systems which use locks for concurrency control,
|
|
|
|
<productname>Postgres</productname>
|
|
|
|
maintains data consistency by using a multiversion model.
|
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>
|
|
|
|
The main difference between multiversion and lock models is that
|
|
|
|
in MVCC locks acquired for querying (reading) data don't conflict
|
|
|
|
with locks acquired for writing data and so reading never blocks
|
|
|
|
writing and writing never blocks reading.
|
|
|
|
</para>
|
|
|
|
</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>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The <acronym>ANSI</acronym>/<acronym>ISO</acronym> <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:
|
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
dirty reads
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
A transaction reads data written by concurrent uncommitted transaction.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
non-repeatable reads
|
|
|
|
</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
|
|
|
|
</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>
|
1999-05-27 17:49:08 +02:00
|
|
|
The four isolation levels and the corresponding behaviors are described below.
|
|
|
|
|
|
|
|
<table tocentry="1">
|
2001-03-28 22:46:34 +02:00
|
|
|
<title><acronym>ANSI</acronym>/<acronym>ISO</acronym> <acronym>SQL</acronym> Isolation Levels</title>
|
1999-05-27 17:49:08 +02:00
|
|
|
<titleabbrev>Isolation Levels</titleabbrev>
|
|
|
|
<tgroup cols="4">
|
|
|
|
<thead>
|
|
|
|
<row>
|
1999-07-06 19:19:42 +02:00
|
|
|
<entry>
|
|
|
|
</entry>
|
1999-05-27 17:49:08 +02:00
|
|
|
<entry>
|
|
|
|
Dirty Read
|
|
|
|
</entry>
|
|
|
|
<entry>
|
|
|
|
Non-Repeatable Read
|
|
|
|
</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>
|
2000-10-11 19:38:36 +02:00
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
|
2000-10-11 19:38:36 +02:00
|
|
|
<para>
|
1999-05-26 19:27:39 +02:00
|
|
|
<productname>Postgres</productname>
|
|
|
|
offers the read committed and serializable isolation levels.
|
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="xact-read-committed">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Read Committed Isolation Level</title>
|
|
|
|
|
|
|
|
<para>
|
1999-05-27 17:49:08 +02:00
|
|
|
<firstterm>Read Committed</firstterm>
|
|
|
|
is the default isolation level in <productname>Postgres</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
|
2001-03-28 22:46:34 +02:00
|
|
|
query began and never sees either uncommitted data or changes committed
|
|
|
|
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
|
2001-03-28 22:46:34 +02:00
|
|
|
executed within this same transaction, even though they are not yet
|
|
|
|
committed.) Notice that two successive <command>SELECT</command>s can see different data,
|
|
|
|
even though they are within a single transaction, when other transactions
|
|
|
|
commit changes during execution of the first <command>SELECT</command>.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
If a target row found by a query while executing an
|
1999-05-26 19:27:39 +02:00
|
|
|
<command>UPDATE</command> statement
|
2000-10-11 19:38:36 +02:00
|
|
|
(or <command>DELETE</command> or <command>SELECT FOR UPDATE</command>)
|
|
|
|
has already been updated by a
|
1999-05-26 19:27:39 +02:00
|
|
|
concurrent uncommitted transaction then the second transaction
|
|
|
|
that tries to update this row will wait for the other transaction to
|
|
|
|
commit or rollback. In the case of rollback, the waiting transaction
|
|
|
|
can proceed to change the row. In the case of commit (and if the
|
|
|
|
row still exists; i.e. was not deleted by the other transaction), the
|
2000-10-11 19:38:36 +02:00
|
|
|
query will be re-executed for this row to check that the new row
|
|
|
|
version still satisfies the query search condition. If the new row version
|
|
|
|
satisfies the query search condition then the row will be
|
|
|
|
updated (or deleted or marked for update). Note that the starting point
|
|
|
|
for the update will be the new row version; moreover, after the update
|
|
|
|
the doubly-updated row is visible to subsequent <command>SELECT</command>s
|
|
|
|
in the current transaction. Thus, the current transaction is able to see
|
|
|
|
the effects of the other transaction for this specific row.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
The partial transaction isolation provided by Read Committed level is
|
|
|
|
adequate for many applications, and this level is fast and simple to use.
|
|
|
|
However, for applications that do complex queries and updates, it may
|
|
|
|
be necessary to guarantee a more rigorously consistent view of the
|
|
|
|
database than Read Committed level provides.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="xact-serializable">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Serializable Isolation Level</title>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
<firstterm>Serializable</firstterm> provides the highest transaction
|
|
|
|
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
|
2001-03-28 22:46:34 +02:00
|
|
|
transaction began and never sees either uncommitted data or changes
|
|
|
|
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
|
2001-03-28 22:46:34 +02:00
|
|
|
executed within this same transaction, even though they are not yet
|
|
|
|
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
|
|
|
|
of the current query within the transaction.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
If a target row found by a query while executing an
|
|
|
|
<command>UPDATE</command> statement
|
1999-05-27 17:49:08 +02:00
|
|
|
(or <command>DELETE</command> or <command>SELECT FOR UPDATE</command>)
|
2000-10-11 19:38:36 +02:00
|
|
|
has already been updated by a
|
|
|
|
concurrent uncommitted transaction then the second transaction
|
1999-05-26 19:27:39 +02:00
|
|
|
that tries to update this row will wait for the other transaction to
|
|
|
|
commit or rollback. In the case of rollback, the waiting transaction
|
|
|
|
can proceed to change the row. In the case of a concurrent
|
|
|
|
transaction commit, a serializable transaction will be rolled back
|
|
|
|
with the message
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
ERROR: Can't serialize access due to concurrent update
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
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.
|
|
|
|
Note that only updating transactions may need to be retried --- read-only
|
|
|
|
transactions never have serialization conflicts.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Serializable transaction level 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,
|
|
|
|
and the cost of redoing complex transactions may be significant. So
|
|
|
|
this level is recommended only when update queries contain logic
|
2001-03-28 22:46:34 +02:00
|
|
|
sufficiently complex that they may give wrong answers in Read Committed
|
2000-10-11 19:38:36 +02:00
|
|
|
level.
|
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<sect1 id="applevel-consistency">
|
|
|
|
<title>Data consistency checks at the application level</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Because readers in <productname>Postgres</productname>
|
|
|
|
don't lock data, regardless of
|
|
|
|
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 still exists at the time it is returned (i.e. sometime after the
|
|
|
|
current transaction 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 "now", 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
|
|
|
|
whole concept of "now" is somewhat suspect anyway. 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 existence of a row and protect it against
|
|
|
|
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> protects the
|
|
|
|
whole table.)
|
|
|
|
This should be taken into account when porting applications to
|
|
|
|
<productname>Postgres</productname> from other environments.
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
Before version 6.5 <productname>Postgres</productname>
|
|
|
|
used read-locks and so the
|
|
|
|
above consideration is also the case
|
|
|
|
when upgrading to 6.5 (or higher) from previous
|
|
|
|
<productname>Postgres</productname> versions.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</sect1>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="locking-tables">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Locking and Tables</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<productname>Postgres</productname>
|
|
|
|
provides various lock modes to control concurrent
|
|
|
|
access to data in tables. Some of these lock modes are acquired by
|
|
|
|
<productname>Postgres</productname>
|
|
|
|
automatically before statement execution, while others are
|
2000-10-11 19:38:36 +02:00
|
|
|
provided to be used by applications. All lock modes acquired in a
|
|
|
|
transaction are held for the duration
|
1999-05-26 19:27:39 +02:00
|
|
|
of the transaction.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Table-level locks</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<variablelist>
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
AccessShareLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
A read-lock mode acquired automatically on tables
|
|
|
|
being queried.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with AccessExclusiveLock only.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
RowShareLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>SELECT FOR UPDATE</command>
|
|
|
|
and <command>LOCK TABLE</command>
|
|
|
|
for <option>IN ROW SHARE MODE</option> statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with ExclusiveLock and AccessExclusiveLock modes.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
RowExclusiveLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>UPDATE</command>, <command>DELETE</command>,
|
|
|
|
<command>INSERT</command> and <command>LOCK TABLE</command>
|
|
|
|
for <option>IN ROW EXCLUSIVE MODE</option> statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with ShareLock, ShareRowExclusiveLock, ExclusiveLock and
|
|
|
|
AccessExclusiveLock modes.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
ShareLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>CREATE INDEX</command>
|
|
|
|
and <command>LOCK TABLE</command> table
|
|
|
|
for <option>IN SHARE MODE</option>
|
|
|
|
statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with RowExclusiveLock, ShareRowExclusiveLock,
|
|
|
|
ExclusiveLock and AccessExclusiveLock modes.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
ShareRowExclusiveLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>LOCK TABLE</command> for
|
|
|
|
<option>IN SHARE ROW EXCLUSIVE MODE</option> statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with RowExclusiveLock, ShareLock, ShareRowExclusiveLock,
|
|
|
|
ExclusiveLock and AccessExclusiveLock modes.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
ExclusiveLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>LOCK TABLE</command> table
|
|
|
|
for <option>IN EXCLUSIVE MODE</option> statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Conflicts with RowShareLock, RowExclusiveLock, ShareLock,
|
|
|
|
ShareRowExclusiveLock, ExclusiveLock and AccessExclusiveLock
|
|
|
|
modes.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
AccessExclusiveLock
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Acquired by <command>ALTER TABLE</command>,
|
|
|
|
<command>DROP TABLE</command>,
|
|
|
|
<command>VACUUM</command> and <command>LOCK TABLE</command>
|
|
|
|
statements.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 20:29:52 +02:00
|
|
|
Conflicts with all modes (AccessShareLock, RowShareLock,
|
|
|
|
RowExclusiveLock, ShareLock,
|
|
|
|
ShareRowExclusiveLock, ExclusiveLock and AccessExclusiveLock).
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
</variablelist>
|
2000-10-11 20:29:52 +02:00
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
Only AccessExclusiveLock blocks <command>SELECT</command> (without
|
|
|
|
<option>FOR UPDATE</option>) statement.
|
|
|
|
</para>
|
|
|
|
</note>
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2>
|
|
|
|
<title>Row-level locks</title>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
These locks are acquired when rows are being updated (or deleted or
|
|
|
|
marked for update).
|
|
|
|
Row-level locks don't affect data querying. They block
|
|
|
|
writers to <emphasis>the same row</emphasis> only.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
<productname>Postgres</productname>
|
|
|
|
doesn't remember any information about modified rows in memory and
|
|
|
|
so has no limit to 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>
|
2000-10-11 19:38:36 +02:00
|
|
|
In addition to table and row locks, short-term share/exclusive locks are
|
|
|
|
used to control read/write access to table pages in the shared buffer
|
|
|
|
pool. These locks are released immediately after a tuple is fetched or
|
|
|
|
updated. Application writers normally need not be concerned with
|
|
|
|
page-level locks, but we mention them for completeness.
|
|
|
|
</para>
|
1999-05-26 19:27:39 +02:00
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
2000-09-29 22:21:34 +02:00
|
|
|
<sect1 id="locking-indices">
|
1999-05-26 19:27:39 +02:00
|
|
|
<title>Locking and Indices</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Though <productname>Postgres</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
|
1999-05-26 19:27:39 +02:00
|
|
|
in <productname>Postgres</productname>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The various index types are handled as follows:
|
|
|
|
|
|
|
|
<variablelist>
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
GiST and R-Tree indices
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
1999-05-27 17:49:08 +02:00
|
|
|
Share/exclusive index-level locks are used for read/write access.
|
1999-05-26 19:27:39 +02:00
|
|
|
Locks are released after statement is done.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
|
|
|
Hash indices
|
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
1999-05-27 17:49:08 +02:00
|
|
|
Share/exclusive page-level locks are used for read/write access.
|
1999-05-26 19:27:39 +02:00
|
|
|
Locks are released after page is processed.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
Page-level locks provide better concurrency than index-level ones
|
1999-05-26 19:27:39 +02:00
|
|
|
but are subject to deadlocks.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
<varlistentry>
|
|
|
|
<term>
|
2000-10-11 19:38:36 +02:00
|
|
|
Btree indices
|
1999-05-26 19:27:39 +02:00
|
|
|
</term>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
Short-term share/exclusive page-level locks are used for
|
|
|
|
read/write access. Locks are released immediately after each index
|
|
|
|
tuple is fetched/inserted.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
1999-05-27 17:49:08 +02:00
|
|
|
Btree indices provide the highest concurrency without deadlock
|
1999-05-26 19:27:39 +02:00
|
|
|
conditions.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
</variablelist>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2000-10-11 19:38:36 +02:00
|
|
|
In short, btree indices are the recommended index type for concurrent
|
|
|
|
applications.
|
1999-05-26 19:27:39 +02:00
|
|
|
</para>
|
|
|
|
</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:
|
|
|
|
-->
|