Manwithoutname
Grünschnabel
Hallo Leute,
ich beschäftige mich im Moment mit verteilten Transaktionen.
Das heisst Schreiboperationen auf unterschiedlichen Datenbanken und unterschiedlichen Datenbanksystemen (PostgreSQL und MySQL).
Mein Problem besteht zur Zeit darin, dass das 2PC Protokoll nicht funktioniert, weil die Methode "prepare(Xid)" immer nur OKs zurück gibt.
Ich benutze die Liburary "org.enhydra.jdbc.standard.*" (xapool).
Entweder stimmt was mit meinem Quellcode nicht oder die Methode prepare ist nicht DBSunabhängig. Das commit und rollback funktioniert innerhalb einer Transaktion einwandfrei, nur im Fehlerfall erkennt die prepare-Methode nichts
Zum Beispiel wenn ein Integer erwartet wird und ich ein String übergebe, kommt zwar eine Exception, das commit wird aber trotzdem ausgeführt.
Kennt jemand noch andere freie APIs, die meinen Anforderungen genügen.
Hier mein Code:
// postgresql treiber
String driverClass = "org.postgresql.Driver";
// URLs der Datenbanken
String url1 = "jdbcostgresql://localhost/db1";
String url2 = "jdbcostgresql://localhost/db2";
//SQL-OPs
String query1 = "update tab1 set lastname='m1' where id=5;";
String query2 = "update tab1 set gehalt='sa' where id=1000;";
try {
Class.forName(driverClass);
}
catch(ClassNotFoundException exc) {
System.out.println("ClassNotFoundException" + exc.getMessage());
System.exit(1);
}
// öffnen der physischen Verbindung zum Datenbanksystem
StandardXADataSource ds1 = new StandardXADataSource();
StandardXADataSource ds2 = new StandardXADataSource();
StandardXAConnection xacon1 = null;
StandardXAConnection xacon2 = null;
XAResource xares1 = null;
XAResource xares2 = null;
Xid xid1 = null;
Xid xid2 = null;
Statement stmt1 = null;
Statement stmt2 = null;
try {
// setzen der URL der Datenbank
ds1.setUrl(url1);
ds2.setUrl(url2);
// nochmaliges setzen des Treibers für die XAConnection
ds1.setDriverName(driverClass);
ds2.setDriverName(driverClass);
xacon1 = (StandardXAConnection)ds1.getXAConnection("postgres", "postgres");
xacon2 = StandardXAConnection)ds2.getXAConnection("postgres", "postgres");
Connection c1 = xacon1.getConnection();
Connection c2 = xacon2.getConnection();
c1.setAutoCommit(false);
c2.setAutoCommit(false);
// die Transaktionsressourcen werden ermittelt
xares1 = xacon1.getXAResource();
xares2 = xacon2.getXAResource();
// erzeugen einer globalen Transaktions-ID
MXid mxid = new MXid();
xid1 = mxid.createXid(1);
xid2 = mxid.createXid(2);
// die Transaktionen werden gestartet
xares1.start(xid1, XAResource.TMNOFLAGS);
xares2.start(xid2, XAResource.TMNOFLAGS);
// Statement-Instanzen werden erzeugt
stmt1 = c1.createStatement();
stmt2 = c2.createStatement();
// Datenbankoperationen werden ausgeführt
stmt1.executeUpdate(query1);
stmt2.executeUpdate(query2);
}
catch(SQLException exc) {
System.out.println("sql: " + exc.toString());
}
catch(XAException xaexc) {
System.out.println(xaexc.toString());
}
try{
// Transaktionen werden beendet
xares1.end(xid1, XAResource.TMSUCCESS);
xares2.end(xid2, XAResource.TMSUCCESS);
// "Prepare" wird zurückgegeben
int prep1 = xares1.prepare(xid1);
int prep2 = xares2.prepare(xid2);
System.out.println("1: " + prep1 + "\n2: " + prep2);
//2PC-Protokoll Abfrage: alle ok => commit sonst => rollback
if(prep1 == XAResource.XA_OK && prep2 == XAResource.XA_OK) {
System.out.println("Hat geklappt !");
xares1.commit(xid1, true);
xares2.commit(xid2, true);
System.out.println();
}
else {
System.out.println("Hat nicht geklappt !");
xares1.rollback(xid1);
xares2.rollback(xid2);
}
}
catch(XAException xaexc) {
System.out.println(xaexc.toString());
}
ich beschäftige mich im Moment mit verteilten Transaktionen.
Das heisst Schreiboperationen auf unterschiedlichen Datenbanken und unterschiedlichen Datenbanksystemen (PostgreSQL und MySQL).
Mein Problem besteht zur Zeit darin, dass das 2PC Protokoll nicht funktioniert, weil die Methode "prepare(Xid)" immer nur OKs zurück gibt.
Ich benutze die Liburary "org.enhydra.jdbc.standard.*" (xapool).
Entweder stimmt was mit meinem Quellcode nicht oder die Methode prepare ist nicht DBSunabhängig. Das commit und rollback funktioniert innerhalb einer Transaktion einwandfrei, nur im Fehlerfall erkennt die prepare-Methode nichts
Zum Beispiel wenn ein Integer erwartet wird und ich ein String übergebe, kommt zwar eine Exception, das commit wird aber trotzdem ausgeführt.
Kennt jemand noch andere freie APIs, die meinen Anforderungen genügen.
Hier mein Code:
// postgresql treiber
String driverClass = "org.postgresql.Driver";
// URLs der Datenbanken
String url1 = "jdbcostgresql://localhost/db1";
String url2 = "jdbcostgresql://localhost/db2";
//SQL-OPs
String query1 = "update tab1 set lastname='m1' where id=5;";
String query2 = "update tab1 set gehalt='sa' where id=1000;";
try {
Class.forName(driverClass);
}
catch(ClassNotFoundException exc) {
System.out.println("ClassNotFoundException" + exc.getMessage());
System.exit(1);
}
// öffnen der physischen Verbindung zum Datenbanksystem
StandardXADataSource ds1 = new StandardXADataSource();
StandardXADataSource ds2 = new StandardXADataSource();
StandardXAConnection xacon1 = null;
StandardXAConnection xacon2 = null;
XAResource xares1 = null;
XAResource xares2 = null;
Xid xid1 = null;
Xid xid2 = null;
Statement stmt1 = null;
Statement stmt2 = null;
try {
// setzen der URL der Datenbank
ds1.setUrl(url1);
ds2.setUrl(url2);
// nochmaliges setzen des Treibers für die XAConnection
ds1.setDriverName(driverClass);
ds2.setDriverName(driverClass);
xacon1 = (StandardXAConnection)ds1.getXAConnection("postgres", "postgres");
xacon2 = StandardXAConnection)ds2.getXAConnection("postgres", "postgres");
Connection c1 = xacon1.getConnection();
Connection c2 = xacon2.getConnection();
c1.setAutoCommit(false);
c2.setAutoCommit(false);
// die Transaktionsressourcen werden ermittelt
xares1 = xacon1.getXAResource();
xares2 = xacon2.getXAResource();
// erzeugen einer globalen Transaktions-ID
MXid mxid = new MXid();
xid1 = mxid.createXid(1);
xid2 = mxid.createXid(2);
// die Transaktionen werden gestartet
xares1.start(xid1, XAResource.TMNOFLAGS);
xares2.start(xid2, XAResource.TMNOFLAGS);
// Statement-Instanzen werden erzeugt
stmt1 = c1.createStatement();
stmt2 = c2.createStatement();
// Datenbankoperationen werden ausgeführt
stmt1.executeUpdate(query1);
stmt2.executeUpdate(query2);
}
catch(SQLException exc) {
System.out.println("sql: " + exc.toString());
}
catch(XAException xaexc) {
System.out.println(xaexc.toString());
}
try{
// Transaktionen werden beendet
xares1.end(xid1, XAResource.TMSUCCESS);
xares2.end(xid2, XAResource.TMSUCCESS);
// "Prepare" wird zurückgegeben
int prep1 = xares1.prepare(xid1);
int prep2 = xares2.prepare(xid2);
System.out.println("1: " + prep1 + "\n2: " + prep2);
//2PC-Protokoll Abfrage: alle ok => commit sonst => rollback
if(prep1 == XAResource.XA_OK && prep2 == XAResource.XA_OK) {
System.out.println("Hat geklappt !");
xares1.commit(xid1, true);
xares2.commit(xid2, true);
System.out.println();
}
else {
System.out.println("Hat nicht geklappt !");
xares1.rollback(xid1);
xares2.rollback(xid2);
}
}
catch(XAException xaexc) {
System.out.println(xaexc.toString());
}
Zuletzt bearbeitet: