#distributed #transactions #xa


A rust language binding for XA Distributed Transactions

6 releases

0.2.4 May 20, 2020
0.2.3 Aug 22, 2019
0.2.2 Dec 14, 2018
0.2.1 Feb 7, 2018
0.1.0 Jan 29, 2018

#504 in Database interfaces

Download history 15/week @ 2022-04-22 34/week @ 2022-04-29 38/week @ 2022-05-06 112/week @ 2022-05-13 34/week @ 2022-05-20 44/week @ 2022-05-27 54/week @ 2022-06-03 10/week @ 2022-06-10 15/week @ 2022-06-17 19/week @ 2022-06-24 15/week @ 2022-07-01 13/week @ 2022-07-08 28/week @ 2022-07-15 20/week @ 2022-07-22 20/week @ 2022-07-29 32/week @ 2022-08-05

101 downloads per month
Used in hdbconnect


784 lines


Structs and traits for dealing with distributed transactions.

This crate is an attempt to provide a reasonable rust language binding for XA Distributed Transactions.

So far there is no support for asynchronous operations in resource managers.


Let's assume we have two (or more) different database connections, most likely to different database installations, and we want to use two-phase-commit to ensure that all our changes to these connections are stored consistently (i.e. all or nothing).

Precondition: both connections (i.e. both drivers) have to be prepared for working with dist_tx, and both are not using automatic commit.

    let mut conn_a = ...;
    let mut conn_b = ...;

First instantiate a SimpleTransactionManager:

# use dist_tx::tm::SimpleTransactionManager;
    let mut tm = SimpleTransactionManager::new("XA Demo");

Then retrieve a ResourceManager implementation from each connection, and register it at the transaction manager. Every registered resource manager is registered with a distinct ID. In the example below we tell the transaction manager to cleanup eventually existing open transaction left-overs from previous runs for the two ids.

This makes already clear that the IDs (of type u64) should be chosen in a way that minimizes undesired collision probabilities, and maximizes intended "collisions".

    tm.register(conn_a.get_resource_manager(), id_1, true)?;
    tm.register(conn_b.get_resource_manager(), id_2, true)?;

Now we start a distributed transaction


and then we're ready to do all required updates via the two database connections:

    conn_a.dml(&insert_stmt(1, "foo"))?;
    conn_b.dml(&insert_stmt(2, "bar"))?;

At this point nothing is committed yet, which we could verify with additional connections to the two databases that are not registered to tm.

Finally, when all updates were done successfully, we commit the transaction:


Now all updates are committed and visible, which we could again verify with additional connections.


Database drivers etc, who want to enable their users to take part in distributed transactions that are managed via dist_tx, can either implement rm::ResourceManager, which is a more rust-idiomatic interpretation of the XA resource manager, or they implement rm::CResourceManager, which is more C-ish, and wrap it into a rm::CRmWrapper (which implements rm::ResourceManager).


~19K SLoC