提交 e7382be6 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Remove DbSettings.largeTransactions

上级 820d98dd
...@@ -130,12 +130,6 @@ public class DbSettings extends SettingsBase { ...@@ -130,12 +130,6 @@ public class DbSettings extends SettingsBase {
*/ */
public final boolean functionsInSchema = get("FUNCTIONS_IN_SCHEMA", true); public final boolean functionsInSchema = get("FUNCTIONS_IN_SCHEMA", true);
/**
* Database setting <code>LARGE_TRANSACTIONS</code> (default: true).<br />
* Support very large transactions
*/
public final boolean largeTransactions = get("LARGE_TRANSACTIONS", true);
/** /**
* Database setting <code>LOB_TIMEOUT</code> (default: 300000, * Database setting <code>LOB_TIMEOUT</code> (default: 300000,
* which means 5 minutes).<br /> * which means 5 minutes).<br />
......
...@@ -8,7 +8,6 @@ package org.h2.engine; ...@@ -8,7 +8,6 @@ package org.h2.engine;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import org.h2.message.DbException;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.table.Table; import org.h2.table.Table;
...@@ -27,7 +26,6 @@ public class UndoLog { ...@@ -27,7 +26,6 @@ public class UndoLog {
private int memoryUndo; private int memoryUndo;
private int storedEntries; private int storedEntries;
private HashMap<Integer, Table> tables; private HashMap<Integer, Table> tables;
private final boolean largeTransactions;
/** /**
* Create a new undo log for the given session. * Create a new undo log for the given session.
...@@ -36,7 +34,6 @@ public class UndoLog { ...@@ -36,7 +34,6 @@ public class UndoLog {
*/ */
UndoLog(Session session) { UndoLog(Session session) {
this.database = session.getDatabase(); this.database = session.getDatabase();
largeTransactions = database.getSettings().largeTransactions;
} }
/** /**
...@@ -45,13 +42,7 @@ public class UndoLog { ...@@ -45,13 +42,7 @@ public class UndoLog {
* @return the number of rows * @return the number of rows
*/ */
int size() { int size() {
if (largeTransactions) { return storedEntries + records.size();
return storedEntries + records.size();
}
if (SysProperties.CHECK && memoryUndo > records.size()) {
DbException.throwInternalError();
}
return records.size();
} }
/** /**
...@@ -77,26 +68,24 @@ public class UndoLog { ...@@ -77,26 +68,24 @@ public class UndoLog {
*/ */
public UndoLogRecord getLast() { public UndoLogRecord getLast() {
int i = records.size() - 1; int i = records.size() - 1;
if (largeTransactions) { if (i < 0 && storedEntries > 0) {
if (i < 0 && storedEntries > 0) { int last = storedEntriesPos.size() - 1;
int last = storedEntriesPos.size() - 1; long pos = storedEntriesPos.remove(last);
long pos = storedEntriesPos.remove(last); long end = file.length();
long end = file.length(); int bufferLength = (int) (end - pos);
int bufferLength = (int) (end - pos); Data buff = Data.create(database, bufferLength);
Data buff = Data.create(database, bufferLength); file.seek(pos);
file.seek(pos); file.readFully(buff.getBytes(), 0, bufferLength);
file.readFully(buff.getBytes(), 0, bufferLength); while (buff.length() < bufferLength) {
while (buff.length() < bufferLength) { UndoLogRecord e = UndoLogRecord.loadFromBuffer(buff, this);
UndoLogRecord e = UndoLogRecord.loadFromBuffer(buff, this); records.add(e);
records.add(e); memoryUndo++;
memoryUndo++;
}
storedEntries -= records.size();
file.setLength(pos);
file.seek(pos);
} }
i = records.size() - 1; storedEntries -= records.size();
file.setLength(pos);
file.seek(pos);
} }
i = records.size() - 1;
UndoLogRecord entry = records.get(i); UndoLogRecord entry = records.get(i);
if (entry.isStored()) { if (entry.isStored()) {
int start = Math.max(0, i - database.getMaxMemoryUndo() / 2); int start = Math.max(0, i - database.getMaxMemoryUndo() / 2);
...@@ -152,62 +141,31 @@ public class UndoLog { ...@@ -152,62 +141,31 @@ public class UndoLog {
*/ */
void add(UndoLogRecord entry) { void add(UndoLogRecord entry) {
records.add(entry); records.add(entry);
if (largeTransactions) { memoryUndo++;
memoryUndo++; if (memoryUndo > database.getMaxMemoryUndo() &&
if (memoryUndo > database.getMaxMemoryUndo() && database.isPersistent() &&
database.isPersistent() && !database.isMVStore()) {
!database.isMVStore()) { if (file == null) {
if (file == null) { String fileName = database.createTempFile();
String fileName = database.createTempFile(); file = database.openFile(fileName, "rw", false);
file = database.openFile(fileName, "rw", false); file.setCheckedWriting(false);
file.setCheckedWriting(false); file.setLength(FileStore.HEADER_LENGTH);
file.setLength(FileStore.HEADER_LENGTH);
}
Data buff = Data.create(database, Constants.DEFAULT_PAGE_SIZE);
for (int i = 0; i < records.size(); i++) {
UndoLogRecord r = records.get(i);
buff.checkCapacity(Constants.DEFAULT_PAGE_SIZE);
r.append(buff, this);
if (i == records.size() - 1 || buff.length() > Constants.UNDO_BLOCK_SIZE) {
storedEntriesPos.add(file.getFilePointer());
file.write(buff.getBytes(), 0, buff.length());
buff.reset();
}
}
storedEntries += records.size();
memoryUndo = 0;
records.clear();
file.autoDelete();
} }
} else { Data buff = Data.create(database, Constants.DEFAULT_PAGE_SIZE);
if (!entry.isStored()) { for (int i = 0; i < records.size(); i++) {
memoryUndo++; UndoLogRecord r = records.get(i);
} buff.checkCapacity(Constants.DEFAULT_PAGE_SIZE);
if (memoryUndo > database.getMaxMemoryUndo() && r.append(buff, this);
database.isPersistent() && if (i == records.size() - 1 || buff.length() > Constants.UNDO_BLOCK_SIZE) {
!database.isMVStore()) { storedEntriesPos.add(file.getFilePointer());
if (file == null) { file.write(buff.getBytes(), 0, buff.length());
String fileName = database.createTempFile(); buff.reset();
file = database.openFile(fileName, "rw", false);
file.setCheckedWriting(false);
file.seek(FileStore.HEADER_LENGTH);
rowBuff = Data.create(database, Constants.DEFAULT_PAGE_SIZE);
Data buff = rowBuff;
for (UndoLogRecord r : records) {
saveIfPossible(r, buff);
}
} else {
saveIfPossible(entry, rowBuff);
} }
file.autoDelete();
} }
} storedEntries += records.size();
} memoryUndo = 0;
records.clear();
private void saveIfPossible(UndoLogRecord r, Data buff) { file.autoDelete();
if (!r.isStored() && r.canStore()) {
r.save(buff, file, this);
memoryUndo--;
} }
} }
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.todo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.tools.DeleteDbFiles;
/**
* A test to reproduce out of memory using a large operation.
*/
public class TestUndoLogMemory {
/**
* Run just this test.
*
* @param args ignored
*/
public static void main(String... args) throws Exception {
TestUndoLogMemory.test(10, "null");
TestUndoLogMemory.test(100, "space(100000)");
// new TestUndoLogMemory().test(100000, "null");
// new TestUndoLogMemory().test(1000, "space(100000)");
}
private static void test(int count, String defaultValue) throws SQLException {
// -Xmx1m -XX:+HeapDumpOnOutOfMemoryError
DeleteDbFiles.execute("data", "test", true);
Connection conn = DriverManager.getConnection(
"jdbc:h2:data/test;large_transactions=true");
Statement stat = conn.createStatement();
stat.execute("set cache_size 32");
stat.execute("SET max_operation_memory 100");
stat.execute("SET max_memory_undo 100");
conn.setAutoCommit(false);
// also a problem: tables without unique index
System.out.println("create--- " + count + " " + defaultValue);
stat.execute("create table test(id int, name varchar default " +
defaultValue + " )");
System.out.println("insert---");
stat.execute("insert into test(id) select x from system_range(1, " +
count + ")");
System.out.println("rollback---");
conn.rollback();
System.out.println("drop---");
stat.execute("drop table test");
System.out.println("create---");
stat.execute("create table test" +
"(id int primary key, name varchar default " +
defaultValue + " )");
// INSERT problem
System.out.println("insert---");
stat.execute(
"insert into test(id) select x from system_range(1, "+count+")");
System.out.println("delete---");
stat.execute("delete from test");
// DELETE problem
System.out.println("insert---");
PreparedStatement prep = conn.prepareStatement(
"insert into test(id) values(?)");
for (int i = 0; i < count; i++) {
prep.setInt(1, i);
prep.execute();
}
System.out.println("delete---");
stat.execute("delete from test");
System.out.println("close---");
conn.close();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论