提交 4f4ab94c authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 28: Multi version concurrency (MVCC): when a row was updated or deleted,…

Issue 28: Multi version concurrency (MVCC): when a row was updated or deleted, but this change was rolled back, the row was not visible by other sessions if no index was used to access it.
上级 8e319b3b
...@@ -16,7 +16,9 @@ Change Log ...@@ -16,7 +16,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Views with multiple joined tables (where one was an outer join) couldn't be used in some cases. Fixed. <ul><li>Multi version concurrency (MVCC): when a row was updated or deleted, but this change was rolled back,
the row was not visible by other sessions if no index was used to access it. Fixed.
</li><li>Views with multiple joined tables (where one was an outer join) couldn't be used in some cases. Fixed.
</li><li>Fixed the Oracle mode: Oracle allows multiple rows with NULL in a unique index. </li><li>Fixed the Oracle mode: Oracle allows multiple rows with NULL in a unique index.
</li><li>Running out of memory could result in incomplete transactions or corrupted databases. Fixed. </li><li>Running out of memory could result in incomplete transactions or corrupted databases. Fixed.
</li><li>When using order by in a query that uses the same table multiple times, the order could </li><li>When using order by in a query that uses the same table multiple times, the order could
......
...@@ -116,6 +116,8 @@ public class UndoLogRecord { ...@@ -116,6 +116,8 @@ public class UndoLogRecord {
try { try {
row.setPos(0); row.setPos(0);
table.addRow(session, row); table.addRow(session, row);
// reset session id, otherwise other session think this row was inserted by this session
row.commit();
} catch (SQLException e) { } catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
&& e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) { && e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
......
...@@ -270,6 +270,12 @@ java org.h2.test.TestAll timer ...@@ -270,6 +270,12 @@ java org.h2.test.TestAll timer
/* /*
drop all objects;
create domain email as varchar;
create table test(e email);
select * from INFORMATION_SCHEMA.COLUMNS where table_name='TEST';
script nosettings;
add download link add download link
Check Eclipse DTP, see also Check Eclipse DTP, see also
......
...@@ -19,6 +19,59 @@ public class TestMvcc3 extends TestBase { ...@@ -19,6 +19,59 @@ public class TestMvcc3 extends TestBase {
public void test() throws Exception { public void test() throws Exception {
testSequence(); testSequence();
testDisableAutoCommit();
testRollback();
}
private void testRollback() throws Exception {
if (!config.mvcc) {
return;
}
deleteDb("mvcc3");
Connection conn = getConnection("mvcc3");
Statement stat = conn.createStatement();
stat.executeUpdate("DROP TABLE IF EXISTS TEST");
stat.executeUpdate("CREATE TABLE TEST (ID NUMBER(2) PRIMARY KEY, VAL VARCHAR(10))");
stat.executeUpdate("INSERT INTO TEST (ID, VAL) VALUES (1, 'Value')");
stat.executeUpdate("INSERT INTO TEST (ID, VAL) VALUES (2, 'Value')");
if (!config.memory) {
conn.close();
conn = getConnection("mvcc3");
}
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
Connection conn2 = getConnection("mvcc3");
conn2.setAutoCommit(false);
conn2.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
conn.createStatement().executeUpdate("UPDATE TEST SET VAL='Updated' WHERE ID = 1");
conn.rollback();
ResultSet rs = conn2.createStatement().executeQuery("SELECT * FROM TEST");
assertTrue(rs.next());
assertEquals("Value", rs.getString(2));
assertTrue(rs.next());
assertEquals("Value", rs.getString(2));
assertFalse(rs.next());
conn.createStatement().executeUpdate("UPDATE TEST SET VAL='Updated' WHERE ID = 1");
conn.commit();
rs = conn2.createStatement().executeQuery("SELECT * FROM TEST ORDER BY ID");
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertEquals("Updated", rs.getString(2));
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertEquals("Value", rs.getString(2));
assertFalse(rs.next());
conn.close();
conn2.close();
}
private void testDisableAutoCommit() throws Exception {
if (!config.mvcc) { if (!config.mvcc) {
return; return;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论