diff --git a/doc/src/connection.rst b/doc/src/connection.rst index 787747a5..df869bc1 100644 --- a/doc/src/connection.rst +++ b/doc/src/connection.rst @@ -90,6 +90,7 @@ The ``connection`` class .. _PgBouncer: http://pgbouncer.projects.postgresql.org/ + .. index:: single: Exceptions; In the connection class @@ -99,6 +100,157 @@ The ``connection`` class available in the `psycopg2` module. See :ref:`dbapi-exceptions`. + + .. index:: + single: Two-phase commit; methods + + .. rubric:: Two-phase commit support methods + + .. versionadded:: 2.2.3 + + .. seealso:: :ref:`tpc` for an introductory explanation of these methods. + + Note that PostgreSQL supports two-phase commit since release 8.1: these + methods raise `~psycopg2.NotSupportedError` if used with an older version + server. + + + .. _tpc_methods: + + .. method:: xid(format_id, gtrid, bqual) + + Returns a transaction ID object suitable for passing to the + `!tpc_*()` methods of this connection. The argument types and + constraints are explained in :ref:`tpc`. + + The object returned can be accessed and unpacked as a 3 items tuple, + returning the arguments passed to the method. The same values are + available as attributes `!format_id`, `!gtrid`, `!bqual`. + + + .. method:: tpc_begin(xid) + + Begins a TPC transaction with the given transaction ID *xid*. + + This method should be called outside of a transaction (i.e. nothing + may have executed since the last `~connection.commit()` or + `~connection.rollback()` and `connection.status` is + `~psycopg2.extensions.STATUS_READY`). + + Furthermore, it is an error to call `!commit()` or `!rollback()` + within the TPC transaction: in this case a `~psycopg2.ProgrammingError` + is raised. + + The *xid* may be either an object returned by the `~connection.xid()` + method or a plain string: the latter allows to create a transaction + using the provided string as PostgreSQL transaction id. See also + `~connection.tpc_recover()`. + + + .. index:: + pair: Transaction; Prepare + + .. method:: tpc_prepare() + + Performs the first phase of a transaction started with + `~connection.tpc_begin()`. A `~psycopg2.ProgrammingError` is raised if + this method is used outside of a TPC transaction. + + After calling `!tpc_prepare()`, no statements can be executed until + `~connection.tpc_commit()` or `~connection.tpc_rollback()` have been + called. The `~connection.reset()` method can be used to restore the + status of the connection to `~psycopg2.extensions.STATUS_READY`: the + transaction will remained prepared in the database and will be + possible to finish it with `!tpc_commit(xid)` and + `!tpc_rollback(xid)`. + + .. seealso:: the |PREPARE TRANSACTION|_ PostgreSQL command. + + .. |PREPARE TRANSACTION| replace:: :sql:`PREPARE TRANSACTION` + .. _PREPARE TRANSACTION: http://www.postgresql.org/docs/9.0/static/sql-prepare-transaction.html + + + .. index:: + pair: Commit; Prepared + + .. method:: tpc_commit([xid]) + + When called with no arguments, `!tpc_commit()` commits a TPC + transaction previously prepared with `~connection.tpc_prepare()`. + + If `!tpc_commit()` is called prior to `!tpc_prepare()`, a single phase + commit is performed. A transaction manager may choose to do this if + only a single resource is participating in the global transaction. + + When called with a transaction ID *xid*, the database commits + the given transaction. If an invalid transaction ID is + provided, a `~psycopg2.ProgrammingError` will be raised. This form + should be called outside of a transaction, and is intended for use in + recovery. + + On return, the TPC transaction is ended. + + .. seealso:: the |COMMIT PREPARED|_ PostgreSQL command. + + .. |COMMIT PREPARED| replace:: :sql:`COMMIT PREPARED` + .. _COMMIT PREPARED: http://www.postgresql.org/docs/9.0/static/sql-commit-prepared.html + + + .. index:: + pair: Rollback; Prepared + + .. method:: tpc_rollback([xid]) + + When called with no arguments, `!tpc_rollback()` rolls back a TPC + transaction. It may be called before or after + `~connection.tpc_prepare()`. + + When called with a transaction ID *xid*, it rolls back the given + transaction. If an invalid transaction ID is provided, a + `~psycopg2.ProgrammingError` is raised. This form should be called + outside of a transaction, and is intended for use in recovery. + + On return, the TPC transaction is ended. + + .. seealso:: the |ROLLBACK PREPARED|_ PostgreSQL command. + + .. |ROLLBACK PREPARED| replace:: :sql:`ROLLBACK PREPARED` + .. _ROLLBACK PREPARED: http://www.postgresql.org/docs/9.0/static/sql-rollback-prepared.html + + + .. index:: + pair: Transaction; Recover + + .. method:: tpc_recover() + + Returns a list of pending transaction IDs suitable for use with + `!tpc_commit(xid)` or `!tpc_rollback(xid)`. + + If a transaction was not initiated by Psycopg, the returned Xids will + have attributes `!format_id` and `!bqual` set to `None` and the + `!gtrid` set to the PostgreSQL transaction ID: such Xids are still + usable for recovery. Psycopg uses the same algorithm of the + `PostgreSQL JDBC driver`__ to encode a XA triple in a string, so + transactions initiated by a program using such driver should be + unpacked correctly. + + .. __: http://jdbc.postgresql.org/ + + Xids returned by `!tpc_recover()` have additional attributes populated + with the values read from the server: + + - `!prepared`: timestamp with timezone reporting the time the + transaction was prepared + - `!owner`: name of the user who prepared the transaction + - `!database`: name of the database the transaction belongs to + + .. seealso:: the |pg_prepared_xacts|_ system view. + + .. |pg_prepared_xacts| replace:: `pg_prepared_xacts` + .. _pg_prepared_xacts: http://www.postgresql.org/docs/9.0/static/view-pg-prepared-xacts.html + + + .. extension:: The above methods are the only ones defined by the |DBAPI| protocol. @@ -118,7 +270,9 @@ The ``connection`` class The method rolls back an eventual pending transaction and executes the PostgreSQL |RESET|_ and |SET SESSION AUTHORIZATION|__ to revert the - session to the default values. + session to the default values. A two-phase commit transaction prepared + using `~connection.tpc_prepare()` will remain in the database + available for recover. .. |RESET| replace:: :sql:`RESET` .. _RESET: http://www.postgresql.org/docs/9.0/static/sql-reset.html diff --git a/doc/src/extensions.rst b/doc/src/extensions.rst index ec93b2e5..6517c709 100644 --- a/doc/src/extensions.rst +++ b/doc/src/extensions.rst @@ -450,6 +450,15 @@ internal usage and Python code should not rely on them. An alias for `STATUS_BEGIN` +.. data:: STATUS_PREPARED + + The connection has been prepared for the second phase in a :ref:`two-phase + commit ` transaction. The connection can't be used to send commands + to the database until the transaction is finished with + `~connection.tpc_commit()` or `~connection.tpc_rollback()`. + + .. versionadded:: 2.2.3 + .. index:: diff --git a/doc/src/usage.rst b/doc/src/usage.rst index 6528f6c5..311e5659 100644 --- a/doc/src/usage.rst +++ b/doc/src/usage.rst @@ -540,3 +540,54 @@ using the |lo_import|_ and |lo_export|_ libpq functions. .. _lo_import: http://www.postgresql.org/docs/9.0/static/lo-interfaces.html#LO-IMPORT .. |lo_export| replace:: `!lo_export()` .. _lo_export: http://www.postgresql.org/docs/9.0/static/lo-interfaces.html#LO-EXPORT + + + +.. index:: + pair: Two-phase commit; Transaction + +.. _tpc: + +Two-Phase Commit protocol support +--------------------------------- + +.. versionadded:: 2.2.3 + +Psycopg exposes the two-phase commit features available from PostgreSQL 8,1 +implementing the *two-phase commit extensions* proposed by the |DBAPI|. + +The |DBAPI| model of two-phase commit is inspired to the `XA specification`__, +according to which transaction IDs are formed from three components: + +- a format ID (non-negative 32 bit integer) +- a global transaction ID (string not longer than 64 bytes) +- a branch qualifier (string not longer than 64 bytes) + +For a particular global transaction, the first two components will be the same +for all the resources. Every resource will be assigned a different branch +qualifier. + +According to the |DBAPI| specification, a transaction ID is created using the +`connection.xid()` method. Once you have a transaction id, a distributed +transaction can be started with `connection.tpc_begin()`, prepared using +`~connection.tpc_prepare()` and completed using `~connection.tpc_commit()` or +`~connection.tpc_rollback()`. Transaction IDs can also be retrieved from the +database using `~connection.tpc_recover()` and completed using the above +`!tpc_commit()` and `!tpc_rollback()`. + +PostgreSQL doesn't follow the XA standard though, and the ID for a PostgreSQL +prepared transaction can be any string up to 200 characters long. Psycopg can +deal both with Xid objects created by the `!xid()` method and with +transactions identified only by a string. + +The format in which the Xids are converted into strings passed to the +database is the same employed by the `PostgreSQL JDBC driver`__: this should +allow interoperation between tools written in Python and in Java. For example +a recovery tool written in Python would be able to recognize the components of +transactions produced by a Java program. + +For further details see the documentation for the above methods. + +.. __: http://www.opengroup.org/bookstore/catalog/c193.htm +.. __: http://jdbc.postgresql.org/ +