提交 d7b1bf4e authored 作者: noelgrandin's avatar noelgrandin

Session-temporary LOB's could sometimes accumulate, increasing the size of the…

Session-temporary LOB's could sometimes accumulate, increasing the size of the DB file until shutdown.
Now they are cleared out at every commit.
上级 7a1a2b68
......@@ -47,6 +47,8 @@ Change Log
</li><li>When the H2 parser fails to parse a SQL statement, throw a more specific exception that
contains extra information to make it possible for smart editors to do autocomplete. Patch from Nicolas Fortin.
</li><li>Fix DROP ALL OBJECTS and DROP SCHEMA in the presence of tables with computed column dependencies.
</li><li>Session-temporary LOB's could sometimes accumulate, increasing the size of the DB file until shutdown.
Now they are cleared out at every commit.
</li></ul>
<h2>Version 1.3.173 (2013-07-28)</h2>
......
......@@ -111,6 +111,7 @@ public class Session extends SessionWithState {
private final int queryCacheSize;
private SmallLRUCache<String, Command> queryCache;
private long modificationMetaID = -1;
private ArrayList<Value> temporaryLobs;
private Transaction transaction;
private long startStatement = -1;
......@@ -475,6 +476,14 @@ public class Session extends SessionWithState {
// (create/drop table and so on)
database.commit(this);
}
if (temporaryLobs != null) {
for (Value v : temporaryLobs) {
if (!v.isLinked()) {
v.close();
}
}
temporaryLobs.clear();
}
if (undoLog.size() > 0) {
// commit the rows when using MVCC
if (database.isMultiVersion()) {
......@@ -1381,6 +1390,13 @@ public class Session extends SessionWithState {
startStatement = -1;
closeTemporaryResults();
}
public void addTemporaryLob(Value v) {
if (temporaryLobs == null) {
temporaryLobs = new ArrayList<Value>();
}
temporaryLobs.add(v);
}
/**
* Represents a savepoint (a position in a transaction to where one can roll
......
......@@ -10,6 +10,7 @@ import java.io.Closeable;
import org.h2.command.CommandInterface;
import org.h2.message.Trace;
import org.h2.store.DataHandler;
import org.h2.value.Value;
/**
* A local or remote session. A session represents a database connection.
......@@ -116,5 +117,7 @@ public interface SessionInterface extends Closeable {
* @param autoCommit the new value
*/
void setAutoCommit(boolean autoCommit);
void addTemporaryLob(Value v);
}
......@@ -805,4 +805,9 @@ public class SessionRemote extends SessionWithState implements DataHandler {
}
return javaObjectSerializerFQN;
}
@Override
public void addTemporaryLob(Value v) {
// do nothing
}
}
......@@ -1493,6 +1493,7 @@ public class JdbcConnection extends TraceObject implements Connection {
Value v = session.getDataHandler().getLobStorage().createClob(
new InputStreamReader(
new ByteArrayInputStream(Utils.EMPTY_BYTES)), 0);
session.addTemporaryLob(v);
return new JdbcClob(this, v, id);
} finally {
afterWriting();
......@@ -1516,6 +1517,7 @@ public class JdbcConnection extends TraceObject implements Connection {
try {
Value v = session.getDataHandler().getLobStorage().createBlob(
new ByteArrayInputStream(Utils.EMPTY_BYTES), 0);
session.addTemporaryLob(v);
return new JdbcBlob(this, v, id);
} finally {
afterWriting();
......@@ -1540,6 +1542,7 @@ public class JdbcConnection extends TraceObject implements Connection {
Value v = session.getDataHandler().getLobStorage().createClob(
new InputStreamReader(
new ByteArrayInputStream(Utils.EMPTY_BYTES)), 0);
session.addTemporaryLob(v);
return new JdbcClob(this, v, id);
} finally {
afterWriting();
......@@ -1723,6 +1726,7 @@ public class JdbcConnection extends TraceObject implements Connection {
length = -1;
}
Value v = session.getDataHandler().getLobStorage().createClob(x, length);
session.addTemporaryLob(v);
return v;
}
......@@ -1742,6 +1746,7 @@ public class JdbcConnection extends TraceObject implements Connection {
length = -1;
}
Value v = session.getDataHandler().getLobStorage().createBlob(x, length);
session.addTemporaryLob(v);
return v;
}
......
......@@ -81,6 +81,7 @@ public class TestLob extends TestBase {
testAddLobRestart();
testLobServerMemory();
testUpdatingLobRow();
testLobCleanupSessionTemporaries();
if (config.memory) {
return;
}
......@@ -685,6 +686,33 @@ public class TestLob extends TestBase {
assertEquals(0, FileUtils.newDirectoryStream(getBaseDir() + "/lob.lobs.db").size());
}
private void testLobCleanupSessionTemporaries() throws SQLException {
if (!SysProperties.LOB_IN_DATABASE) {
return;
}
deleteDb("lob");
Connection conn = getConnection("lob");
Statement stat = conn.createStatement();
stat.execute("create table test(data clob)");
ResultSet rs = stat.executeQuery("select count(*) from INFORMATION_SCHEMA.LOBS");
assertTrue(rs.next());
assertEquals(0, rs.getInt(1));
rs.close();
PreparedStatement prep = conn.prepareStatement("INSERT INTO test(data) VALUES(?)");
final String name = "A veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery long string generated only to insert enough data to reproduce the increasing db size PITA ";
prep.setString(1, name);
prep.execute();
prep.close();
rs = stat.executeQuery("select count(*) from INFORMATION_SCHEMA.LOBS");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
rs.close();
conn.close();
}
private void testLobServerMemory() throws SQLException {
deleteDb("lob");
Connection conn = getConnection("lob");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论