Nice work on creating the test case!
Interesting, this is a genuine bug somewhere in the LOB code, and it
manifests even with MVCC=false.
The only short-term fix I can see is to set your transaction isolation
to TRANSACTION_REPEATABLE_READ.
Thomas, I further reduced the test-case, and I'm including it here.
Note that (for me) it did not fail every single time. I normally let it
run for about 15 seconds, and then terminate and try again.
I get a failure rate of about 50%.
package test.TestCase1;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestCase1 {
private static final String URL =
"jdbc:h2:db/test01;MVCC=TRUE;MULTI_THREADED=0;LOCK_MODE=3;LOCK_TIMEOUT=20000;";
private static final String LONG_STRING =
"1111111111111111111111111111111111111111111111111111111111111111111"
+
"1111111111111111111111111111111111111111111111111111111111111111111".replace("1",
"1234567890");
public TestCase1() {
}
/**
* Test case start. After about 10s the exceptions will go to the
stdout.
*/
public void start() throws Exception {
final Connection conn = connect();
// Create initial schema (will fail on the second time run
unless the db
// file is deleted)
Statement st = null;
try {
st = conn.createStatement();
st.executeUpdate("CREATE TABLE IF NOT EXISTS TestInstance
(Id BIGINT generated by default as identity, "
+ "Description TEXT NOT NULL, Dummy VARCHAR(255)
NOT NULL, PRIMARY KEY (Id));");
conn.commit();
} catch (Exception e) {
conn.rollback();
e.printStackTrace();
}
// Add initial row
PreparedStatement pst = conn.prepareStatement("INSERT INTO
TestInstance (Description, Dummy) VALUES (?, ?)");
pst.setString(1, LONG_STRING);
pst.setString(2, "dummy");
pst.execute();
conn.commit();
if (st != null) {
st.close();
}
// Start the updater thread
new Thread("updater") {
@Override
public void run() {
try {
doUpdates(connect());
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
// Do the reading in the current thread
doReads(conn);
if (!conn.isClosed()) {
conn.close();
}
System.out.println("Closed the database");
}
/**
* Reads all rows from the target table.
*/
private void doReads(Connection conn) throws Exception {
while (true) {
try {
final Statement st = conn.createStatement();
final ResultSet rs = st.executeQuery("SELECT * FROM
TestInstance");
while (rs.next()) {
rs.getInt(1);
rs.getString(2);
rs.getString(3);
}
rs.close();
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn.commit();
Thread.sleep(50);
}
}
/**
* Reads the 1st row & then updates it.
*/
private void doUpdates(Connection conn) throws Exception {
final PreparedStatement pst = conn
.prepareStatement("UPDATE TestInstance set
Description=?, Dummy=? WHERE id=1");
int i = 0;
while (true) {
// Read the instance
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM TestInstance
WHERE Id=1");
while (rs.next()) {
rs.getInt(1);
rs.getString(2);
rs.getString(3);
}
rs.close();
st.close();
// Update the instance
pst.setString(1, LONG_STRING + i++);
pst.setString(2, "Dummy");
pst.execute();
conn.commit();
Thread.sleep(50);
}
}
/**
* Connects to the db.
*/
private Connection connect() throws Exception {
Class.forName("org.h2.Driver");
System.out.println("Connecting to database");
Connection conn = DriverManager.getConnection(URL);
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
return conn;
}
public static void main(String[] args) throws Exception {
new File("db/test01.h2.db").delete();
new File("db/test01.lock.db").delete();
new File("db/test01.trace.db").delete();
TestCase1 tc1 = new TestCase1();
tc1.start();
}
}
--
You received this message because you are subscribed to the Google Groups "H2
Database" group.
To post to this group, send email to h2-database@googlegroups.com.
To unsubscribe from this group, send email to
h2-database+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/h2-database?hl=en.