XA support

Lists: pgsql-jdbc
From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: XA support
Date: 2005-06-29 19:49:51
Message-ID: Pine.OSF.4.61.0506291920120.108382@kosh.hut.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Now that we have support for two-phase commit in the backend, it's time to
add XA support to the JDBC driver.

The first issue we have to solve is the way we associate transactions with
connections.

Consider the following example:

public void testMultiplex() throws Exception {
Xid xid1 = new CustomXid(1);
Xid xid2 = new CustomXid(2);
Xid xid3 = new CustomXid(3);

xaRes.start(xid1, XAResource.TMNOFLAGS);
conn.createStatement().executeUpdate("UPDATE foobar1 SET foo = 'aa'");
xaRes.end(xid1, XAResource.TMSUCCESS);

xaRes.start(xid2, XAResource.TMNOFLAGS);
conn.createStatement().executeUpdate("UPDATE foobar2 SET foo = 'bb'");
xaRes.end(xid2, XAResource.TMSUCCESS);

xaRes.start(xid3, XAResource.TMNOFLAGS);
conn.createStatement().executeUpdate("UPDATE foobar3 SET foo = 'cc'");
xaRes.end(xid3, XAResource.TMSUCCESS);

xaRes.commit(xid1, true);
xaRes.commit(xid2, true);
xaRes.commit(xid3, true);
}

According to the JTA spec, this should be supported. One connection can be
used to initiate a new transaction, without committing, preparing or
rolling back the previous one.

We don't have backend support for this kind of operation. A connection can
be associated with only transaction at a time. Changing that behaviour
would require a major overhaul of the way the backend handles transactions
and connections, AFAICS.

I can see three alternative ways to handle this in the driver:

A. When the second transaction starts, a new physical connection is opened
behind the scenes. The second transaction is associated with the new
physical connection and the first transaction remains associated with the
original connection.

The application server is usually responsible for connection pooling, so
opening new connnections behind the scenes will mess with the pool limits
and possible prepared statement cache. We would have to do some kind of
connection pooling ourselves, regardless of the application server pool.

B. When the second transaction starts, the first transaction is prepared
behind the scenes, freeing the connection for the new transaction.

This makes it impossible to implement the transaction suspend/resume
functionality, since the first transaction cannot be used to issue any
more statements after the implicit prepare. It also imposes the additional
overhead of two-phase commit for transactions that could otherwise use
regular one-phase commit. It will also cause trouble if the connection is
broken after the implicit prepare, because the transaction manager
might not recognize the implicitly prepared transaction, so it will stay
in the system holding locks etc. until it's manually rolled back by the
administrator.

C. The second start call blocks, until the first transaction is committed,
prepared, or rolled back.

This might cause tricky deadlocks, depending on the threading model of the
application server and the transaction manager.

I experimented with some other DBMS' to find out how they handle this.

Apache Derby (IBM Cloudscape):
Supports XA only in embedded mode. Playing with temporary tables lead me
to think that it does something similar to A. Connection management is
probably quite lightweight in embedded mode. I didn't bother to look at
the source code, though.

DB2 (Type 4 driver):
Does B, and suffers from the problems described above. "LIST INDOUBT
TRANSACTIONS" shows the implicitly prepared transactions, suspend/resume
doesn't work as it should.

Oracle:
The server natively supports having many active transactions in one connection.

I tried to install Firebird and Sybase as well, but couldn't get them
installed properly. Anyone want to test them, or some other DBMS?

Which approach should we take?

- Heikki


From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-29 20:27:32
Message-ID: 84DC4D65-95BD-4CB5-AD5E-6C1E80EF6E69@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

I see option A below as the lesser of three evils. Is it reasonable
to believe that people using XA would
know enough to allocate enough connections ?

Optionally we could have two implementations and choose between A and B

Dave
On 29-Jun-05, at 3:49 PM, Heikki Linnakangas wrote:

> Now that we have support for two-phase commit in the backend, it's
> time to add XA support to the JDBC driver.
>
> The first issue we have to solve is the way we associate
> transactions with connections.
>
> Consider the following example:
>
> public void testMultiplex() throws Exception {
> Xid xid1 = new CustomXid(1);
> Xid xid2 = new CustomXid(2);
> Xid xid3 = new CustomXid(3);
>
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar1 SET foo =
> 'aa'");
> xaRes.end(xid1, XAResource.TMSUCCESS);
>
> xaRes.start(xid2, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar2 SET foo =
> 'bb'");
> xaRes.end(xid2, XAResource.TMSUCCESS);
>
> xaRes.start(xid3, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar3 SET foo =
> 'cc'");
> xaRes.end(xid3, XAResource.TMSUCCESS);
>
> xaRes.commit(xid1, true);
> xaRes.commit(xid2, true);
> xaRes.commit(xid3, true);
> }
>
> According to the JTA spec, this should be supported. One connection
> can be used to initiate a new transaction, without committing,
> preparing or rolling back the previous one.
>
> We don't have backend support for this kind of operation. A
> connection can be associated with only transaction at a time.
> Changing that behaviour would require a major overhaul of the way
> the backend handles transactions and connections, AFAICS.
>
> I can see three alternative ways to handle this in the driver:
>
> A. When the second transaction starts, a new physical connection is
> opened behind the scenes. The second transaction is associated with
> the new physical connection and the first transaction remains
> associated with the original connection.
>
> The application server is usually responsible for connection
> pooling, so opening new connnections behind the scenes will mess
> with the pool limits and possible prepared statement cache. We
> would have to do some kind of connection pooling ourselves,
> regardless of the application server pool.
>
> B. When the second transaction starts, the first transaction is
> prepared behind the scenes, freeing the connection for the new
> transaction.
>
> This makes it impossible to implement the transaction suspend/
> resume functionality, since the first transaction cannot be used to
> issue any more statements after the implicit prepare. It also
> imposes the additional overhead of two-phase commit for
> transactions that could otherwise use regular one-phase commit. It
> will also cause trouble if the connection is broken after the
> implicit prepare, because the transaction manager might not
> recognize the implicitly prepared transaction, so it will stay in
> the system holding locks etc. until it's manually rolled back by
> the administrator.
>
> C. The second start call blocks, until the first transaction is
> committed, prepared, or rolled back.
>
> This might cause tricky deadlocks, depending on the threading model
> of the application server and the transaction manager.
>
> I experimented with some other DBMS' to find out how they handle this.
>
> Apache Derby (IBM Cloudscape):
> Supports XA only in embedded mode. Playing with temporary tables
> lead me to think that it does something similar to A. Connection
> management is probably quite lightweight in embedded mode. I didn't
> bother to look at the source code, though.
>
> DB2 (Type 4 driver):
> Does B, and suffers from the problems described above. "LIST
> INDOUBT TRANSACTIONS" shows the implicitly prepared transactions,
> suspend/resume doesn't work as it should.
>
> Oracle:
> The server natively supports having many active transactions in one
> connection.
>
> I tried to install Firebird and Sybase as well, but couldn't get
> them installed properly. Anyone want to test them, or some other DBMS?
>
> Which approach should we take?
>
> - Heikki
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to
> majordomo(at)postgresql(dot)org)
>
>


From: Dave Cramer <davec(at)fastcrypt(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-29 20:36:19
Message-ID: 45AEF985-8CB5-40E7-8FCB-0A61315E3315@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

What about the notion of being able to vote on whether to commit?
xaRes.prepare() ?

Do we have any support for this notion ?

Dave
On 29-Jun-05, at 3:49 PM, Heikki Linnakangas wrote:

> Now that we have support for two-phase commit in the backend, it's
> time to add XA support to the JDBC driver.
>
> The first issue we have to solve is the way we associate
> transactions with connections.
>
> Consider the following example:
>
> public void testMultiplex() throws Exception {
> Xid xid1 = new CustomXid(1);
> Xid xid2 = new CustomXid(2);
> Xid xid3 = new CustomXid(3);
>
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar1 SET foo =
> 'aa'");
> xaRes.end(xid1, XAResource.TMSUCCESS);
>
> xaRes.start(xid2, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar2 SET foo =
> 'bb'");
> xaRes.end(xid2, XAResource.TMSUCCESS);
>
> xaRes.start(xid3, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar3 SET foo =
> 'cc'");
> xaRes.end(xid3, XAResource.TMSUCCESS);
>
> xaRes.commit(xid1, true);
> xaRes.commit(xid2, true);
> xaRes.commit(xid3, true);
> }
>
> According to the JTA spec, this should be supported. One connection
> can be used to initiate a new transaction, without committing,
> preparing or rolling back the previous one.
>
> We don't have backend support for this kind of operation. A
> connection can be associated with only transaction at a time.
> Changing that behaviour would require a major overhaul of the way
> the backend handles transactions and connections, AFAICS.
>
> I can see three alternative ways to handle this in the driver:
>
> A. When the second transaction starts, a new physical connection is
> opened behind the scenes. The second transaction is associated with
> the new physical connection and the first transaction remains
> associated with the original connection.
>
> The application server is usually responsible for connection
> pooling, so opening new connnections behind the scenes will mess
> with the pool limits and possible prepared statement cache. We
> would have to do some kind of connection pooling ourselves,
> regardless of the application server pool.
>
> B. When the second transaction starts, the first transaction is
> prepared behind the scenes, freeing the connection for the new
> transaction.
>
> This makes it impossible to implement the transaction suspend/
> resume functionality, since the first transaction cannot be used to
> issue any more statements after the implicit prepare. It also
> imposes the additional overhead of two-phase commit for
> transactions that could otherwise use regular one-phase commit. It
> will also cause trouble if the connection is broken after the
> implicit prepare, because the transaction manager might not
> recognize the implicitly prepared transaction, so it will stay in
> the system holding locks etc. until it's manually rolled back by
> the administrator.
>
> C. The second start call blocks, until the first transaction is
> committed, prepared, or rolled back.
>
> This might cause tricky deadlocks, depending on the threading model
> of the application server and the transaction manager.
>
> I experimented with some other DBMS' to find out how they handle this.
>
> Apache Derby (IBM Cloudscape):
> Supports XA only in embedded mode. Playing with temporary tables
> lead me to think that it does something similar to A. Connection
> management is probably quite lightweight in embedded mode. I didn't
> bother to look at the source code, though.
>
> DB2 (Type 4 driver):
> Does B, and suffers from the problems described above. "LIST
> INDOUBT TRANSACTIONS" shows the implicitly prepared transactions,
> suspend/resume doesn't work as it should.
>
> Oracle:
> The server natively supports having many active transactions in one
> connection.
>
> I tried to install Firebird and Sybase as well, but couldn't get
> them installed properly. Anyone want to test them, or some other DBMS?
>
> Which approach should we take?
>
> - Heikki
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to
> majordomo(at)postgresql(dot)org)
>
>


From: Dave Cramer <pg(at)fastcrypt(dot)com>
To: List <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: XA support
Date: 2005-06-29 20:43:41
Message-ID: E027840B-0C81-4C2A-8EC5-C2C7DBE03C00@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

What about the notion of being able to vote on whether to commit?
xaRes.prepare() ?

Do we have any support for this notion ?

Dave

On 29-Jun-05, at 3:49 PM, Heikki Linnakangas wrote:

> Now that we have support for two-phase commit in the backend, it's
> time to add XA support to the JDBC driver.
>
> The first issue we have to solve is the way we associate
> transactions with connections.
>
> Consider the following example:
>
> public void testMultiplex() throws Exception {
> Xid xid1 = new CustomXid(1);
> Xid xid2 = new CustomXid(2);
> Xid xid3 = new CustomXid(3);
>
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar1 SET foo =
> 'aa'");
> xaRes.end(xid1, XAResource.TMSUCCESS);
>
> xaRes.start(xid2, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar2 SET foo =
> 'bb'");
> xaRes.end(xid2, XAResource.TMSUCCESS);
>
> xaRes.start(xid3, XAResource.TMNOFLAGS);
> conn.createStatement().executeUpdate("UPDATE foobar3 SET foo =
> 'cc'");
> xaRes.end(xid3, XAResource.TMSUCCESS);
>
> xaRes.commit(xid1, true);
> xaRes.commit(xid2, true);
> xaRes.commit(xid3, true);
> }
>
> According to the JTA spec, this should be supported. One connection
> can be used to initiate a new transaction, without committing,
> preparing or rolling back the previous one.
>
> We don't have backend support for this kind of operation. A
> connection can be associated with only transaction at a time.
> Changing that behaviour would require a major overhaul of the way
> the backend handles transactions and connections, AFAICS.
>
> I can see three alternative ways to handle this in the driver:
>
> A. When the second transaction starts, a new physical connection is
> opened behind the scenes. The second transaction is associated with
> the new physical connection and the first transaction remains
> associated with the original connection.
>
> The application server is usually responsible for connection
> pooling, so opening new connnections behind the scenes will mess
> with the pool limits and possible prepared statement cache. We
> would have to do some kind of connection pooling ourselves,
> regardless of the application server pool.
>
> B. When the second transaction starts, the first transaction is
> prepared behind the scenes, freeing the connection for the new
> transaction.
>
> This makes it impossible to implement the transaction suspend/
> resume functionality, since the first transaction cannot be used to
> issue any more statements after the implicit prepare. It also
> imposes the additional overhead of two-phase commit for
> transactions that could otherwise use regular one-phase commit. It
> will also cause trouble if the connection is broken after the
> implicit prepare, because the transaction manager might not
> recognize the implicitly prepared transaction, so it will stay in
> the system holding locks etc. until it's manually rolled back by
> the administrator.
>
> C. The second start call blocks, until the first transaction is
> committed, prepared, or rolled back.
>
> This might cause tricky deadlocks, depending on the threading model
> of the application server and the transaction manager.
>
> I experimented with some other DBMS' to find out how they handle this.
>
> Apache Derby (IBM Cloudscape):
> Supports XA only in embedded mode. Playing with temporary tables
> lead me to think that it does something similar to A. Connection
> management is probably quite lightweight in embedded mode. I didn't
> bother to look at the source code, though.
>
> DB2 (Type 4 driver):
> Does B, and suffers from the problems described above. "LIST
> INDOUBT TRANSACTIONS" shows the implicitly prepared transactions,
> suspend/resume doesn't work as it should.
>
> Oracle:
> The server natively supports having many active transactions in one
> connection.
>
> I tried to install Firebird and Sybase as well, but couldn't get
> them installed properly. Anyone want to test them, or some other DBMS?
>
> Which approach should we take?
>
> - Heikki
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to
> majordomo(at)postgresql(dot)org)
>
>


From: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
To: Dave Cramer <pg(at)fastcrypt(dot)com>
Cc: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>, pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-29 20:52:11
Message-ID: 1120078331.8208.128.camel@state.g2switchworks.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Wed, 2005-06-29 at 15:27, Dave Cramer wrote:
> I see option A below as the lesser of three evils. Is it reasonable
> to believe that people using XA would
> know enough to allocate enough connections ?
>
> Optionally we could have two implementations and choose between A and B

If they've used it before with jdbc, yes. It's the way Oracle does it
too. Under Jboss you have a two to one ration of backend to frontend
connections. I.e. every application connection going through an XA
connector requires TWO backend connections.

IT might be worth putting a note in the jdbc docs though.


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-29 22:19:00
Message-ID: 42C31E54.20000@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Heikki Linnakangas wrote:

> B. When the second transaction starts, the first transaction is prepared
> behind the scenes, freeing the connection for the new transaction.

This is probably the way to go initially, since it's much simpler. It
should also deal with the more common uses of XA where you're just
coordinating 2 or more resources in an otherwise straightforward
begin-do stuff-commit sequence. We can get clever later :)

Related issues: supporting this case:

xaRes.start(xid1, XAResource.TMNOFLAGS);
stmt.executeUpdate("...");
xaRes.end(xid1, XAResource.TMSUSPEND);
// ...
xaRes.start(xid1, XAResource.TMRESUME);
stmt.executeUpdate("...");
xaRes.end(xid1, XAResource.TMSUCCESS);

and this one:

xaRes.start(xid1, XAResource.TMNOFLAGS);
stmt.executeUpdate("...");
xaRes.end(xid1, XAResource.TMSUCCESS);
// ...
xaRes.start(xid1, XAResource.TMJOIN);
stmt.executeUpdate("...");
xaRes.end(xid1, XAResource.TMSUCCESS);

and this one (yow!):

(thread 1):
xaRes.start(xid1, XAResource.TMNOFLAGS);
stmt.executeUpdate("...");

(thread 2):
xaRes.start(xid1, XAResource.TMJOIN);
stmt.executeUpdate("...");

-O


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Dave Cramer <davec(at)fastcrypt(dot)com>
Cc: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>, pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-29 22:25:13
Message-ID: 42C31FC9.3080102@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Dave Cramer wrote:
> What about the notion of being able to vote on whether to commit?
> xaRes.prepare() ?
>
> Do we have any support for this notion ?

That's what all the 2PC work in the backend has been in aid of..

-O


From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-30 18:15:54
Message-ID: Pine.OSF.4.61.0506302112310.45052@kosh.hut.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Wed, 29 Jun 2005, Scott Marlowe wrote:

> On Wed, 2005-06-29 at 15:27, Dave Cramer wrote:
>> I see option A below as the lesser of three evils. Is it reasonable
>> to believe that people using XA would
>> know enough to allocate enough connections ?
>>
>> Optionally we could have two implementations and choose between A and B
>
> If they've used it before with jdbc, yes. It's the way Oracle does it
> too. Under Jboss you have a two to one ration of backend to frontend
> connections. I.e. every application connection going through an XA
> connector requires TWO backend connections.

Do you mean that Oracle opens extra connections behind the scenes? That's
not what I saw happening. I ran ethereal while running the test case, and
it showed just one TCP connection and all SQL statements flowing through
that.

I'm no Oracle expert though. Maybe it opens multiple virtual connections
that are multiplexed into one TCP connection, I don't know.

That JBoss thing is quite interesting too. I wonder why they do that.

> IT might be worth putting a note in the jdbc docs though.

Definitely.

- Heikki


From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Oliver Jowett <oliver(at)opencloud(dot)com>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-30 18:37:16
Message-ID: Pine.OSF.4.61.0506302116360.45052@kosh.hut.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Thu, 30 Jun 2005, Oliver Jowett wrote:

> Heikki Linnakangas wrote:
>
>> B. When the second transaction starts, the first transaction is prepared
>> behind the scenes, freeing the connection for the new transaction.
>
> This is probably the way to go initially, since it's much simpler. It
> should also deal with the more common uses of XA where you're just
> coordinating 2 or more resources in an otherwise straightforward
> begin-do stuff-commit sequence. We can get clever later :)
>
> Related issues: supporting this case:
>
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> stmt.executeUpdate("...");
> xaRes.end(xid1, XAResource.TMSUSPEND);
> // ...
> xaRes.start(xid1, XAResource.TMRESUME);
> stmt.executeUpdate("...");
> xaRes.end(xid1, XAResource.TMSUCCESS);

This is essentially impossible with approach B, if the ... part uses the
connection for some other xid. Otherwise, should work.

> and this one:
>
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> stmt.executeUpdate("...");
> xaRes.end(xid1, XAResource.TMSUCCESS);
> // ...
> xaRes.start(xid1, XAResource.TMJOIN);
> stmt.executeUpdate("...");
> xaRes.end(xid1, XAResource.TMSUCCESS);

Practically the same as above, really.

> and this one (yow!):
>
> (thread 1):
> xaRes.start(xid1, XAResource.TMNOFLAGS);
> stmt.executeUpdate("...");
>
> (thread 2):
> xaRes.start(xid1, XAResource.TMJOIN);
> stmt.executeUpdate("...");

Note that the XA term "thread of control" actually means a connection in
JTA terms. It doesn't make any difference which java thread does work. See
JTA spec, section 3.4.3.

I'm leaning towards approach C myself, since it's the simplest to
implement and doesn't cause any unexpected prepares. Or possibly even
violating the spec and not allowing to start another transaction before
the previous one has been prepared. It depends on how the popular
application servers behave in real life.

- Heikki


From: Dave Cramer <davec(at)fastcrypt(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: List <pgsql-jdbc(at)postgresql(dot)org>
Subject: Re: XA support
Date: 2005-06-30 19:08:01
Message-ID: D90E9D45-AA91-4145-8E35-5D8A9010B3BD@fastcrypt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Heikki,

The folks at JONAS want to test the driver so I'd think they would
work with you on this.
Post this on the pgj2ee list.

Dave
On 30-Jun-05, at 2:37 PM, Heikki Linnakangas wrote:

> On Thu, 30 Jun 2005, Oliver Jowett wrote:
>
>
>> Heikki Linnakangas wrote:
>>
>>
>>> B. When the second transaction starts, the first transaction is
>>> prepared
>>> behind the scenes, freeing the connection for the new transaction.
>>>
>>
>> This is probably the way to go initially, since it's much simpler. It
>> should also deal with the more common uses of XA where you're just
>> coordinating 2 or more resources in an otherwise straightforward
>> begin-do stuff-commit sequence. We can get clever later :)
>>
>> Related issues: supporting this case:
>>
>> xaRes.start(xid1, XAResource.TMNOFLAGS);
>> stmt.executeUpdate("...");
>> xaRes.end(xid1, XAResource.TMSUSPEND);
>> // ...
>> xaRes.start(xid1, XAResource.TMRESUME);
>> stmt.executeUpdate("...");
>> xaRes.end(xid1, XAResource.TMSUCCESS);
>>
>
> This is essentially impossible with approach B, if the ... part
> uses the connection for some other xid. Otherwise, should work.
>
>
>> and this one:
>>
>> xaRes.start(xid1, XAResource.TMNOFLAGS);
>> stmt.executeUpdate("...");
>> xaRes.end(xid1, XAResource.TMSUCCESS);
>> // ...
>> xaRes.start(xid1, XAResource.TMJOIN);
>> stmt.executeUpdate("...");
>> xaRes.end(xid1, XAResource.TMSUCCESS);
>>
>
> Practically the same as above, really.
>
>
>> and this one (yow!):
>>
>> (thread 1):
>> xaRes.start(xid1, XAResource.TMNOFLAGS);
>> stmt.executeUpdate("...");
>>
>> (thread 2):
>> xaRes.start(xid1, XAResource.TMJOIN);
>> stmt.executeUpdate("...");
>>
>
> Note that the XA term "thread of control" actually means a
> connection in JTA terms. It doesn't make any difference which java
> thread does work. See JTA spec, section 3.4.3.
>
> I'm leaning towards approach C myself, since it's the simplest to
> implement and doesn't cause any unexpected prepares. Or possibly
> even violating the spec and not allowing to start another
> transaction before the previous one has been prepared. It depends
> on how the popular application servers behave in real life.
>
> - Heikki
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faq
>
>


From: peter royal <proyal(at)pace2020(dot)com>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-30 20:17:57
Message-ID: 6D580D22-AC78-453A-914A-A36168F995C3@pace2020.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Jun 30, 2005, at 2:37 PM, Heikki Linnakangas wrote:
> I'm leaning towards approach C myself, since it's the simplest to
> implement and doesn't cause any unexpected prepares. Or possibly
> even violating the spec and not allowing to start another
> transaction before the previous one has been prepared. It depends
> on how the popular application servers behave in real life.

'C' seems best to me also.

I'm using pg with a custom wrapper that fakes XA, and each
transaction gets its own physical connection from the pool. Depending
on how an appserver integrates connection pooling and their TM, it
might never be a problem.

Blocking shouldn't ever cause a deadlock, as the JTA timeout on the
transaction should kick in and forcibly rollback (this would happen
when used with JOTM, I can't vouch for other TM's). Could be some
nasty unexpected pauses though :)

A non-spec compliant switch would be nice too, as you suggest.
-pete

--
peter royal -> proyal(at)pace2020(dot)com


From: Oliver Jowett <oliver(at)opencloud(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-06-30 23:05:14
Message-ID: 42C47AAA.2010302@opencloud.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

Heikki Linnakangas wrote:

> This is essentially impossible with approach B, if the ... part uses the
> connection for some other xid. Otherwise, should work.

Right, I was thinking about implications for the other approaches.

> Note that the XA term "thread of control" actually means a connection in
> JTA terms. It doesn't make any difference which java thread does work.
> See JTA spec, section 3.4.3.

Ah, ok, that makes a lot more sense then :-)

> I'm leaning towards approach C myself [...]

Blocking seems really dangerous :( It seems quite likely that you could
deadlock against yourself..

> since it's the simplest to
> implement and doesn't cause any unexpected prepares.

Yeah, I thought some more about that and B is really bad from the
unexpected prepare angle. If we're preparing before the TM asks us to
(and therefore have transaction showing up as prepared in recovery) it
seems possible that a TM will incorrectly decide to commit those after
recovery.

> Or possibly even violating the spec and not allowing to start another transaction before the previous one has been prepared.

This actually sounds like the best thing now as it produces obvious,
easy-to-diagnose errors when you do something that the driver doesn't
yet support.

-O


From: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
To: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Cc: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: XA support
Date: 2005-07-01 17:15:49
Message-ID: 1120238149.8208.139.camel@state.g2switchworks.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-jdbc

On Thu, 2005-06-30 at 13:15, Heikki Linnakangas wrote:
> On Wed, 29 Jun 2005, Scott Marlowe wrote:
>
> > On Wed, 2005-06-29 at 15:27, Dave Cramer wrote:
> >> I see option A below as the lesser of three evils. Is it reasonable
> >> to believe that people using XA would
> >> know enough to allocate enough connections ?
> >>
> >> Optionally we could have two implementations and choose between A and B
> >
> > If they've used it before with jdbc, yes. It's the way Oracle does it
> > too. Under Jboss you have a two to one ration of backend to frontend
> > connections. I.e. every application connection going through an XA
> > connector requires TWO backend connections.
>
> Do you mean that Oracle opens extra connections behind the scenes? That's
> not what I saw happening. I ran ethereal while running the test case, and
> it showed just one TCP connection and all SQL statements flowing through
> that.

No, our jdbc / jboss connection pooling is doing that. It needs two
connections to the db for every XA transaction.