在嵌入模式下使用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的行。
我的第一个倾向是我正在处理某种锁定问题。我尝试了以下(结果没有变化):
关于如何识别正在发生的事情的正确方向的任何指示?我最后插入了:
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
答案 0 :(得分:2)
h2人已经明显解决了这个问题。
https://code.google.com/p/h2database/issues/detail?id=566
要么需要从版本控制中获取代码,要么等待下一个版本构建。谢谢托马斯。