h2database / h2database/h2database

Timeout trying to lock table "SYS"

Open
#2,145 0 comments 0 reactions 0 assignees View on GitHub

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());
    }
  }
}

Test.java.gz

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.