提交 54e3a90a authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #382 from vitalus/master

Recover for "page store" H2   breaks LOBs consistency
...@@ -456,25 +456,31 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -456,25 +456,31 @@ public class LobStorageBackend implements LobStorageInterface {
synchronized (conn.getSession()) { synchronized (conn.getSession()) {
try { try {
init(); init();
long lobId = getNextLobId(); ValueLobDb v = null;
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " + if(!old.isRecoveryReference()){
"SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?"; long lobId = getNextLobId();
PreparedStatement prep = prepare(sql); String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " +
prep.setLong(1, lobId); "SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?";
prep.setLong(2, oldLobId); PreparedStatement prep = prepare(sql);
prep.executeUpdate(); prep.setLong(1, lobId);
reuse(sql, prep); prep.setLong(2, oldLobId);
prep.executeUpdate();
sql = "INSERT INTO " + LOBS + "(ID, BYTE_COUNT, TABLE) " + reuse(sql, prep);
"SELECT ?, BYTE_COUNT, ? FROM " + LOBS + " WHERE ID = ?";
prep = prepare(sql); sql = "INSERT INTO " + LOBS + "(ID, BYTE_COUNT, TABLE) " +
prep.setLong(1, lobId); "SELECT ?, BYTE_COUNT, ? FROM " + LOBS + " WHERE ID = ?";
prep.setLong(2, tableId); prep = prepare(sql);
prep.setLong(3, oldLobId); prep.setLong(1, lobId);
prep.executeUpdate(); prep.setLong(2, tableId);
reuse(sql, prep); prep.setLong(3, oldLobId);
prep.executeUpdate();
ValueLobDb v = ValueLobDb.create(type, database, tableId, lobId, null, length); reuse(sql, prep);
v = ValueLobDb.create(type, database, tableId, lobId, null, length);
}else{
//Recovery process, no need to copy LOB using normal infrastructure
v = ValueLobDb.create(type, database, tableId, oldLobId, null, length);
}
return v; return v;
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
......
...@@ -218,8 +218,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -218,8 +218,10 @@ public class Recover extends Tool implements DataHandler {
long precision) { long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h); verifyPageStore(h);
return ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP, ValueLobDb lob = ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision); lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
} }
private static void verifyPageStore(DataHandler h) { private static void verifyPageStore(DataHandler h) {
...@@ -237,8 +239,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -237,8 +239,10 @@ public class Recover extends Tool implements DataHandler {
long precision) { long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h); verifyPageStore(h);
return ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP, ValueLobDb lob = ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision); lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
} }
/** /**
......
...@@ -54,6 +54,11 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -54,6 +54,11 @@ public class ValueLobDb extends Value implements Value.ValueClob,
private final FileStore tempFile; private final FileStore tempFile;
private int tableId; private int tableId;
private int hash; private int hash;
//Arbonaut: 13.07.2016
// Fix for recovery tool.
private boolean isRecoveryReference = false;
private ValueLobDb(int type, DataHandler handler, int tableId, long lobId, private ValueLobDb(int type, DataHandler handler, int tableId, long lobId,
byte[] hmac, long precision) { byte[] hmac, long precision) {
...@@ -664,4 +669,12 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -664,4 +669,12 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return new ValueLobDb(type, small, precision); return new ValueLobDb(type, small, precision);
} }
public void setRecoveryReference(boolean isRecoveryReference) {
this.isRecoveryReference = isRecoveryReference;
}
public boolean isRecoveryReference() {
return isRecoveryReference;
}
} }
...@@ -114,6 +114,7 @@ import org.h2.test.mvcc.TestMvcc3; ...@@ -114,6 +114,7 @@ import org.h2.test.mvcc.TestMvcc3;
import org.h2.test.mvcc.TestMvcc4; import org.h2.test.mvcc.TestMvcc4;
import org.h2.test.mvcc.TestMvccMultiThreaded; import org.h2.test.mvcc.TestMvccMultiThreaded;
import org.h2.test.poweroff.TestReorderWrites; import org.h2.test.poweroff.TestReorderWrites;
import org.h2.test.recover.RecoverLobTest;
import org.h2.test.rowlock.TestRowLocks; import org.h2.test.rowlock.TestRowLocks;
import org.h2.test.server.TestAutoServer; import org.h2.test.server.TestAutoServer;
import org.h2.test.server.TestInit; import org.h2.test.server.TestInit;
...@@ -858,6 +859,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -858,6 +859,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestReader()); addTest(new TestReader());
addTest(new TestRecovery()); addTest(new TestRecovery());
addTest(new TestScriptReader()); addTest(new TestScriptReader());
addTest(new RecoverLobTest());
addTest(createTest("org.h2.test.unit.TestServlet")); addTest(createTest("org.h2.test.unit.TestServlet"));
addTest(new TestSecurity()); addTest(new TestSecurity());
addTest(new TestShell()); addTest(new TestShell());
...@@ -872,6 +874,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -872,6 +874,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestValue()); addTest(new TestValue());
addTest(new TestValueHashMap()); addTest(new TestValueHashMap());
addTest(new TestWeb()); addTest(new TestWeb());
runAddedTests(); runAddedTests();
......
package org.h2.test.recover;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Recover;
public class RecoverLobTest extends TestBase {
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public TestBase init() throws Exception {
TestBase tb = super.init();
config.mvStore=false;
return tb;
}
@Override
public void test() throws Exception {
testRecoverClob();
}
public void testRecoverClob() throws Exception {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table test(id int, data clob)");
stat.execute("insert into test values(1, space(10000))");
stat.execute("insert into test values(2, space(20000))");
stat.execute("insert into test values(3, space(30000))");
stat.execute("insert into test values(4, space(40000))");
stat.execute("insert into test values(5, space(50000))");
stat.execute("insert into test values(6, space(60000))");
stat.execute("insert into test values(7, space(70000))");
stat.execute("insert into test values(8, space(80000))");
conn.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery");
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
conn = getConnection(
"recovery;init=runscript from '" +
getBaseDir() + "/recovery.h2.sql'");
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from test");
while(rs.next()){
int id = rs.getInt(1);
String data = rs.getString(2);
assertTrue(data != null);
assertTrue(data.length() == 10000 * id);
}
rs.close();
conn.close();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论