Unverified 提交 acf1f91e authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1208 from katzyn/mvcc

Make MVCC setting a no-op
...@@ -227,8 +227,7 @@ See the <a href="grammar.html">Grammar</a> for details. ...@@ -227,8 +227,7 @@ See the <a href="grammar.html">Grammar</a> for details.
Transaction isolation is provided for all data manipulation language (DML) statements. Transaction isolation is provided for all data manipulation language (DML) statements.
</p> </p>
<p> <p>
Please note MVCC is enabled in version 1.4.x by default, when using the MVStore. Please note that with default MVStore storage engine table level locking is not used.
In this case, table level locking is not used.
Instead, rows are locked for update, and read committed is used in all cases Instead, rows are locked for update, and read committed is used in all cases
(changing the isolation level has no effect). (changing the isolation level has no effect).
</p> </p>
...@@ -302,8 +301,8 @@ for each connection. ...@@ -302,8 +301,8 @@ for each connection.
<h2 id="mvcc">Multi-Version Concurrency Control (MVCC)</h2> <h2 id="mvcc">Multi-Version Concurrency Control (MVCC)</h2>
<p> <p>
The MVCC feature allows higher concurrency than using (table level or row level) locks. The MVCC feature allows higher concurrency than using (table level or row level) locks.
When using MVCC in this database, delete, insert and update operations will only issue a Delete, insert and update operations will only issue a shared lock on the table.
shared lock on the table. An exclusive lock is still used when adding or removing columns, An exclusive lock is still used when adding or removing columns,
when dropping the table, and when using <code>SELECT ... FOR UPDATE</code>. when dropping the table, and when using <code>SELECT ... FOR UPDATE</code>.
Connections only 'see' committed data, and own changes. That means, if connection A updates Connections only 'see' committed data, and own changes. That means, if connection A updates
a row but doesn't commit this change yet, connection B will see the old value. a row but doesn't commit this change yet, connection B will see the old value.
...@@ -312,30 +311,11 @@ Only when the change is committed, the new value is visible by other connections ...@@ -312,30 +311,11 @@ Only when the change is committed, the new value is visible by other connections
database waits until it can apply the change, but at most until the lock timeout expires. database waits until it can apply the change, but at most until the lock timeout expires.
</p> </p>
<p> <p>
To use the MVCC feature, append <code>;MVCC=TRUE</code> to the database URL: This feature is only available with the default MVStore storage engine.
</p> Changing the lock mode with it (<code>LOCK_MODE</code>) has no effect.
<pre>
jdbc:h2:~/test;MVCC=TRUE
</pre>
<p>
The setting must be specified in the first connection (the one that opens the database).
It is not possible to enable or disable this setting while the database is already open.
</p> </p>
<p> <p>
If MVCC is enabled, changing the lock mode (<code>LOCK_MODE</code>) has no effect. MVCC is not used when using the PageStore storage engine.
</p>
<p>
The MVCC mode is enabled by default in version 1.4.x,
with the default MVStore storage engine.
MVCC is disabled by default when using the PageStore storage engine
(which is the default in version 1.3.x).
The following applies when using the PageStore storage engine:
The MVCC feature is not fully tested yet.
The limitations of the MVCC mode are:
with the PageStore storage engine, it can not be used at the same time as
<code>MULTI_THREADED=TRUE</code>;
the complete undo log (the list of uncommitted changes) must fit in memory when using multi-version concurrency.
The setting <code>MAX_MEMORY_UNDO</code> has no effect.
</p> </p>
<h2 id="clustering">Clustering / High Availability</h2> <h2 id="clustering">Clustering / High Availability</h2>
...@@ -1645,16 +1625,20 @@ If this file is in the classpath, every connect to an older database will result ...@@ -1645,16 +1625,20 @@ If this file is in the classpath, every connect to an older database will result
<p> <p>
The conversion itself is done internally via <code>'script to'</code> and <code>'runscript from'</code>. After the conversion process, the files will be The conversion itself is done internally via <code>'script to'</code> and <code>'runscript from'</code>. After the conversion process, the files will be
renamed from renamed from
</p>
<ul> <ul>
<li><code>dbName.data.db</code> to <code>dbName.data.db.backup</code> <li><code>dbName.data.db</code> to <code>dbName.data.db.backup</code>
</li><li><code>dbName.index.db</code> to <code>dbName.index.db.backup</code> </li><li><code>dbName.index.db</code> to <code>dbName.index.db.backup</code>
</li></ul> </li></ul>
<p>
by default. Also, the temporary script will be written to the database directory instead of a temporary directory. by default. Also, the temporary script will be written to the database directory instead of a temporary directory.
Both defaults can be customized via Both defaults can be customized via
</p>
<ul> <ul>
<li><code>org.h2.upgrade.DbUpgrade.setDeleteOldDb(boolean)</code> <li><code>org.h2.upgrade.DbUpgrade.setDeleteOldDb(boolean)</code>
</li><li><code>org.h2.upgrade.DbUpgrade.setScriptInTmpDir(boolean)</code> </li><li><code>org.h2.upgrade.DbUpgrade.setScriptInTmpDir(boolean)</code>
</li></ul> </li></ul>
<p>
prior opening a database connection. prior opening a database connection.
</p> </p>
<p> <p>
...@@ -1678,6 +1662,7 @@ To disable this feature set the system property <code>h2.serializeJavaObject=fal ...@@ -1678,6 +1662,7 @@ To disable this feature set the system property <code>h2.serializeJavaObject=fal
<p> <p>
Serialization and deserialization of java objects is customizable both at system level and at database level providing a Serialization and deserialization of java objects is customizable both at system level and at database level providing a
<a href="http://www.h2database.com/javadoc/org/h2/api/JavaObjectSerializer.html">JavaObjectSerializer</a> implementation: <a href="http://www.h2database.com/javadoc/org/h2/api/JavaObjectSerializer.html">JavaObjectSerializer</a> implementation:
</p>
<ul> <ul>
<li> <li>
At system level set the system property <code>h2.javaObjectSerializer</code> with the At system level set the system property <code>h2.javaObjectSerializer</code> with the
...@@ -1693,7 +1678,6 @@ Please note that this SQL statement can only be executed before any tables are d ...@@ -1693,7 +1678,6 @@ Please note that this SQL statement can only be executed before any tables are d
</p> </p>
</li> </li>
</ul> </ul>
</p>
<h2 id="custom_data_types_handler_api">Custom Data Types Handler API</h2> <h2 id="custom_data_types_handler_api">Custom Data Types Handler API</h2>
<p> <p>
...@@ -1704,6 +1688,7 @@ of minimal required API basically consisting of type identification and conversi ...@@ -1704,6 +1688,7 @@ of minimal required API basically consisting of type identification and conversi
In order to enable this feature, set the system property <code>h2.customDataTypesHandler</code> (default: null) to the fully qualified name of the class providing In order to enable this feature, set the system property <code>h2.customDataTypesHandler</code> (default: null) to the fully qualified name of the class providing
<a href="http://www.h2database.com/javadoc/org/h2/api/CustomDataTypesHandler.html">CustomDataTypesHandler</a> interface implementation. <br /> <a href="http://www.h2database.com/javadoc/org/h2/api/CustomDataTypesHandler.html">CustomDataTypesHandler</a> interface implementation. <br />
The instance of that class will be created by H2 and used to: The instance of that class will be created by H2 and used to:
</p>
<ul> <ul>
<li>resolve the names and identifiers of extrinsic data types. <li>resolve the names and identifiers of extrinsic data types.
</li> </li>
...@@ -1712,7 +1697,6 @@ The instance of that class will be created by H2 and used to: ...@@ -1712,7 +1697,6 @@ The instance of that class will be created by H2 and used to:
<li>provide order of the data types. <li>provide order of the data types.
</li> </li>
</ul> </ul>
</p>
<p>This is a system-level setting, i.e. affects all the databases.</p> <p>This is a system-level setting, i.e. affects all the databases.</p>
<p><b>Note: </b>Please keep in mind that this feature may not possibly provide the same ABI stability level as other features as it exposes many of the H2 internals. You may be required to update your code occasionally due to internal changes in H2 if you are going to use this feature. <p><b>Note: </b>Please keep in mind that this feature may not possibly provide the same ABI stability level as other features as it exposes many of the H2 internals. You may be required to update your code occasionally due to internal changes in H2 if you are going to use this feature.
......
...@@ -1861,7 +1861,7 @@ public class ErrorCode { ...@@ -1861,7 +1861,7 @@ public class ErrorCode {
* connections at the same time, or trying to insert two rows with the same * connections at the same time, or trying to insert two rows with the same
* key from two connections. Example: * key from two connections. Example:
* <pre> * <pre>
* jdbc:h2:~/test;MVCC=TRUE * jdbc:h2:~/test
* Session 1: * Session 1:
* CREATE TABLE TEST(ID INT); * CREATE TABLE TEST(ID INT);
* INSERT INTO TEST VALUES(1); * INSERT INTO TEST VALUES(1);
...@@ -1887,8 +1887,7 @@ public class ErrorCode { ...@@ -1887,8 +1887,7 @@ public class ErrorCode {
/** /**
* The error with code <code>90133</code> is thrown when * The error with code <code>90133</code> is thrown when
* trying to change a specific database property while the database is * trying to change a specific database property while the database is
* already open. The MVCC property needs to be set in the first connection * already open.
* (in the connection opening the database) and can not be changed later on.
*/ */
public static final int CANNOT_CHANGE_SETTING_WHEN_OPEN_1 = 90133; public static final int CANNOT_CHANGE_SETTING_WHEN_OPEN_1 = 90133;
......
...@@ -5589,10 +5589,8 @@ public class Parser { ...@@ -5589,10 +5589,8 @@ public class Parser {
return new TransactionCommand(session, setting); return new TransactionCommand(session, setting);
} else if (readIf("MVCC")) { } else if (readIf("MVCC")) {
readIfEqualOrTo(); readIfEqualOrTo();
boolean value = readBooleanSetting(); readBooleanSetting();
Set command = new Set(session, SetTypes.MVCC); return new NoOperation(session);
command.setInt(value ? 1 : 0);
return command;
} else if (readIf("EXCLUSIVE")) { } else if (readIf("EXCLUSIVE")) {
readIfEqualOrTo(); readIfEqualOrTo();
Set command = new Set(session, SetTypes.EXCLUSIVE); Set command = new Set(session, SetTypes.EXCLUSIVE);
......
...@@ -1308,7 +1308,7 @@ public class Select extends Query { ...@@ -1308,7 +1308,7 @@ public class Select extends Query {
public void setForUpdate(boolean b) { public void setForUpdate(boolean b) {
this.isForUpdate = b; this.isForUpdate = b;
if (session.getDatabase().getSettings().selectForUpdateMvcc && if (session.getDatabase().getSettings().selectForUpdateMvcc &&
session.getDatabase().isMultiVersion()) { session.getDatabase().isMVStore()) {
isForUpdateMvcc = b; isForUpdateMvcc = b;
} }
} }
......
...@@ -354,13 +354,6 @@ public class Set extends Prepared { ...@@ -354,13 +354,6 @@ public class Set extends Prepared {
} }
break; break;
} }
case SetTypes.MVCC: {
if (database.isMultiVersion() != (getIntValue() == 1)) {
throw DbException.get(
ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, "MVCC");
}
break;
}
case SetTypes.OPTIMIZE_REUSE_RESULTS: { case SetTypes.OPTIMIZE_REUSE_RESULTS: {
session.getUser().checkAdmin(); session.getUser().checkAdmin();
database.setOptimizeReuseResults(getIntValue() != 0); database.setOptimizeReuseResults(getIntValue() != 0);
......
...@@ -162,100 +162,95 @@ public class SetTypes { ...@@ -162,100 +162,95 @@ public class SetTypes {
*/ */
public static final int REFERENTIAL_INTEGRITY = 30; public static final int REFERENTIAL_INTEGRITY = 30;
/**
* The type of a SET MVCC statement.
*/
public static final int MVCC = 31;
/** /**
* The type of a SET MAX_OPERATION_MEMORY statement. * The type of a SET MAX_OPERATION_MEMORY statement.
*/ */
public static final int MAX_OPERATION_MEMORY = 32; public static final int MAX_OPERATION_MEMORY = 31;
/** /**
* The type of a SET EXCLUSIVE statement. * The type of a SET EXCLUSIVE statement.
*/ */
public static final int EXCLUSIVE = 33; public static final int EXCLUSIVE = 32;
/** /**
* The type of a SET CREATE_BUILD statement. * The type of a SET CREATE_BUILD statement.
*/ */
public static final int CREATE_BUILD = 34; public static final int CREATE_BUILD = 33;
/** /**
* The type of a SET \@VARIABLE statement. * The type of a SET \@VARIABLE statement.
*/ */
public static final int VARIABLE = 35; public static final int VARIABLE = 34;
/** /**
* The type of a SET QUERY_TIMEOUT statement. * The type of a SET QUERY_TIMEOUT statement.
*/ */
public static final int QUERY_TIMEOUT = 36; public static final int QUERY_TIMEOUT = 35;
/** /**
* The type of a SET REDO_LOG_BINARY statement. * The type of a SET REDO_LOG_BINARY statement.
*/ */
public static final int REDO_LOG_BINARY = 37; public static final int REDO_LOG_BINARY = 36;
/** /**
* The type of a SET BINARY_COLLATION statement. * The type of a SET BINARY_COLLATION statement.
*/ */
public static final int BINARY_COLLATION = 38; public static final int BINARY_COLLATION = 37;
/** /**
* The type of a SET JAVA_OBJECT_SERIALIZER statement. * The type of a SET JAVA_OBJECT_SERIALIZER statement.
*/ */
public static final int JAVA_OBJECT_SERIALIZER = 39; public static final int JAVA_OBJECT_SERIALIZER = 38;
/** /**
* The type of a SET RETENTION_TIME statement. * The type of a SET RETENTION_TIME statement.
*/ */
public static final int RETENTION_TIME = 40; public static final int RETENTION_TIME = 39;
/** /**
* The type of a SET QUERY_STATISTICS statement. * The type of a SET QUERY_STATISTICS statement.
*/ */
public static final int QUERY_STATISTICS = 41; public static final int QUERY_STATISTICS = 40;
/** /**
* The type of a SET QUERY_STATISTICS_MAX_ENTRIES statement. * The type of a SET QUERY_STATISTICS_MAX_ENTRIES statement.
*/ */
public static final int QUERY_STATISTICS_MAX_ENTRIES = 42; public static final int QUERY_STATISTICS_MAX_ENTRIES = 41;
/** /**
* The type of a SET ROW_FACTORY statement. * The type of a SET ROW_FACTORY statement.
*/ */
public static final int ROW_FACTORY = 43; public static final int ROW_FACTORY = 42;
/** /**
* The type of SET BATCH_JOINS statement. * The type of SET BATCH_JOINS statement.
*/ */
public static final int BATCH_JOINS = 44; public static final int BATCH_JOINS = 43;
/** /**
* The type of SET FORCE_JOIN_ORDER statement. * The type of SET FORCE_JOIN_ORDER statement.
*/ */
public static final int FORCE_JOIN_ORDER = 45; public static final int FORCE_JOIN_ORDER = 44;
/** /**
* The type of SET LAZY_QUERY_EXECUTION statement. * The type of SET LAZY_QUERY_EXECUTION statement.
*/ */
public static final int LAZY_QUERY_EXECUTION = 46; public static final int LAZY_QUERY_EXECUTION = 45;
/** /**
* The type of SET BUILTIN_ALIAS_OVERRIDE statement. * The type of SET BUILTIN_ALIAS_OVERRIDE statement.
*/ */
public static final int BUILTIN_ALIAS_OVERRIDE = 47; public static final int BUILTIN_ALIAS_OVERRIDE = 46;
/** /**
* The type of a SET COLUMN_NAME_RULES statement. * The type of a SET COLUMN_NAME_RULES statement.
*/ */
public static final int COLUMN_NAME_RULES = 48; public static final int COLUMN_NAME_RULES = 47;
/** /**
* The type of a SET AUTHENTICATOR statement. * The type of a SET AUTHENTICATOR statement.
*/ */
public static final int AUTHENTICATOR= 49; public static final int AUTHENTICATOR = 48;
private static final int COUNT = AUTHENTICATOR + 1; private static final int COUNT = AUTHENTICATOR + 1;
...@@ -298,7 +293,6 @@ public class SetTypes { ...@@ -298,7 +293,6 @@ public class SetTypes {
list.add(SCHEMA_SEARCH_PATH, "SCHEMA_SEARCH_PATH"); list.add(SCHEMA_SEARCH_PATH, "SCHEMA_SEARCH_PATH");
list.add(UNDO_LOG, "UNDO_LOG"); list.add(UNDO_LOG, "UNDO_LOG");
list.add(REFERENTIAL_INTEGRITY, "REFERENTIAL_INTEGRITY"); list.add(REFERENTIAL_INTEGRITY, "REFERENTIAL_INTEGRITY");
list.add(MVCC, "MVCC");
list.add(MAX_OPERATION_MEMORY, "MAX_OPERATION_MEMORY"); list.add(MAX_OPERATION_MEMORY, "MAX_OPERATION_MEMORY");
list.add(EXCLUSIVE, "EXCLUSIVE"); list.add(EXCLUSIVE, "EXCLUSIVE");
list.add(CREATE_BUILD, "CREATE_BUILD"); list.add(CREATE_BUILD, "CREATE_BUILD");
......
...@@ -92,7 +92,7 @@ public class ConnectionInfo implements Cloneable { ...@@ -92,7 +92,7 @@ public class ConnectionInfo implements Cloneable {
static { static {
String[] connectionTime = { "ACCESS_MODE_DATA", "AUTOCOMMIT", "CIPHER", String[] connectionTime = { "ACCESS_MODE_DATA", "AUTOCOMMIT", "CIPHER",
"CREATE", "CACHE_TYPE", "FILE_LOCK", "IGNORE_UNKNOWN_SETTINGS", "CREATE", "CACHE_TYPE", "FILE_LOCK", "IGNORE_UNKNOWN_SETTINGS",
"IFEXISTS", "INIT", "PASSWORD", "RECOVER", "RECOVER_TEST", "IFEXISTS", "INIT", "MVCC", "PASSWORD", "RECOVER", "RECOVER_TEST",
"USER", "AUTO_SERVER", "AUTO_SERVER_PORT", "NO_UPGRADE", "USER", "AUTO_SERVER", "AUTO_SERVER_PORT", "NO_UPGRADE",
"AUTO_RECONNECT", "OPEN_NEW", "PAGE_SIZE", "PASSWORD_HASH", "JMX", "AUTO_RECONNECT", "OPEN_NEW", "PAGE_SIZE", "PASSWORD_HASH", "JMX",
"SCOPE_GENERATED_KEYS", "AUTHREALM", "AUTHZPWD" }; "SCOPE_GENERATED_KEYS", "AUTHREALM", "AUTHZPWD" };
......
...@@ -185,8 +185,6 @@ public class Database implements DataHandler { ...@@ -185,8 +185,6 @@ public class Database implements DataHandler {
private final String cacheType; private final String cacheType;
private final String accessModeData; private final String accessModeData;
private boolean referentialIntegrity = true; private boolean referentialIntegrity = true;
/** ie. the MVCC setting */
private boolean multiVersion;
private Mode mode = Mode.getRegular(); private Mode mode = Mode.getRegular();
/** ie. the MULTI_THREADED setting */ /** ie. the MULTI_THREADED setting */
private boolean multiThreaded; private boolean multiThreaded;
...@@ -284,8 +282,6 @@ public class Database implements DataHandler { ...@@ -284,8 +282,6 @@ public class Database implements DataHandler {
if (modeName != null) { if (modeName != null) {
this.mode = Mode.getInstance(modeName); this.mode = Mode.getInstance(modeName);
} }
this.multiVersion =
ci.getProperty("MVCC", dbSettings.mvStore);
this.logMode = this.logMode =
ci.getProperty("LOG", PageStore.LOG_MODE_SYNC); ci.getProperty("LOG", PageStore.LOG_MODE_SYNC);
this.javaObjectSerializerName = this.javaObjectSerializerName =
...@@ -657,7 +653,6 @@ public class Database implements DataHandler { ...@@ -657,7 +653,6 @@ public class Database implements DataHandler {
dbSettings.mvStore = false; dbSettings.mvStore = false;
// Need to re-init this because the first time we do it we don't // Need to re-init this because the first time we do it we don't
// know if we have an mvstore or a pagestore. // know if we have an mvstore or a pagestore.
multiVersion = ci.getProperty("MVCC", false);
multiThreaded = ci.getProperty("MULTI_THREADED", false); multiThreaded = ci.getProperty("MULTI_THREADED", false);
} }
if (readOnly) { if (readOnly) {
...@@ -920,7 +915,7 @@ public class Database implements DataHandler { ...@@ -920,7 +915,7 @@ public class Database implements DataHandler {
verifyMetaLocked(session); verifyMetaLocked(session);
} }
meta.addRow(session, r); meta.addRow(session, r);
if (isMultiVersion()) { if (isMVStore()) {
// TODO this should work without MVCC, but avoid risks at the // TODO this should work without MVCC, but avoid risks at the
// moment // moment
session.log(meta, UndoLogRecord.INSERT, r); session.log(meta, UndoLogRecord.INSERT, r);
...@@ -1026,7 +1021,7 @@ public class Database implements DataHandler { ...@@ -1026,7 +1021,7 @@ public class Database implements DataHandler {
} }
Row found = cursor.get(); Row found = cursor.get();
meta.removeRow(session, found); meta.removeRow(session, found);
if (isMultiVersion()) { if (isMVStore()) {
// TODO this should work without MVCC, but avoid risks at // TODO this should work without MVCC, but avoid risks at
// the moment // the moment
session.log(meta, UndoLogRecord.DELETE, found); session.log(meta, UndoLogRecord.DELETE, found);
...@@ -2423,12 +2418,12 @@ public class Database implements DataHandler { ...@@ -2423,12 +2418,12 @@ public class Database implements DataHandler {
} }
/** /**
* Check if multi version concurrency is enabled for this database. * Check if MVStore backend is used for this database.
* *
* @return true if it is enabled * @return {@code true} for MVStore, {@code false} for PageStore
*/ */
public boolean isMultiVersion() { public boolean isMVStore() {
return multiVersion; return dbSettings.mvStore;
} }
/** /**
...@@ -2458,13 +2453,6 @@ public class Database implements DataHandler { ...@@ -2458,13 +2453,6 @@ public class Database implements DataHandler {
public void setMultiThreaded(boolean multiThreaded) { public void setMultiThreaded(boolean multiThreaded) {
if (multiThreaded && this.multiThreaded != multiThreaded) { if (multiThreaded && this.multiThreaded != multiThreaded) {
if (multiVersion && mvStore == null) {
// currently the combination of MVCC and MULTI_THREADED is not
// supported
throw DbException.get(
ErrorCode.UNSUPPORTED_SETTING_COMBINATION,
"MVCC & MULTI_THREADED & !MV_STORE");
}
if (lockMode == 0) { if (lockMode == 0) {
// currently the combination of LOCK_MODE=0 and MULTI_THREADED // currently the combination of LOCK_MODE=0 and MULTI_THREADED
// is not supported // is not supported
...@@ -2872,10 +2860,6 @@ public class Database implements DataHandler { ...@@ -2872,10 +2860,6 @@ public class Database implements DataHandler {
this.defaultTableType = defaultTableType; this.defaultTableType = defaultTableType;
} }
public void setMultiVersion(boolean multiVersion) {
this.multiVersion = multiVersion;
}
public DbSettings getSettings() { public DbSettings getSettings() {
return dbSettings; return dbSettings;
} }
......
...@@ -693,7 +693,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -693,7 +693,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
removeTemporaryLobs(true); removeTemporaryLobs(true);
if (undoLog.size() > 0) { if (undoLog.size() > 0) {
// commit the rows when using MVCC // commit the rows when using MVCC
if (database.isMultiVersion()) { if (database.isMVStore()) {
synchronized (database) { synchronized (database) {
ArrayList<Row> rows = new ArrayList<>(undoLog.size()); ArrayList<Row> rows = new ArrayList<>(undoLog.size());
while (undoLog.size() > 0) { while (undoLog.size() > 0) {
...@@ -916,7 +916,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -916,7 +916,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
if (SysProperties.CHECK) { if (SysProperties.CHECK) {
int lockMode = database.getLockMode(); int lockMode = database.getLockMode();
if (lockMode != Constants.LOCK_MODE_OFF && if (lockMode != Constants.LOCK_MODE_OFF &&
!database.isMultiVersion()) { !database.isMVStore()) {
TableType tableType = log.getTable().getTableType(); TableType tableType = log.getTable().getTableType();
if (!locks.contains(log.getTable()) if (!locks.contains(log.getTable())
&& TableType.TABLE_LINK != tableType && TableType.TABLE_LINK != tableType
...@@ -927,7 +927,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -927,7 +927,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
} }
undoLog.add(log); undoLog.add(log);
} else { } else {
if (database.isMultiVersion()) { if (database.isMVStore()) {
// see also UndoLogRecord.commit // see also UndoLogRecord.commit
ArrayList<Index> indexes = table.getIndexes(); ArrayList<Index> indexes = table.getIndexes();
for (Index index : indexes) { for (Index index : indexes) {
...@@ -943,7 +943,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba ...@@ -943,7 +943,7 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
* READ_COMMITTED. * READ_COMMITTED.
*/ */
public void unlockReadLocks() { public void unlockReadLocks() {
if (database.isMultiVersion()) { if (database.isMVStore()) {
// MVCC: keep shared locks (insert / update / delete) // MVCC: keep shared locks (insert / update / delete)
return; return;
} }
......
...@@ -156,7 +156,7 @@ public class UndoLog { ...@@ -156,7 +156,7 @@ public class UndoLog {
memoryUndo++; memoryUndo++;
if (memoryUndo > database.getMaxMemoryUndo() && if (memoryUndo > database.getMaxMemoryUndo() &&
database.isPersistent() && database.isPersistent() &&
!database.isMultiVersion()) { !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);
...@@ -185,7 +185,7 @@ public class UndoLog { ...@@ -185,7 +185,7 @@ public class UndoLog {
} }
if (memoryUndo > database.getMaxMemoryUndo() && if (memoryUndo > database.getMaxMemoryUndo() &&
database.isPersistent() && database.isPersistent() &&
!database.isMultiVersion()) { !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);
......
...@@ -58,7 +58,7 @@ public class PageDataIndex extends PageIndex { ...@@ -58,7 +58,7 @@ public class PageDataIndex extends PageIndex {
public PageDataIndex(RegularTable table, int id, IndexColumn[] columns, public PageDataIndex(RegularTable table, int id, IndexColumn[] columns,
IndexType indexType, boolean create, Session session) { IndexType indexType, boolean create, Session session) {
initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType); initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType);
this.multiVersion = database.isMultiVersion(); this.multiVersion = database.isMVStore();
// trace = database.getTrace(Trace.PAGE_STORE + "_di"); // trace = database.getTrace(Trace.PAGE_STORE + "_di");
// trace.setLevel(TraceSystem.DEBUG); // trace.setLevel(TraceSystem.DEBUG);
......
...@@ -44,7 +44,7 @@ public class ScanIndex extends BaseIndex { ...@@ -44,7 +44,7 @@ public class ScanIndex extends BaseIndex {
public ScanIndex(RegularTable table, int id, IndexColumn[] columns, public ScanIndex(RegularTable table, int id, IndexColumn[] columns,
IndexType indexType) { IndexType indexType) {
initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType); initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType);
if (database.isMultiVersion()) { if (database.isMVStore()) {
sessionRowCount = new HashMap<>(); sessionRowCount = new HashMap<>();
} else { } else {
sessionRowCount = null; sessionRowCount = null;
...@@ -67,7 +67,7 @@ public class ScanIndex extends BaseIndex { ...@@ -67,7 +67,7 @@ public class ScanIndex extends BaseIndex {
tableData.setRowCount(0); tableData.setRowCount(0);
rowCount = 0; rowCount = 0;
rowCountDiff = 0; rowCountDiff = 0;
if (database.isMultiVersion()) { if (database.isMVStore()) {
sessionRowCount.clear(); sessionRowCount.clear();
} }
} }
...@@ -102,7 +102,7 @@ public class ScanIndex extends BaseIndex { ...@@ -102,7 +102,7 @@ public class ScanIndex extends BaseIndex {
rows.set((int) key, row); rows.set((int) key, row);
} }
row.setDeleted(false); row.setDeleted(false);
if (database.isMultiVersion()) { if (database.isMVStore()) {
if (delta == null) { if (delta == null) {
delta = new HashSet<>(); delta = new HashSet<>();
} }
...@@ -117,7 +117,7 @@ public class ScanIndex extends BaseIndex { ...@@ -117,7 +117,7 @@ public class ScanIndex extends BaseIndex {
@Override @Override
public void commit(int operation, Row row) { public void commit(int operation, Row row) {
if (database.isMultiVersion()) { if (database.isMVStore()) {
if (delta != null) { if (delta != null) {
delta.remove(row); delta.remove(row);
} }
...@@ -127,7 +127,7 @@ public class ScanIndex extends BaseIndex { ...@@ -127,7 +127,7 @@ public class ScanIndex extends BaseIndex {
} }
private void incrementRowCount(int sessionId, int count) { private void incrementRowCount(int sessionId, int count) {
if (database.isMultiVersion()) { if (database.isMVStore()) {
Integer id = sessionId; Integer id = sessionId;
Integer c = sessionRowCount.get(id); Integer c = sessionRowCount.get(id);
int current = c == null ? 0 : c.intValue(); int current = c == null ? 0 : c.intValue();
...@@ -139,7 +139,7 @@ public class ScanIndex extends BaseIndex { ...@@ -139,7 +139,7 @@ public class ScanIndex extends BaseIndex {
@Override @Override
public void remove(Session session, Row row) { public void remove(Session session, Row row) {
// in-memory // in-memory
if (!database.isMultiVersion() && rowCount == 1) { if (!database.isMVStore() && rowCount == 1) {
rows = Utils.newSmallArrayList(); rows = Utils.newSmallArrayList();
firstFree = -1; firstFree = -1;
} else { } else {
...@@ -153,7 +153,7 @@ public class ScanIndex extends BaseIndex { ...@@ -153,7 +153,7 @@ public class ScanIndex extends BaseIndex {
rows.set((int) key, free); rows.set((int) key, free);
firstFree = key; firstFree = key;
} }
if (database.isMultiVersion()) { if (database.isMVStore()) {
// if storage is null, the delete flag is not yet set // if storage is null, the delete flag is not yet set
row.setDeleted(true); row.setDeleted(true);
if (delta == null) { if (delta == null) {
...@@ -170,7 +170,7 @@ public class ScanIndex extends BaseIndex { ...@@ -170,7 +170,7 @@ public class ScanIndex extends BaseIndex {
@Override @Override
public Cursor find(Session session, SearchRow first, SearchRow last) { public Cursor find(Session session, SearchRow first, SearchRow last) {
return new ScanCursor(session, this, database.isMultiVersion()); return new ScanCursor(session, this, database.isMVStore());
} }
@Override @Override
...@@ -182,7 +182,7 @@ public class ScanIndex extends BaseIndex { ...@@ -182,7 +182,7 @@ public class ScanIndex extends BaseIndex {
@Override @Override
public long getRowCount(Session session) { public long getRowCount(Session session) {
if (database.isMultiVersion()) { if (database.isMVStore()) {
Integer i = sessionRowCount.get(session.getId()); Integer i = sessionRowCount.get(session.getId());
long count = i == null ? 0 : i.intValue(); long count = i == null ? 0 : i.intValue();
count += rowCount; count += rowCount;
......
...@@ -116,7 +116,7 @@ public class DatabaseInfo implements DatabaseInfoMBean { ...@@ -116,7 +116,7 @@ public class DatabaseInfo implements DatabaseInfoMBean {
@Override @Override
public boolean isMvcc() { public boolean isMvcc() {
return database.isMultiVersion(); return database.isMVStore();
} }
@Override @Override
......
...@@ -167,7 +167,7 @@ public class MVTable extends TableBase { ...@@ -167,7 +167,7 @@ public class MVTable extends TableBase {
if (lockMode == Constants.LOCK_MODE_OFF) { if (lockMode == Constants.LOCK_MODE_OFF) {
return false; return false;
} }
if (!forceLockEvenInMvcc && database.isMultiVersion()) { if (!forceLockEvenInMvcc && database.isMVStore()) {
// MVCC: update, delete, and insert use a shared lock. // MVCC: update, delete, and insert use a shared lock.
// Select doesn't lock except when using FOR UPDATE and // Select doesn't lock except when using FOR UPDATE and
// the system property h2.selectForUpdateMvcc // the system property h2.selectForUpdateMvcc
...@@ -310,7 +310,7 @@ public class MVTable extends TableBase { ...@@ -310,7 +310,7 @@ public class MVTable extends TableBase {
if (lockExclusiveSession == null) { if (lockExclusiveSession == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
if (!database.isMultiThreaded() && if (!database.isMultiThreaded() &&
!database.isMultiVersion()) { !database.isMVStore()) {
// READ_COMMITTED: a read lock is acquired, // READ_COMMITTED: a read lock is acquired,
// but released immediately after the operation // but released immediately after the operation
// is complete. // is complete.
......
...@@ -360,13 +360,7 @@ public class PageStore implements CacheWriter { ...@@ -360,13 +360,7 @@ public class PageStore implements CacheWriter {
readVariableHeader(); readVariableHeader();
log = new PageLog(this); log = new PageLog(this);
log.openForReading(logKey, logFirstTrunkPage, logFirstDataPage); log.openForReading(logKey, logFirstTrunkPage, logFirstDataPage);
boolean old = database.isMultiVersion();
// temporarily disabling multi-version concurrency, because
// the multi-version index sometimes compares rows
// and the LOB storage is not yet available.
database.setMultiVersion(false);
boolean isEmpty = recover(); boolean isEmpty = recover();
database.setMultiVersion(old);
if (!database.isReadOnly()) { if (!database.isReadOnly()) {
readMode = true; readMode = true;
if (!isEmpty || !SysProperties.MODIFY_ON_WRITE || tempObjects != null) { if (!isEmpty || !SysProperties.MODIFY_ON_WRITE || tempObjects != null) {
......
...@@ -1043,7 +1043,6 @@ public class MetaTable extends Table { ...@@ -1043,7 +1043,6 @@ public class MetaTable extends Table {
"FALSE" : "TRUE"); "FALSE" : "TRUE");
add(rows, "MODE", database.getMode().getName()); add(rows, "MODE", database.getMode().getName());
add(rows, "MULTI_THREADED", database.isMultiThreaded() ? "1" : "0"); add(rows, "MULTI_THREADED", database.isMultiThreaded() ? "1" : "0");
add(rows, "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE");
add(rows, "QUERY_TIMEOUT", Integer.toString(session.getQueryTimeout())); add(rows, "QUERY_TIMEOUT", Integer.toString(session.getQueryTimeout()));
add(rows, "RETENTION_TIME", Integer.toString(database.getRetentionTime())); add(rows, "RETENTION_TIME", Integer.toString(database.getRetentionTime()));
add(rows, "LOG", Integer.toString(database.getLogMode())); add(rows, "LOG", Integer.toString(database.getLogMode()));
......
...@@ -116,7 +116,7 @@ public class RegularTable extends TableBase { ...@@ -116,7 +116,7 @@ public class RegularTable extends TableBase {
@Override @Override
public void addRow(Session session, Row row) { public void addRow(Session session, Row row) {
lastModificationId = database.getNextModificationDataId(); lastModificationId = database.getNextModificationDataId();
if (database.isMultiVersion()) { if (database.isMVStore()) {
row.setSessionId(session.getId()); row.setSessionId(session.getId());
} }
int i = 0; int i = 0;
...@@ -167,7 +167,7 @@ public class RegularTable extends TableBase { ...@@ -167,7 +167,7 @@ public class RegularTable extends TableBase {
} }
private void checkRowCount(Session session, Index index, int offset) { private void checkRowCount(Session session, Index index, int offset) {
if (SysProperties.CHECK && !database.isMultiVersion()) { if (SysProperties.CHECK && !database.isMVStore()) {
if (!(index instanceof PageDelegateIndex)) { if (!(index instanceof PageDelegateIndex)) {
long rc = index.getRowCount(session); long rc = index.getRowCount(session);
if (rc != rowCount + offset) { if (rc != rowCount + offset) {
...@@ -259,7 +259,7 @@ public class RegularTable extends TableBase { ...@@ -259,7 +259,7 @@ public class RegularTable extends TableBase {
index = new TreeIndex(this, indexId, indexName, cols, indexType); index = new TreeIndex(this, indexId, indexName, cols, indexType);
} }
} }
if (database.isMultiVersion()) { if (database.isMVStore()) {
index = new MultiVersionIndex(index, this); index = new MultiVersionIndex(index, this);
} }
if (index.needRebuild() && rowCount > 0) { if (index.needRebuild() && rowCount > 0) {
...@@ -366,7 +366,7 @@ public class RegularTable extends TableBase { ...@@ -366,7 +366,7 @@ public class RegularTable extends TableBase {
@Override @Override
public long getRowCount(Session session) { public long getRowCount(Session session) {
if (database.isMultiVersion()) { if (database.isMVStore()) {
return getScanIndex(session).getRowCount(session); return getScanIndex(session).getRowCount(session);
} }
return rowCount; return rowCount;
...@@ -374,7 +374,7 @@ public class RegularTable extends TableBase { ...@@ -374,7 +374,7 @@ public class RegularTable extends TableBase {
@Override @Override
public void removeRow(Session session, Row row) { public void removeRow(Session session, Row row) {
if (database.isMultiVersion()) { if (database.isMVStore()) {
if (row.isDeleted()) { if (row.isDeleted()) {
throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, getName()); throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, getName());
} }
...@@ -444,7 +444,7 @@ public class RegularTable extends TableBase { ...@@ -444,7 +444,7 @@ public class RegularTable extends TableBase {
if (lockMode == Constants.LOCK_MODE_OFF) { if (lockMode == Constants.LOCK_MODE_OFF) {
return lockExclusiveSession != null; return lockExclusiveSession != null;
} }
if (!forceLockEvenInMvcc && database.isMultiVersion()) { if (!forceLockEvenInMvcc && database.isMVStore()) {
// MVCC: update, delete, and insert use a shared lock. // MVCC: update, delete, and insert use a shared lock.
// Select doesn't lock except when using FOR UPDATE // Select doesn't lock except when using FOR UPDATE
if (exclusive) { if (exclusive) {
...@@ -550,7 +550,7 @@ public class RegularTable extends TableBase { ...@@ -550,7 +550,7 @@ public class RegularTable extends TableBase {
} else { } else {
if (lockExclusiveSession == null) { if (lockExclusiveSession == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
if (!database.isMultiThreaded() && !database.isMultiVersion()) { if (!database.isMultiThreaded() && !database.isMVStore()) {
// READ_COMMITTED: a read lock is acquired, // READ_COMMITTED: a read lock is acquired,
// but released immediately after the operation // but released immediately after the operation
// is complete. // is complete.
......
...@@ -251,7 +251,6 @@ public abstract class TestBase { ...@@ -251,7 +251,6 @@ public abstract class TestBase {
if (name.startsWith("jdbc:")) { if (name.startsWith("jdbc:")) {
if (config.mvStore) { if (config.mvStore) {
name = addOption(name, "MV_STORE", "true"); name = addOption(name, "MV_STORE", "true");
// name = addOption(name, "MVCC", "true");
} else { } else {
name = addOption(name, "MV_STORE", "false"); name = addOption(name, "MV_STORE", "false");
} }
......
...@@ -527,7 +527,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp ...@@ -527,7 +527,7 @@ public class TestGeneralCommonTableQueries extends AbstractBaseForCommonTableExp
config = new TestAll(); config = new TestAll();
try { try {
// Test with settings: lazy mvStore memory mvcc multiThreaded // Test with settings: lazy mvStore memory multiThreaded
// connection url is // connection url is
// mem:script;MV_STORE=true;LOG=1;LOCK_TIMEOUT=50; // mem:script;MV_STORE=true;LOG=1;LOCK_TIMEOUT=50;
// MULTI_THREADED=TRUE;LAZY_QUERY_EXECUTION=1 // MULTI_THREADED=TRUE;LAZY_QUERY_EXECUTION=1
......
...@@ -36,27 +36,9 @@ public class TestMvcc1 extends TestBase { ...@@ -36,27 +36,9 @@ public class TestMvcc1 extends TestBase {
@Override @Override
public void test() throws SQLException { public void test() throws SQLException {
testCases(); testCases();
testSetMode();
deleteDb("mvcc1"); deleteDb("mvcc1");
} }
private void testSetMode() throws SQLException {
deleteDb("mvcc1");
c1 = getConnection("mvcc1;MVCC=FALSE");
Statement stat = c1.createStatement();
ResultSet rs = stat.executeQuery(
"select * from information_schema.settings where name='MVCC'");
rs.next();
assertEquals("FALSE", rs.getString("VALUE"));
assertThrows(ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, stat).
execute("SET MVCC TRUE");
rs = stat.executeQuery("select * from information_schema.settings " +
"where name='MVCC'");
rs.next();
assertEquals("FALSE", rs.getString("VALUE"));
c1.close();
}
private void testCases() throws SQLException { private void testCases() throws SQLException {
if (!config.mvStore) { if (!config.mvStore) {
return; return;
......
...@@ -82,12 +82,10 @@ public class TestMVTableEngine extends TestBase { ...@@ -82,12 +82,10 @@ public class TestMVTableEngine extends TestBase {
testAutoCommit(); testAutoCommit();
testReopen(); testReopen();
testBlob(); testBlob();
testExclusiveLock();
testEncryption(); testEncryption();
testReadOnly(); testReadOnly();
testReuseDiskSpace(); testReuseDiskSpace();
testDataTypes(); testDataTypes();
testLocking();
testSimple(); testSimple();
if (!config.travis) { if (!config.travis) {
testReverseDeletePerformance(); testReverseDeletePerformance();
...@@ -1112,29 +1110,6 @@ public class TestMVTableEngine extends TestBase { ...@@ -1112,29 +1110,6 @@ public class TestMVTableEngine extends TestBase {
conn.close(); conn.close();
} }
private void testExclusiveLock() throws Exception {
deleteDb(getTestName());
String dbName = getTestName() + ";MV_STORE=TRUE;MVCC=FALSE";
Connection conn, conn2;
Statement stat, stat2;
conn = getConnection(dbName);
stat = conn.createStatement();
stat.execute("create table test(id int)");
stat.execute("insert into test values(1)");
conn.setAutoCommit(false);
// stat.execute("update test set id = 2");
stat.executeQuery("select * from test for update");
conn2 = getConnection(dbName);
stat2 = conn2.createStatement();
ResultSet rs2 = stat2.executeQuery(
"select * from information_schema.locks");
assertTrue(rs2.next());
assertEquals("TEST", rs2.getString("table_name"));
assertEquals("WRITE", rs2.getString("lock_type"));
conn2.close();
conn.close();
}
private void testReadOnly() throws Exception { private void testReadOnly() throws Exception {
if (config.memory) { if (config.memory) {
return; return;
...@@ -1343,42 +1318,6 @@ public class TestMVTableEngine extends TestBase { ...@@ -1343,42 +1318,6 @@ public class TestMVTableEngine extends TestBase {
conn.close(); conn.close();
} }
private void testLocking() throws Exception {
deleteDb(getTestName());
String dbName = getTestName() + ";MV_STORE=TRUE;MVCC=FALSE";
Connection conn = getConnection(dbName);
Statement stat = conn.createStatement();
stat.execute("set lock_timeout 1000");
stat.execute("create table a(id int primary key, name varchar)");
stat.execute("create table b(id int primary key, name varchar)");
Connection conn1 = getConnection(dbName);
final Statement stat1 = conn1.createStatement();
stat1.execute("set lock_timeout 1000");
conn.setAutoCommit(false);
conn1.setAutoCommit(false);
stat.execute("insert into a values(1, 'Hello')");
stat1.execute("insert into b values(1, 'Hello')");
Task t = new Task() {
@Override
public void call() throws Exception {
stat1.execute("insert into a values(2, 'World')");
}
};
t.execute();
try {
stat.execute("insert into b values(2, 'World')");
throw t.getException();
} catch (SQLException e) {
assertEquals(e.toString(), ErrorCode.DEADLOCK_1, e.getErrorCode());
}
conn1.close();
conn.close();
}
private void testSimple() throws Exception { private void testSimple() throws Exception {
deleteDb(getTestName()); deleteDb(getTestName());
String dbName = getTestName() + ";MV_STORE=TRUE"; String dbName = getTestName() + ";MV_STORE=TRUE";
......
...@@ -31,7 +31,6 @@ public class TestConcurrentUpdate extends TestBase { ...@@ -31,7 +31,6 @@ public class TestConcurrentUpdate extends TestBase {
config.memory = true; config.memory = true;
config.multiThreaded = true; config.multiThreaded = true;
// config.mvStore = false; // config.mvStore = false;
// config.mvcc = false;
System.out.println(config); System.out.println(config);
TestBase test = createCaller().init(config); TestBase test = createCaller().init(config);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
......
...@@ -167,7 +167,7 @@ public class TestPageStore extends TestBase { ...@@ -167,7 +167,7 @@ public class TestPageStore extends TestBase {
private void testRecoverLobInDatabase() throws SQLException { private void testRecoverLobInDatabase() throws SQLException {
deleteDb("pageStoreRecoverLobInDatabase"); deleteDb("pageStoreRecoverLobInDatabase");
String url = getURL("pageStoreRecoverLobInDatabase;" + String url = getURL("pageStoreRecoverLobInDatabase;" +
"MVCC=TRUE;CACHE_SIZE=1", true); "CACHE_SIZE=1", true);
Connection conn; Connection conn;
Statement stat; Statement stat;
conn = getConnection(url, getUser(), getPassword()); conn = getConnection(url, getUser(), getPassword());
...@@ -182,7 +182,7 @@ public class TestPageStore extends TestBase { ...@@ -182,7 +182,7 @@ public class TestPageStore extends TestBase {
Connection conn2 = getConnection(url, getUser(), getPassword()); Connection conn2 = getConnection(url, getUser(), getPassword());
list.add(conn2); list.add(conn2);
Statement stat2 = conn2.createStatement(); Statement stat2 = conn2.createStatement();
conn2.setAutoCommit(false); // conn2.setAutoCommit(false);
if (r.nextBoolean()) { if (r.nextBoolean()) {
stat2.execute("update test set id = id where id = " + r.nextInt(100)); stat2.execute("update test set id = id where id = " + r.nextInt(100));
} else { } else {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论