Explicit two-phase commit (2PC)
===============================

!!!Note Two-phase commit is not available with Group Commit or CAMO. See
 :ref:`Durability limitations <Limitations>`  .

An application can explicitly opt to use two-phase commit with PGD. See `Distributed Transaction Processing: The XA Specification <http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf>`_  .

The X/Open Distributed Transaction Processing (DTP) model envisions
three software components:

-  An application program (AP) that defines transaction boundaries and
   specifies actions that constitute a transaction

-  Resource managers (RMs, such as databases or file-access systems)
   that provide access to shared resources

-  A separate component called a transaction manager (TM) that assigns
   identifiers to transactions, monitors their progress, and takes
   responsibility for transaction completion and for failure recovery

PGD supports explicit external 2PC using the ``PREPARE TRANSACTION`` and
``COMMIT PREPARED`` /``ROLLBACK PREPARED`` commands. Externally, a EDB
Postgres Distributed cluster appears to be a single resource manager to
the transaction manager for a single session.

When ``bdr.commit_scope`` is ``local`` , the transaction is prepared
only on the local node. Once committed, changes are replicated, and PGD
then applies post-commit conflict resolution.

Using ``bdr.commit_scope`` set to ``local`` might not seem to make sense
with explicit two-phase commit. However, the option is offered to allow
you to control the tradeoff between transaction latency and robustness.

Explicit two-phase commit doesn’t work with either CAMO or the global
commit scope. Future releases might enable this combination.

Use
---

Two-phase commits with a local commit scope work exactly like standard
PostgreSQL. Use the local commit scope and disable CAMO.

.. code:: sql

   BEGIN;

   SET LOCAL bdr.enable_camo = off;
   SET LOCAL bdr.commit_scope = local;

   ... other commands possible...

To start the first phase of the commit, the client must assign a global
transaction id, which can be any unique string identifying the
transaction:

.. code:: sql

   PREPARE TRANSACTION some-global-id;

After a successful first phase, all nodes have applied the changes and
are prepared for committing the transaction. The client must then invoke
the second phase from the same node:

.. code:: sql

   COMMIT PREPARED some-global-id;
