Sophie

Sophie

distrib > Mandriva > current > i586 > media > main-updates > by-pkgid > fc62ce67f262cdcd253dc7f849ce3223 > files > 936

postgresql8.4-docs-8.4.12-0.1mdv2010.2.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>Transaction Isolation</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REV="MADE"
HREF="mailto:pgsql-docs@postgresql.org"><LINK
REL="HOME"
TITLE="PostgreSQL 8.4.12 Documentation"
HREF="index.html"><LINK
REL="UP"
TITLE="Concurrency Control"
HREF="mvcc.html"><LINK
REL="PREVIOUS"
TITLE="Introduction"
HREF="mvcc-intro.html"><LINK
REL="NEXT"
TITLE="Explicit Locking"
HREF="explicit-locking.html"><LINK
REL="STYLESHEET"
TYPE="text/css"
HREF="stylesheet.css"><META
HTTP-EQUIV="Content-Type"
CONTENT="text/html; charset=ISO-8859-1"><META
NAME="creation"
CONTENT="2012-05-31T23:30:11"></HEAD
><BODY
CLASS="SECT1"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="5"
ALIGN="center"
VALIGN="bottom"
>PostgreSQL 8.4.12 Documentation</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="top"
><A
HREF="mvcc-intro.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="top"
><A
HREF="mvcc.html"
>Fast Backward</A
></TD
><TD
WIDTH="60%"
ALIGN="center"
VALIGN="bottom"
>Chapter 13. Concurrency Control</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="top"
><A
HREF="mvcc.html"
>Fast Forward</A
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="top"
><A
HREF="explicit-locking.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="TRANSACTION-ISO"
>13.2. Transaction Isolation</A
></H1
><A
NAME="AEN20935"
></A
><P
>    The <ACRONYM
CLASS="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:

    <P
></P
></P><DIV
CLASS="VARIABLELIST"
><DL
><DT
>dirty read
       <A
NAME="AEN20942"
></A
></DT
><DD
><P
>        A transaction reads data written by a concurrent uncommitted transaction.
       </P
></DD
><DT
>nonrepeatable read
       <A
NAME="AEN20948"
></A
></DT
><DD
><P
>        A transaction re-reads data it has previously read and finds that data
        has been modified by another transaction (that committed since the
        initial read).
       </P
></DD
><DT
>phantom read
       <A
NAME="AEN20954"
></A
></DT
><DD
><P
>        A transaction re-executes a query returning a set of rows that satisfy a
        search condition and finds that the set of rows satisfying the condition
        has changed due to another recently-committed transaction.
       </P
></DD
></DL
></DIV
><P>
   </P
><P
>    <A
NAME="AEN20959"
></A
>
    The four transaction isolation levels and the corresponding
    behaviors are described in <A
HREF="transaction-iso.html#MVCC-ISOLEVEL-TABLE"
>Table 13-1</A
>.
   </P
><DIV
CLASS="TABLE"
><A
NAME="MVCC-ISOLEVEL-TABLE"
></A
><P
><B
>Table 13-1. <ACRONYM
CLASS="ACRONYM"
>SQL</ACRONYM
> Transaction Isolation Levels</B
></P
><TABLE
BORDER="1"
CLASS="CALSTABLE"
><COL><COL><COL><COL><THEAD
><TR
><TH
>         Isolation Level
        </TH
><TH
>         Dirty Read
        </TH
><TH
>         Nonrepeatable Read
        </TH
><TH
>         Phantom Read
        </TH
></TR
></THEAD
><TBODY
><TR
><TD
>         Read uncommitted
        </TD
><TD
>         Possible
        </TD
><TD
>         Possible
        </TD
><TD
>         Possible
        </TD
></TR
><TR
><TD
>         Read committed
        </TD
><TD
>         Not possible
        </TD
><TD
>         Possible
        </TD
><TD
>         Possible
        </TD
></TR
><TR
><TD
>         Repeatable read
        </TD
><TD
>         Not possible
        </TD
><TD
>         Not possible
        </TD
><TD
>         Possible
        </TD
></TR
><TR
><TD
>         Serializable
        </TD
><TD
>         Not possible
        </TD
><TD
>         Not possible
        </TD
><TD
>         Not possible
        </TD
></TR
></TBODY
></TABLE
></DIV
><P
>    In <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
>, 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
    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 might 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
    phenomena must happen.  The reason that <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
>
    only provides two isolation levels is that this is the only
    sensible way to map the standard isolation levels to the multiversion
    concurrency control architecture.  The behavior of the available
    isolation levels is detailed in the following subsections.
   </P
><P
>    To set the transaction isolation level of a transaction, use the
    command <A
HREF="sql-set-transaction.html"
><I
>SET TRANSACTION</I
></A
>.
   </P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="XACT-READ-COMMITTED"
>13.2.1. Read Committed Isolation Level</A
></H2
><A
NAME="AEN21000"
></A
><P
>    <I
CLASS="FIRSTTERM"
>Read Committed</I
> is the default isolation
    level in <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
>.  When a transaction
    uses this isolation level, a <TT
CLASS="COMMAND"
>SELECT</TT
> query
    (without a <TT
CLASS="LITERAL"
>FOR UPDATE/SHARE</TT
> clause) sees only data
    committed before the query began; it never sees either uncommitted
    data or changes committed during query execution by concurrent
    transactions.  In effect, a <TT
CLASS="COMMAND"
>SELECT</TT
> query sees
    a snapshot of the database as of the instant the query begins to
    run.   However, <TT
CLASS="COMMAND"
>SELECT</TT
> does see the effects
    of previous updates executed within its own transaction, even
    though they are not yet committed.  Also note that two successive
    <TT
CLASS="COMMAND"
>SELECT</TT
> commands can see different data, even
    though they are within a single transaction, if other transactions
    commit changes during execution of the first <TT
CLASS="COMMAND"
>SELECT</TT
>.
   </P
><P
>    <TT
CLASS="COMMAND"
>UPDATE</TT
>, <TT
CLASS="COMMAND"
>DELETE</TT
>, <TT
CLASS="COMMAND"
>SELECT
    FOR UPDATE</TT
>, and <TT
CLASS="COMMAND"
>SELECT FOR SHARE</TT
> commands
    behave the same as <TT
CLASS="COMMAND"
>SELECT</TT
>
    in terms of searching for target rows: they will only find target rows
    that were committed as of the command start time.  However, such a target
    row might have already been updated (or deleted or locked) 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
    the row.  The search condition of the command (the <TT
CLASS="LITERAL"
>WHERE</TT
> clause) is
    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
    using the updated version of the row.  In the case of
    <TT
CLASS="COMMAND"
>SELECT FOR UPDATE</TT
> and <TT
CLASS="COMMAND"
>SELECT FOR
    SHARE</TT
>, this means it is the updated version of the row that is
    locked and returned to the client.
   </P
><P
>    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 on 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
    involve complex search conditions; however, it is just right for simpler
    cases.  For example, consider updating bank balances with transactions
    like:

</P><PRE
CLASS="SCREEN"
>BEGIN;
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 12345;
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 7534;
COMMIT;</PRE
><P>

    If two such transactions concurrently try to change the balance of account
    12345, we clearly want the second transaction to start with the updated
    version of the account's row.  Because each command is affecting only a
    predetermined row, letting it see the updated version of the row does
    not create any troublesome inconsistency.
   </P
><P
>    More complex usage can produce undesirable results in Read Committed
    mode.  For example, consider a <TT
CLASS="COMMAND"
>DELETE</TT
> command
    operating on data that is being both added and removed from its
    restriction criteria by another command, e.g., assume
    <TT
CLASS="LITERAL"
>website</TT
> is a two-row table with
    <TT
CLASS="LITERAL"
>website.hits</TT
> equaling <TT
CLASS="LITERAL"
>9</TT
> and
    <TT
CLASS="LITERAL"
>10</TT
>:

</P><PRE
CLASS="SCREEN"
>BEGIN;
UPDATE website SET hits = hits + 1;
-- run from another session:  DELETE FROM website WHERE hits = 10;
COMMIT;</PRE
><P>

    The <TT
CLASS="COMMAND"
>DELETE</TT
> will have no effect even though
    there is a <TT
CLASS="LITERAL"
>website.hits = 10</TT
> row before and
    after the <TT
CLASS="COMMAND"
>UPDATE</TT
>. This occurs because the
    pre-update row value <TT
CLASS="LITERAL"
>9</TT
> is skipped, and when the
    <TT
CLASS="COMMAND"
>UPDATE</TT
> completes and <TT
CLASS="COMMAND"
>DELETE</TT
>
    obtains a lock, the new row value is no longer <TT
CLASS="LITERAL"
>10</TT
> but
    <TT
CLASS="LITERAL"
>11</TT
>, which no longer matches the criteria.
   </P
><P
>    Because Read Committed mode starts each command with a new snapshot
    that includes all transactions committed up to that instant,
    subsequent commands in the same transaction will see the effects
    of the committed concurrent transaction in any case.  The point
    at issue above is whether or not a <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>single</I
></SPAN
> command
    sees an absolutely consistent view of the database.
   </P
><P
>    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.
   </P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="XACT-SERIALIZABLE"
>13.2.2. Serializable Isolation Level</A
></H2
><A
NAME="AEN21043"
></A
><P
>    The <I
CLASS="FIRSTTERM"
>Serializable</I
> isolation level provides the strictest 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.
   </P
><P
>    When a transaction is using the serializable level,
    a <TT
CLASS="COMMAND"
>SELECT</TT
> query only sees data committed before the
    transaction began; it never sees either uncommitted data or changes
    committed
    during transaction execution by concurrent transactions.  (However,
    the query does see the effects of previous updates
    executed within its own transaction, even though they are not yet
    committed.)  This is different from Read Committed in that
    a query in a serializable transaction
    sees a snapshot as of the start of the <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>transaction</I
></SPAN
>,
    not as of the start
    of the current query within the transaction.  Thus, successive
    <TT
CLASS="COMMAND"
>SELECT</TT
> commands within a <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>single</I
></SPAN
>
    transaction see the same data, i.e., they do not see changes made by
    other transactions that committed after their own transaction started.
    (This behavior can be ideal for reporting applications.)
   </P
><P
>    <TT
CLASS="COMMAND"
>UPDATE</TT
>, <TT
CLASS="COMMAND"
>DELETE</TT
>, <TT
CLASS="COMMAND"
>SELECT
    FOR UPDATE</TT
>, and <TT
CLASS="COMMAND"
>SELECT FOR SHARE</TT
> commands
    behave the same as <TT
CLASS="COMMAND"
>SELECT</TT
>
    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 might have already been updated (or deleted or locked) 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 locked it)
    then the serializable transaction will be rolled back with the message

</P><PRE
CLASS="SCREEN"
>ERROR:  could not serialize access due to concurrent update</PRE
><P>

    because a serializable transaction cannot modify or lock rows changed by
    other transactions after the serializable transaction began.
   </P
><P
>    When an application receives this error message, it should abort
    the current transaction and retry the whole transaction from
    the beginning.  The second time through, the transaction will see 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.
   </P
><P
>    Note that only updating transactions might need to be retried; read-only
    transactions will never have serialization conflicts.
   </P
><P
>    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 can be significant,
    serializable mode is recommended only when updating transactions contain logic
    sufficiently complex that they might give wrong answers in Read
    Committed mode.  Most commonly, Serializable mode is necessary when
    a transaction executes several successive commands that must see
    identical views of the database.
   </P
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="MVCC-SERIALIZABILITY"
>13.2.2.1. Serializable Isolation versus True Serializability</A
></H3
><A
NAME="AEN21065"
></A
><A
NAME="AEN21067"
></A
><P
>    The intuitive meaning (and mathematical definition) of
    <SPAN
CLASS="QUOTE"
>"serializable"</SPAN
> execution is that any two successfully committed
    concurrent transactions will appear to have executed strictly serially,
    one after the other &mdash; although which one appeared to occur first might
    not be predictable in advance.  It is important to realize that forbidding
    the undesirable behaviors listed in <A
HREF="transaction-iso.html#MVCC-ISOLEVEL-TABLE"
>Table 13-1</A
>
    is not sufficient to guarantee true serializability, and in fact
    <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
>'s Serializable mode <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>does
    not guarantee serializable execution in this sense</I
></SPAN
>.  As an example,
    consider a table <TT
CLASS="STRUCTNAME"
>mytab</TT
>, initially containing:
</P><PRE
CLASS="SCREEN"
> class | value 
-------+-------
     1 |    10
     1 |    20
     2 |   100
     2 |   200</PRE
><P>
    Suppose that serializable transaction A computes:
</P><PRE
CLASS="SCREEN"
>SELECT SUM(value) FROM mytab WHERE class = 1;</PRE
><P>
    and then inserts the result (30) as the <TT
CLASS="STRUCTFIELD"
>value</TT
> in a
    new row with <TT
CLASS="STRUCTFIELD"
>class</TT
><TT
CLASS="LITERAL"
> = 2</TT
>.  Concurrently, serializable
    transaction B computes:
</P><PRE
CLASS="SCREEN"
>SELECT SUM(value) FROM mytab WHERE class = 2;</PRE
><P>
    and obtains the result 300, which it inserts in a new row with
    <TT
CLASS="STRUCTFIELD"
>class</TT
><TT
CLASS="LITERAL"
> = 1</TT
>.  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.
   </P
><P
>    To guarantee true mathematical serializability, it is necessary for
    a database system to enforce <I
CLASS="FIRSTTERM"
>predicate locking</I
>, which
    means that a transaction cannot insert or modify a row that would
    have matched the <TT
CLASS="LITERAL"
>WHERE</TT
> condition of a query in another concurrent
    transaction.  For example, once transaction A has executed the query
    <TT
CLASS="LITERAL"
>SELECT ... WHERE class = 1</TT
>, a predicate-locking system
    would forbid transaction B from inserting any new row with class 1
    until A has committed.
     <A
NAME="AEN21087"
HREF="#FTN.AEN21087"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>
    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.)  For these reasons,
    <SPAN
CLASS="PRODUCTNAME"
>PostgreSQL</SPAN
> does not implement predicate
    locking.
   </P
><P
>    In cases where the possibility of non-serializable execution
    is a real hazard, problems can be prevented by appropriate use of
    explicit locking.  Further discussion appears in the following
    sections.
   </P
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN21087"
HREF="transaction-iso.html#AEN21087"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>       Essentially, a predicate-locking system prevents phantom reads
       by restricting what is written, whereas MVCC prevents them by
       restricting what is read.
      </P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="mvcc-intro.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="explicit-locking.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Introduction</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="mvcc.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Explicit Locking</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>