提交 078d94ce authored 作者: Thomas Mueller's avatar Thomas Mueller

Running out of memory could result in incomplete transactions or corrupted databases

上级 66f3f69d
...@@ -193,6 +193,7 @@ public abstract class Command implements CommandInterface { ...@@ -193,6 +193,7 @@ public abstract class Command implements CommandInterface {
public int executeUpdate() throws SQLException { public int executeUpdate() throws SQLException {
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
Database database = session.getDatabase(); Database database = session.getDatabase();
database.allocateReserveMemory();
Object sync = database.getMultiThreaded() ? (Object) session : (Object) database; Object sync = database.getMultiThreaded() ? (Object) session : (Object) database;
session.waitIfExclusiveModeEnabled(); session.waitIfExclusiveModeEnabled();
synchronized (sync) { synchronized (sync) {
...@@ -200,10 +201,10 @@ public abstract class Command implements CommandInterface { ...@@ -200,10 +201,10 @@ public abstract class Command implements CommandInterface {
session.setCurrentCommand(this, startTime); session.setCurrentCommand(this, startTime);
try { try {
database.checkPowerOff(); database.checkPowerOff();
int test;
try { try {
return update(); return update();
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
database.freeReserveMemory();
throw Message.convert(e); throw Message.convert(e);
} catch (Throwable e) { } catch (Throwable e) {
throw Message.convert(e); throw Message.convert(e);
......
...@@ -389,6 +389,14 @@ public class SysProperties { ...@@ -389,6 +389,14 @@ public class SysProperties {
*/ */
public static final int REDO_BUFFER_SIZE = getIntSetting("h2.redoBufferSize", 256 * 1024); public static final int REDO_BUFFER_SIZE = getIntSetting("h2.redoBufferSize", 256 * 1024);
/**
* System property <code>h2.reserveMemory</code> (default: 131072).<br />
* This many bytes in main memory are allocated as a reserve. This reserve
* is freed up when if no memory is available, so that rolling back a large
* transaction is easier.
*/
public static final int RESERVE_MEMORY = getIntSetting("h2.reserveMemory", 128 * 1024);
/** /**
* System property <code>h2.reuseSpaceAfter</code> (default: 16).<br /> * System property <code>h2.reuseSpaceAfter</code> (default: 16).<br />
* Reuse space in database files after this many pages are free. * Reuse space in database files after this many pages are free.
......
...@@ -157,6 +157,8 @@ public class Database implements DataHandler { ...@@ -157,6 +157,8 @@ public class Database implements DataHandler {
private boolean lobFilesInDirectories = SysProperties.LOB_FILES_IN_DIRECTORIES; private boolean lobFilesInDirectories = SysProperties.LOB_FILES_IN_DIRECTORIES;
private SmallLRUCache lobFileListCache = new SmallLRUCache(128); private SmallLRUCache lobFileListCache = new SmallLRUCache(128);
private Object reserveMemory;
public Database(String name, ConnectionInfo ci, String cipher) throws SQLException { public Database(String name, ConnectionInfo ci, String cipher) throws SQLException {
this.compareMode = new CompareMode(null, null, 0); this.compareMode = new CompareMode(null, null, 0);
this.persistent = ci.isPersistent(); this.persistent = ci.isPersistent();
...@@ -2005,4 +2007,21 @@ public class Database implements DataHandler { ...@@ -2005,4 +2007,21 @@ public class Database implements DataHandler {
return meta.isLockedExclusively(); return meta.isLockedExclusively();
} }
/**
* Allocate a little main memory that is freed up when if no memory is
* available, so that rolling back a large transaction is easier.
*/
public void allocateReserveMemory() {
if (reserveMemory == null) {
reserveMemory = new byte[SysProperties.RESERVE_MEMORY];
}
}
/**
* Free up the reserve memory.
*/
public void freeReserveMemory() {
reserveMemory = null;
}
} }
...@@ -115,7 +115,6 @@ public class Mode { ...@@ -115,7 +115,6 @@ public class Mode {
add(mode); add(mode);
mode = new Mode("Oracle"); mode = new Mode("Oracle");
mode.uniqueIndexSingleNull = true;
add(mode); add(mode);
} }
......
...@@ -260,6 +260,8 @@ public class FileLock { ...@@ -260,6 +260,8 @@ public class FileLock {
save(); save();
} }
Thread.sleep(sleep); Thread.sleep(sleep);
} catch (OutOfMemoryError e) {
// ignore
} catch (Exception e) { } catch (Exception e) {
trace.debug("watchdog", e); trace.debug("watchdog", e);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论