h2database / h2database/h2database
Timeout trying to lock table "SYS"
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 4.6k
- Forks
- 1.3k
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 9
Description
I am using h2 as the basis of a "data-preparation"-tool, i.e. with a focus on creating/editing/dropping tables. I am aware that h2 (mvstore) may not have been developed for such an application.
My problem: I run into an exception on multi-threaded table editing. The attached 72-line java programm starts two threads that repeatedly create/edit/drop each of them one table. After a few cycles there seems to be a deadlock that seems to be resolved after 2000 ms, one of the two threads dies (in my code), the other continues. Here is a typical output on my computer (a simple core-i5 with 8Gbyte).
Started two threads 'AAA' and 'BBB'
thread AAA required 2021 ms at step: 39
thread BBB stopped with exception at step: 37
msg: Timeout trying to lock table "SYS"; SQL statement:
alter table BBB add column if not exists X BIGINT as -1L [50200-199]
thread: AAA finished OK
Is there anything I could change to prevent this error ?
regards, rafel
package test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.h2.tools.Server;
public class Test {
static Connection connection;
static ExecutorService threadPool = Executors.newCachedThreadPool();
public static void main(String[] args) {
try {
// start h2
String dbURL = "jdbc:h2:./testMVCC;MVCC=true;AUTO_SERVER=TRUE;ALIAS_COLUMN_NAME=TRUE";
Server.createTcpServer().start();
// create two threads
for (String x : new String[] {"AAA", "BBB"}) {
final String tName = x;
threadPool.submit(new Runnable() {
Connection connection = DriverManager.getConnection(dbURL);
void execute(String sql) throws SQLException {
connection.createStatement().execute(sql);
}
@Override
public void run() {
int step=0;
try {
// repeat three statements: create/edit/drop a table
for (step=0; step<1000; step++) {
Long start = System.currentTimeMillis();
execute("create table if not exists " + tName + " as select 7");
execute("alter table " + tName + " add column if not exists X BIGINT as -1L");
execute("drop table if exists " + tName );
Long time = System.currentTimeMillis() - start;
if (time > 1000 ) {
System.out.println("\nthread " + tName + " required "
+ (System.currentTimeMillis() - start) + " ms at step: " + step);
}
}
System.out.println("\nthread: " + tName + " finished OK");
} catch (Exception e) {
System.out.println("\nthread " + tName + " stopped with exception at step: " + step
+ "\n\tmsg: " + e.getLocalizedMessage());
}
}
});
}
System.out.println("Started two threads 'AAA' and 'BBB'");
} catch (SQLException e) {
System.out.println(e.getLocalizedMessage());
}
}
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached Test.java reproducer and run its JDBC URL with two concurrent threads performing create, alter, and drop operations. Inspect the timeout while both threads contend for the SYS table lock, then trace the corresponding H2 database locking path. Done means the cause is identified and a verified prevention or fix is established for this concurrent workload.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100