提交 53c4629a authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: up to 65535 open transactions are now supported. Previously, the limit…

MVStore: up to 65535 open transactions are now supported. Previously, the limit was at most 65535 transactions between the oldest open and the newest open transaction (which was quite a strange limit).
上级 5064fb56
......@@ -1621,6 +1621,7 @@ This database has the following known limitations:
In that case files are split into files of 1 GB by default.
An example database URL is: <code>jdbc:h2:split:~/test</code>.
</li><li>The maximum number of rows per table is 2^64.
</li><li>The maximum number of open transactions is 65535.
</li><li>Main memory requirements: The larger the database, the more main memory is required.
With the current storage mechanism (the page store),
the minimum main memory required is around 1 MB for each 8 GB database file size.
......
......@@ -17,7 +17,10 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>The default limit for in-place LOB objects was changed from 128 to 256 bytes.
<ul><li>MVStore: up to 65535 open transactions are now supported.
Previously, the limit was at most 65535 transactions between the oldest open and the
newest open transaction (which was quite a strange limit).
</li><li>The default limit for in-place LOB objects was changed from 128 to 256 bytes.
This is because each read creates a reference to a LOB, and maintaining the references
is a big overhead. With the higher limit, less references are needed.
</li><li>Tables without columns didn't work.
......
......@@ -89,9 +89,9 @@ public class DataUtils {
public static final int ERROR_TRANSACTION_LOCKED = 101;
/**
* A very old transaction is still open.
* There are too many open transactions.
*/
public static final int ERROR_TRANSACTION_STILL_OPEN = 102;
public static final int ERROR_TOO_MANY_OPEN_TRANSACTIONS = 102;
/**
* The transaction store is in an illegal state (for example, not yet
......
......@@ -7,6 +7,7 @@ package org.h2.mvstore.db;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
......@@ -57,9 +58,9 @@ public class TransactionStore {
private final DataType dataType;
private boolean init;
private final BitSet openTransactions = new BitSet();
private int lastTransactionId;
private boolean init;
private int maxTransactionId = 0xffff;
......@@ -119,8 +120,10 @@ public class TransactionStore {
}
synchronized (undoLog) {
if (undoLog.size() > 0) {
Long key = undoLog.firstKey();
lastTransactionId = getTransactionId(key);
for (Long key : undoLog.keySet()) {
int transactionId = getTransactionId(key);
openTransactions.set(transactionId);
}
}
}
}
......@@ -225,10 +228,14 @@ public class TransactionStore {
DataUtils.ERROR_TRANSACTION_ILLEGAL_STATE,
"Not initialized");
}
int transactionId = ++lastTransactionId;
if (lastTransactionId >= maxTransactionId) {
lastTransactionId = 0;
int transactionId = openTransactions.nextClearBit(1);
if (transactionId > maxTransactionId) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_TOO_MANY_OPEN_TRANSACTIONS,
"There are {0} open transactions",
transactionId - 1);
}
openTransactions.set(transactionId);
int status = Transaction.STATUS_OPEN;
return new Transaction(this, transactionId, status, null, 0);
}
......@@ -263,7 +270,7 @@ public class TransactionStore {
if (logId == 0) {
if (undoLog.containsKey(undoKey)) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_TRANSACTION_STILL_OPEN,
DataUtils.ERROR_TOO_MANY_OPEN_TRANSACTIONS,
"An old transaction with the same id " +
"is still open: {0}",
t.getId());
......@@ -435,6 +442,7 @@ public class TransactionStore {
preparedTransactions.remove(t.getId());
}
t.setStatus(Transaction.STATUS_CLOSED);
openTransactions.clear(t.transactionId);
if (store.getAutoCommitDelay() == 0) {
store.commit();
return;
......
......@@ -49,6 +49,7 @@ public class TestMVTableEngine extends TestBase {
@Override
public void test() throws Exception {
testManyTransactions();
testAppendOnly();
testLowRetentionTime();
testOldAndNew();
......@@ -82,6 +83,23 @@ public class TestMVTableEngine extends TestBase {
testSimple();
}
private void testManyTransactions() throws Exception {
deleteDb("testManyTransactions");
Connection conn = getConnection("testManyTransactions");
Statement stat = conn.createStatement();
stat.execute("create table test()");
conn.setAutoCommit(false);
stat.execute("insert into test values()");
Connection conn2 = getConnection("testManyTransactions");
Statement stat2 = conn2.createStatement();
for (long i = 0; i < 100000; i++) {
stat2.execute("insert into test values()");
}
conn2.close();
conn.close();
}
private void testAppendOnly() throws Exception {
deleteDb("testAppendOnly");
Connection conn = getConnection(
......
......@@ -154,15 +154,21 @@ public class TestTransactionStore extends TestBase {
ts = new TransactionStore(s);
ts.init();
ts.setMaxTransactionId(16);
ArrayList<Transaction> openList = new ArrayList<Transaction>();
for (int i = 0, j = 1; i < 64; i++) {
Transaction t = ts.begin();
openList.add(t);
assertEquals(j, t.getId());
t.commit();
j++;
if (j > 16) {
j = 1;
}
if (openList.size() >= 16) {
t = openList.remove(0);
t.commit();
}
}
s = MVStore.open(null);
ts = new TransactionStore(s);
ts.init();
......@@ -170,10 +176,10 @@ public class TestTransactionStore extends TestBase {
ArrayList<Transaction> fifo = New.arrayList();
int open = 0;
for (int i = 0; i < 64; i++) {
Transaction t = ts.begin();
Transaction t = null;
if (open >= 16) {
try {
t.openMap("data").put(i, i);
t = ts.begin();
fail();
} catch (IllegalStateException e) {
// expected - too many open
......@@ -182,9 +188,10 @@ public class TestTransactionStore extends TestBase {
first.commit();
open--;
}
t = ts.begin();
t.openMap("data").put(i, i);
fifo.add(t);
open++;
t.openMap("data").put(i, i);
}
s.close();
}
......@@ -514,6 +521,8 @@ public class TestTransactionStore extends TestBase {
assertEquals("first transaction", txOld.getName());
txOld.prepare();
assertEquals(Transaction.STATUS_PREPARED, txOld.getStatus());
txOld = list.get(1);
txOld.commit();
s.commit();
s.close();
......@@ -522,6 +531,7 @@ public class TestTransactionStore extends TestBase {
ts.init();
tx = ts.begin();
m = tx.openMap("test");
m.put("3", "Test");
assertEquals(2, tx.getId());
list = ts.getOpenTransactions();
assertEquals(2, list.size());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论