提交 3d206afc authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix two-phase commit in MVStore

上级 6bde4590
......@@ -344,6 +344,7 @@ public class TransactionStore {
}
// TODO could synchronize on blocks (100 at a time or so)
rwLock.writeLock().lock();
int oldStatus = t.status;
try {
t.setStatus(Transaction.STATUS_COMMITTING);
for (long logId = 0; logId < maxLogId; logId++) {
......@@ -383,7 +384,7 @@ public class TransactionStore {
} finally {
rwLock.writeLock().unlock();
}
endTransaction(t);
endTransaction(t, oldStatus);
}
/**
......@@ -467,14 +468,15 @@ public class TransactionStore {
* End this transaction
*
* @param t the transaction
* @param previous status of this transaction
*/
synchronized void endTransaction(Transaction t) {
if (t.getStatus() == Transaction.STATUS_PREPARED) {
synchronized void endTransaction(Transaction t, int oldStatus) {
if (oldStatus == Transaction.STATUS_PREPARED) {
preparedTransactions.remove(t.getId());
}
t.setStatus(Transaction.STATUS_CLOSED);
openTransactions.clear(t.transactionId);
if (store.getAutoCommitDelay() == 0) {
if (oldStatus == Transaction.STATUS_PREPARED || store.getAutoCommitDelay() == 0) {
store.commit();
return;
}
......@@ -825,7 +827,7 @@ public class TransactionStore {
public void rollback() {
checkNotClosed();
store.rollbackTo(this, logId, 0);
store.endTransaction(this);
store.endTransaction(this, status);
}
/**
......
......@@ -48,6 +48,7 @@ public class TestTransaction extends TestBase {
testReferential();
testSavepoint();
testIsolation();
testTwoPhaseCommit();
deleteDb("transaction");
}
......@@ -543,4 +544,42 @@ public class TestTransaction extends TestBase {
stat.execute(sql);
}
private void testTwoPhaseCommit() throws SQLException {
if (config.memory) {
return;
}
deleteDb("transaction2pc");
Connection conn = getConnection("transaction2pc");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST (ID INT PRIMARY KEY)");
conn.setAutoCommit(false);
stat.execute("INSERT INTO TEST VALUES (1)");
stat.execute("PREPARE COMMIT \"#1\"");
conn.commit();
stat.execute("SHUTDOWN IMMEDIATELY");
conn = getConnection("transaction2pc");
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT TRANSACTION, STATE FROM INFORMATION_SCHEMA.IN_DOUBT");
assertFalse(rs.next());
rs = stat.executeQuery("SELECT ID FROM TEST");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
conn.setAutoCommit(false);
stat.execute("INSERT INTO TEST VALUES (2)");
stat.execute("PREPARE COMMIT \"#2\"");
conn.rollback();
stat.execute("SHUTDOWN IMMEDIATELY");
conn = getConnection("transaction2pc");
stat = conn.createStatement();
rs = stat.executeQuery("SELECT TRANSACTION, STATE FROM INFORMATION_SCHEMA.IN_DOUBT");
assertFalse(rs.next());
rs = stat.executeQuery("SELECT ID FROM TEST");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertFalse(rs.next());
conn.close();
deleteDb("transaction2pc");
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论