提交 5ae2eac5 authored 作者: Thomas Mueller's avatar Thomas Mueller

Multi-Version Concurrency (MVCC) may no longer be used when using the…

Multi-Version Concurrency (MVCC) may no longer be used when using the multi-threaded kernel feature (MULTI_THREADED).
上级 ceb1858a
...@@ -132,7 +132,6 @@ public class Database implements DataHandler { ...@@ -132,7 +132,6 @@ public class Database implements DataHandler {
private boolean logIndexChanges; private boolean logIndexChanges;
private int logLevel = 1; private int logLevel = 1;
private int maxLengthInplaceLob = Constants.DEFAULT_MAX_LENGTH_INPLACE_LOB; private int maxLengthInplaceLob = Constants.DEFAULT_MAX_LENGTH_INPLACE_LOB;
private long biggestFileSize;
private int allowLiterals = Constants.DEFAULT_ALLOW_LITERALS; private int allowLiterals = Constants.DEFAULT_ALLOW_LITERALS;
private int powerOffCount = initialPowerOffCount; private int powerOffCount = initialPowerOffCount;
...@@ -198,6 +197,7 @@ public class Database implements DataHandler { ...@@ -198,6 +197,7 @@ public class Database implements DataHandler {
this.recovery = true; this.recovery = true;
} }
this.multiVersion = ci.removeProperty("MVCC", false); this.multiVersion = ci.removeProperty("MVCC", false);
checkMultiThreadedAllowed();
boolean closeAtVmShutdown = ci.removeProperty("DB_CLOSE_ON_EXIT", true); boolean closeAtVmShutdown = ci.removeProperty("DB_CLOSE_ON_EXIT", true);
int traceLevelFile = ci.getIntProperty(SetTypes.TRACE_LEVEL_FILE, TraceSystem.DEFAULT_TRACE_LEVEL_FILE); int traceLevelFile = ci.getIntProperty(SetTypes.TRACE_LEVEL_FILE, TraceSystem.DEFAULT_TRACE_LEVEL_FILE);
int traceLevelSystemOut = ci.getIntProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT, int traceLevelSystemOut = ci.getIntProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT,
...@@ -1749,7 +1749,6 @@ public class Database implements DataHandler { ...@@ -1749,7 +1749,6 @@ public class Database implements DataHandler {
case Constants.LOCK_MODE_READ_COMMITTED: case Constants.LOCK_MODE_READ_COMMITTED:
case Constants.LOCK_MODE_TABLE: case Constants.LOCK_MODE_TABLE:
case Constants.LOCK_MODE_TABLE_GC: case Constants.LOCK_MODE_TABLE_GC:
case Constants.LOCK_MODE_ROW:
break; break;
default: default:
throw Message.getInvalidValueException("lock mode", "" + lockMode); throw Message.getInvalidValueException("lock mode", "" + lockMode);
...@@ -1860,30 +1859,17 @@ public class Database implements DataHandler { ...@@ -1860,30 +1859,17 @@ public class Database implements DataHandler {
} }
/** /**
* Called when the size if the data or index file has been changed. The log * Called when the size if the data or index file has been changed.
* file size is at least 10% of the largest file.
* *
* @param length the new file size * @param length the new file size
*/ */
public void notifyFileSize(long length) { public void notifyFileSize(long length) {
if (length > biggestFileSize) { // ignore
biggestFileSize = length;
setMaxLogSize(0);
}
} }
public synchronized void setMaxLogSize(long value) { public synchronized void setMaxLogSize(long value) {
long minLogSize = biggestFileSize / Constants.LOG_SIZE_DIVIDER;
minLogSize = Math.max(value, minLogSize);
long currentLogSize = getLog().getMaxLogSize();
if (minLogSize > currentLogSize || (value > 0 && minLogSize > value)) {
// works for currentLogSize <= 0 as well
value = minLogSize;
}
if (value > 0) {
getLog().setMaxLogSize(value); getLog().setMaxLogSize(value);
} }
}
public void setAllowLiterals(int value) { public void setAllowLiterals(int value) {
this.allowLiterals = value; this.allowLiterals = value;
...@@ -1970,10 +1956,19 @@ public class Database implements DataHandler { ...@@ -1970,10 +1956,19 @@ public class Database implements DataHandler {
return multiThreaded; return multiThreaded;
} }
public void setMultiThreaded(boolean multiThreaded) { public void setMultiThreaded(boolean multiThreaded) throws SQLException {
this.multiThreaded = multiThreaded; this.multiThreaded = multiThreaded;
checkMultiThreadedAllowed();
} }
private void checkMultiThreadedAllowed() throws SQLException {
if (multiThreaded && multiVersion) {
multiVersion = false;
throw Message.getSQLException(ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, "MVCC & MULTI_THREADED");
}
}
public void setMaxOperationMemory(int maxOperationMemory) { public void setMaxOperationMemory(int maxOperationMemory) {
this.maxOperationMemory = maxOperationMemory; this.maxOperationMemory = maxOperationMemory;
} }
......
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.mvcc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.h2.test.TestBase;
/**
* Multi-threaded MVCC (multi version concurrency) test cases.
*/
public class TestMvccMultiThreaded extends TestBase {
public void test() throws Exception {
if (!config.mvcc) {
return;
}
if (config.mvcc) {
// not supported at this time
return;
}
deleteDb("mvccMultiThreaded");
int len = 2;
final Connection[] connList = new Connection[len];
for (int i = 0; i < len; i++) {
connList[i] = getConnection("mvccMultiThreaded;MULTI_THREADED=TRUE");
}
Connection conn = connList[0];
conn.createStatement().execute("create table test(id int primary key, value int)");
conn.createStatement().execute("insert into test values(0, 0)");
final SQLException[] ex = new SQLException[1];
final int count = 1000;
Thread[] threads = new Thread[len];
for (int i = 0; i < len; i++) {
final int x = i;
threads[i] = new Thread() {
public void run() {
for (int a = 0; a < count; a++) {
try {
connList[x].createStatement().execute("update test set value=value+1");
} catch (SQLException e) {
ex[0] = e;
}
}
}
};
threads[i].start();
}
for (int i = 0; i < len; i++) {
threads[i].join();
}
if (ex[0] != null) {
throw ex[0];
}
ResultSet rs = conn.createStatement().executeQuery("select value from test");
rs.next();
assertEquals(count * len, rs.getInt(1));
for (int i = 0; i < len; i++) {
connList[i].close();
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论