According to the error message, you are using H2 version 1.2.134
(error code 90131-134), but I don't think this is the problem. I think
it's a deadlock. The easiest way to reproduce the problem is using two
connections that try to update the same rows in a different order:
Class.forName("org.h2.Driver");
String dir = "~/data/h2database/h2/data";
DeleteDbFiles.execute(dir, null, true);
String url = "jdbc:h2:" + dir + "/test;MVCC=TRUE";
Connection conn1 = DriverManager.getConnection(url);
Statement stat1 = conn1.createStatement();
stat1.execute("create table test(id int primary key, data varchar)");
stat1.execute("insert into test values(1, 'A'), (2, 'B')");
Connection conn2 = DriverManager.getConnection(url);
Statement stat2 = conn2.createStatement();
conn1.setAutoCommit(false);
conn2.setAutoCommit(false);
stat1.execute("update test set data='a' where id=1");
stat2.execute("update test set data='b' where id=2");
stat1.execute("update test set data='b' where id=2");
stat2.execute("update test set data='a' where id=1");
conn1.close();
conn2.close();
or
Class.forName("org.h2.Driver");
String dir = "~/data/h2database/h2/data";
DeleteDbFiles.execute(dir, null, true);
String url = "jdbc:h2:" + dir + "/test;MVCC=TRUE";
Connection conn1 = DriverManager.getConnection(url);
final Statement stat1 = conn1.createStatement();
stat1.execute("create table test(id int primary key, data varchar)");
stat1.execute("insert into test values(1, 'A'), (2, 'B')");
Connection conn2 = DriverManager.getConnection(url);
Statement stat2 = conn2.createStatement();
conn1.setAutoCommit(false);
conn2.setAutoCommit(false);
stat1.execute("update test set data='a' where id=1");
stat2.execute("update test set data='b' where id=2");
new Thread() {
public void run() {
try {
stat1.execute("update test set data='b' where id=2");
} catch (SQLException e) {
e.printStackTrace();
}
}
}.start();
stat2.execute("update test set data='a' where id=1");
conn1.close();
conn2.close();
Most likely this is what is happening here. It is also known as the
dining philosophers problem:
http://en.wikipedia.org/wiki/Dining_philosophers_problem
One solution is to automatically re-try the transaction, another
solution is to always lock the rows in the same order.
When using MVCC, H2 doesn't give a detailed error message about the
cause of the deadlock. When not using MVCC, the error message will be
more detailed, but only when using multiple tables:
Class.forName("org.h2.Driver");
String dir = "~/data/h2database/h2/data";
DeleteDbFiles.execute(dir, null, true);
String url = "jdbc:h2:" + dir + "/test";
Connection conn1 = DriverManager.getConnection(url);
final Statement stat1 = conn1.createStatement();
stat1.execute("create table a(id int)");
stat1.execute("create table b(id int)");
Connection conn2 = DriverManager.getConnection(url);
Statement stat2 = conn2.createStatement();
conn1.setAutoCommit(false);
conn2.setAutoCommit(false);
stat1.execute("insert into a values(1)");
stat2.execute("insert into b values(1)");
new Thread() {
public void run() {
try {
stat1.execute("insert into b values(2)");
} catch (SQLException e) {
e.printStackTrace();
}
}
}.start();
stat2.execute("insert into a values(2)");
conn1.close();
conn2.close();
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Deadlock detected.
The current transaction was rolled back. Details: "
Session #2 (user: ) is waiting to lock PUBLIC.B while locking PUBLIC.A
(exclusive).
Session #3 (user: ) is waiting to lock PUBLIC.A while locking PUBLIC.B
(exclusive).";
SQL statement: insert into a values(2) [40001-144]
Regards,
Thomas
To unsubscribe from this group and stop receiving emails from it, send an email to h2-database...@googlegroups.com.--
You received this message because you are subscribed to the Google Groups "H2 Database" group.
To post to this group, send email to h2-da...@googlegroups.com.
Visit this group at http://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.