h2指数腐败?使用runscript加载的嵌入式数据库具有“不可见”行

时间:2014-06-17 15:35:55

标签: h2

在嵌入模式下使用h2,我正在从先前由h2使用SCRIPT命令生成的脚本备份中恢复内存数据库。

我使用此网址:

jdbc:h2:mem:main

我这样做:

FileReader script = new FileReader("db.sql");
RunScript.execute(conn,script);
根据文档,

应该与此SQL类似:

RUNSCRIPT FROM 'db.sql'

而且,在我的应用程序中,他们执行相同的操作。但是,如果我使用h2.bat使用Web控制台运行负载,我会得到不同的结果。

在我的应用程序中加载了这些数据之后,我知道有些行已加载但我无法通过查询访问这些行。这些查询证明了这一点:

select count(*) from MY_TABLE yields 96576
select count(*) from MY_TABLE where ID <> 3238396 yields 96575
select count(*) from MY_TABLE where ID = 3238396 yields 0

加载Web控制台并使用相同的RUNSCRIPT命令和文件加载会生成一个数据库,其中可以找到具有该ID的行。

我的第一个倾向是我正在处理某种锁定问题。我尝试了以下(结果没有变化):

  1. 在RunScript.execute()
  2. 之后手动发出conn.commit()
  3. 追加; LOCK_MODE = 3,LOCK_MODE = 0到我的网址
  4. 关于如何识别正在发生的事情的正确方向的任何指示?我最后插入了:

    Server.createWebServer("-trace","-webPort","9083").start()
    

    这样我就可以通过Web控制台运行这些查询,以便检查通过JDBC返回的内容。问题在我的应用中始终如一,并且始终不会通过Web控制台发生。所以必须要有一些工作。

    表模式不是异国情调。这是

    中的架构列
    select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME='MY_TABLE'
    
    CREATE MEMORY TABLE PUBLIC.MY_TABLE(
       ID INTEGER SELECTIVITY 100,
       P_ID INTEGER SELECTIVITY 4,
       TYPE VARCHAR(10) SELECTIVITY 1,
       P_ORDER DECIMAL(8, 0) SELECTIVITY 11,
       E_GROUP INTEGER SELECTIVITY 1,
       P_USAGE VARCHAR(16) SELECTIVITY 1
    )
    

    任何正确方向的推动都会非常感激。

    修改

    因此,在运行RunScript命令加载数据库之后,似乎数据库已经以某种方式损坏。当我试图调试以查明发生了什么时,我尝试执行以下操作:

    delete from MY_TABLE where ID <> 3238396
    

    我最终得到了:

    Row not found when trying to delete from index "PUBLIC.MY_TABLE_IX1: 95326", SQL statement:
    delete from MY_TABLE where ID <> 3238396 [90112-178] 90112/90112 (Help)
    

    然后我尝试从上下文中删除并重新创建所有索引,但它对整体问题没有影响。

    帮助!

    编辑2

    更多信息:由于创建索引而出现问题。 (我相信我在h2中发现了一个错误,我正在努力创建一个可以重现它的小例子)。如果您拥有正确的数据集,下面的简单代码将重现该问题。

    public static void main(String[] args)
    {
          try
          {
                 final String DB_H2URL = "jdbc:h2:mem:main;LOCK_MODE=3";
                 Class.forName("org.h2.Driver");
                 Connection c = DriverManager.getConnection(DB_H2URL, "sa", "");
                 FileReader script = new FileReader("db.sql");
                 RunScript.execute(c,script);
                 script.close();
                 Statement st = c.createStatement();
                 ResultSet rs = st.executeQuery("select count(*) from MY_TABLE where P_ID = 3238396");
                 rs.next();
                 if(rs.getLong(1) == 0)
                       System.err.println("It happened");
                 else
                       System.err.println("It didn't happen");
          } catch (Throwable e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
          }
    }
    

    我已将db.sql脚本减少到大约5000行,但仍然会发生。当我试图去2500行时,它停止了发生。如果我删除db.sql的最后一行(这是索引创建),问题也将停止发生。最后一行是这样的:

    CREATE INDEX PUBLIC.MY_TABLE_IX1 ON PUBLIC.MY_TABLE(P_ID);
    

    但数据是这方面的重要参与者。它似乎只是一行而且索引以某种方式使它无法访问。

    编辑3

    我已经确定了要重现的最小数据示例。我将表格架构拆分为一列,我发现该列中的值似乎并不重要 - 只是行数。以下是通过SCRIPT命令生成的db.sql的内容(用明显的东西剪掉):

    ;            
    CREATE USER IF NOT EXISTS SA SALT '8eed806dbbd1ea59' HASH '6d55cf715c56f4ca392aca7389da216a97ae8c9785de5d071b49de5436b0c003' ADMIN;          
    CREATE MEMORY TABLE PUBLIC.MY_TABLE(
        P_ID INTEGER SELECTIVITY 100
    );   
    -- 5132 +/- SELECT COUNT(*) FROM PUBLIC.MY_TABLE;            
    INSERT INTO PUBLIC.MY_TABLE(P_ID) VALUES
    (1),
    (2),
    (3),
    ...  snipped you obviously have breaks in the bulk insert here ...
    (5143),
    (3238396);    
    CREATE INDEX PUBLIC.MY_TABLE_IX1 ON PUBLIC.MY_TABLE(P_ID);
    

    但这会重现问题。 [请注意,每次有大量插入行时,我的编号会跳过一个数字。所以确实有5132行,但是你看到5143从MY_TABLE中选择计数(*)得到5132]。此外,我似乎能够通过以下方式直接在WebConsole中重新创建问题:

    drop table MY_TABLE
    runscript from 'db.sql'
    select count(*) from MY_TABLE where P_ID = 3238396
    

    如果你知道在那里有一行,那么当你从选择中得到0时,你已经重新创建了这个问题。

    奇怪的是,我似乎能够做到

    select * from MY_TABLE order by P_ID desc
    

    我可以看到这一行。但直接去排:

    select * from MY_TABLE where P_ID = 3238396
    

    一无所获。

    我刚才意识到我应该注意到我正在使用 h2-1.4.178.jar

1 个答案:

答案 0 :(得分:2)

h2人已经明显解决了这个问题。

https://code.google.com/p/h2database/issues/detail?id=566

要么需要从版本控制中获取代码,要么等待下一个版本构建。谢谢托马斯。