the precise circumstances,
but it will always have the SQLSTATE code <literal>40001</literal>
(<literal>serialization_failure</literal>).
</para>
<para>
It may also be advisable to retry deadlock failures.
These have the SQLSTATE code <literal>40P01</literal>
(<literal>deadlock_detected</literal>).
</para>
<para>
In some cases it is also appropriate to retry unique-key failures,
which have SQLSTATE code <literal>23505</literal>
(<literal>unique_violation</literal>), and exclusion constraint
failures, which have SQLSTATE code <literal>23P01</literal>
(<literal>exclusion_violation</literal>). For example, if the
application selects a new value for a primary key column after
inspecting the currently stored keys, it could get a unique-key
failure because another application instance selected the same new key
concurrently. This is effectively a serialization failure, but the
server will not detect it as such because it cannot <quote>see</quote>
the connection between the inserted value and the previous reads.
There are also some corner cases in which the server will issue a
unique-key or exclusion constraint error even though in principle it
has enough information to determine that a serialization problem
is the underlying cause. While it's recommendable to just
retry <literal>serialization_failure</literal> errors unconditionally,
more care is needed when retrying these other error codes, since they
might represent persistent error conditions rather than transient
failures.
</para>
<para>
It is important to retry the complete transaction, including all logic
that decides which SQL to issue and/or which values to use.
Therefore, <productname>PostgreSQL</productname> does not offer an
automatic retry facility, since it cannot do so with any guarantee of
correctness.
</para>
<para>
Transaction retry does not guarantee that the retried transaction will
complete; multiple retries may be needed. In cases with very high
contention, it is possible that completion of a transaction may take
many attempts. In cases involving a conflicting prepared transaction,
it may not be possible to make progress until the prepared transaction
commits or rolls back.
</para>
</sect1>
<sect1 id="mvcc-caveats">
<title>Caveats</title>
<para>
Some DDL commands, currently only <link linkend="sql-truncate"><command>TRUNCATE</command></link> and the
table-rewriting forms of <link linkend="sql-altertable"><command>ALTER TABLE</command></link>, are not
MVCC-safe. This means that after the truncation or rewrite commits, the
table will appear empty to concurrent transactions, if they are using a
snapshot taken before the DDL command committed. This will only be an
issue for a transaction that did not access the table in question
before the DDL command started — any transaction that has done so
would hold at least an <literal>ACCESS SHARE</literal> table lock,
which would block the DDL command until that transaction completes.
So these commands will not cause any apparent inconsistency in the
table contents for successive queries on the target table, but they
could cause visible inconsistency between the contents of the target
table and other tables in the database.
</para>
<para>
Support for the Serializable transaction isolation level has not yet