Update read committed documentation to better explain undesirable

behavior of concurrent commands in cases where rows are being added and
removed from matching query criteria.

Minor word-smithing.
This commit is contained in:
Bruce Momjian 2009-02-04 16:05:50 +00:00
parent 649a1252b7
commit d8a30eca2e
1 changed files with 57 additions and 32 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.69 2007/02/18 01:21:49 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.70 2009/02/04 16:05:50 momjian Exp $ -->
<chapter id="mvcc"> <chapter id="mvcc">
<title>Concurrency Control</title> <title>Concurrency Control</title>
@ -239,19 +239,19 @@
</indexterm> </indexterm>
<para> <para>
<firstterm>Read Committed</firstterm> <firstterm>Read Committed</firstterm> is the default isolation
is the default isolation level in <productname>PostgreSQL</productname>. level in <productname>PostgreSQL</productname>. When a transaction
When a transaction runs on this isolation level, uses this isolation level, a <command>SELECT</command> query
a <command>SELECT</command> query sees only data committed before the (without a <literal>FOR UPDATE/SHARE</> clause) sees only data
query began; it never sees either uncommitted data or changes committed committed before the query began; it never sees either uncommitted
during query execution by concurrent transactions. (However, the data or changes committed during query execution by concurrent
<command>SELECT</command> does see the effects of previous updates transactions. In effect, a <command>SELECT</command> query sees
executed within its own transaction, even though they are not yet a snapshot of the database as of the instant the query begins to
committed.) In effect, a <command>SELECT</command> query run. However, <command>SELECT</command> does see the effects
sees a snapshot of the database as of the instant that that query of previous updates executed within its own transaction, even
begins to run. Notice that two successive <command>SELECT</command> commands can though they are not yet committed. Also note that two successive
see different data, even though they are within a single transaction, if <command>SELECT</command> commands can see different data, even
other transactions though they are within a single transaction, if other transactions
commit changes during execution of the first <command>SELECT</command>. commit changes during execution of the first <command>SELECT</command>.
</para> </para>
@ -271,22 +271,22 @@
otherwise it will attempt to apply its operation to the updated version of otherwise it will attempt to apply its operation to the updated version of
the row. The search condition of the command (the <literal>WHERE</> clause) is the row. The search condition of the command (the <literal>WHERE</> clause) is
re-evaluated to see if the updated version of the row still matches the 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, search condition. If so, the second updater proceeds with its operation
starting from the updated version of the row. (In the case of using the updated version of the row. In the case of
<command>SELECT FOR UPDATE</command> and <command>SELECT FOR <command>SELECT FOR UPDATE</command> and <command>SELECT FOR
SHARE</command>, that means it is the updated version of the row that is SHARE</command>, this means it is the updated version of the row that is
locked and returned to the client.) locked and returned to the client.
</para> </para>
<para> <para>
Because of the above rule, it is possible for an updating command to see an 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 inconsistent snapshot: it can see the effects of concurrent updating
commands that affected the same rows it is trying to update, but it commands on the same rows it is trying to update, but it
does not see effects of those commands on other rows in the database. does not see effects of those commands on other rows in the database.
This behavior makes Read Committed mode unsuitable for commands that This behavior makes Read Committed mode unsuitable for commands that
involve complex search conditions. However, it is just right for simpler involve complex search conditions; however, it is just right for simpler
cases. For example, consider updating bank balances with transactions cases. For example, consider updating bank balances with transactions
like like:
<screen> <screen>
BEGIN; BEGIN;
@ -303,20 +303,45 @@ COMMIT;
</para> </para>
<para> <para>
Since in Read Committed mode each new command starts with a new snapshot More complex usage can produce undesirable results in Read Committed
that includes all transactions committed up to that instant, subsequent mode. For example, consider a <command>DELETE</command> command
commands in the same transaction will see the effects of the committed operating on data that is being both added and removed from its
concurrent transaction in any case. The point at issue here is whether restriction criteria by another command, e.g. assume
or not within a <emphasis>single</> command we see an absolutely consistent <literal>website</literal> is a two-row table with
view of the database. <literal>website.hits</literal> equaling <literal>9</literal> and
<literal>10</literal>:
<screen>
BEGIN;
UPDATE website SET hits = hits + 1;
-- run from another session: DELETE FROM website WHERE hits = 10;
COMMIT;
</screen>
The <command>DELETE</command> will have no effect even though
there is a <literal>website.hits = 10</literal> row before and
after the <command>UPDATE</command>. This occurs because the
pre-update row value <literal>9</> is skipped, and when the
<command>UPDATE</command> completes and <command>DELETE</command>
obtains a lock, the new row value is no longer <literal>10</> but
<literal>11</>, which no longer matches the criteria.
</para> </para>
<para> <para>
The partial transaction isolation provided by Read Committed mode is Because Read Committed mode starts each command with a new snapshot
adequate for many applications, and this mode is fast and simple to use. that includes all transactions committed up to that instant,
However, for applications that do complex queries and updates, it might subsequent commands in the same transaction will see the effects
be necessary to guarantee a more rigorously consistent view of the of the committed concurrent transaction in any case. The point
database than the Read Committed mode provides. at issue above is whether or not a <emphasis>single</> command
sees an absolutely consistent 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; however, it is not sufficient for all cases. Applications
that do complex queries and updates might require a more rigorously
consistent view of the database than Read Committed mode provides.
</para> </para>
</sect2> </sect2>