提交 16bdacb2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 101: Rollback of a large transaction could fail.

上级 0e440644
......@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Various improvements in the page store mechanism (still experimental).
<ul><li>Issue 101: Rollback of a large transaction could fail.
</li><li>Various improvements in the page store mechanism (still experimental).
</li><li>The functions LENGTH, OCTET_LENGTH, and BIT_LENGTH now return BIGINT.
</li><li>Data types CLOB and BLOB: the maximum precision was Integer.MAX_VALUE, it is now Long.MAX_VALUE.
</li><li>Multi-threaded kernel: creating and dropping temporary database objects
......
......@@ -85,6 +85,10 @@ public class UndoLog {
}
}
}
for (int k = 0; k < i; k++) {
UndoLogRecord e = records.get(k);
e.invalidatePos();
}
first.seek(file);
}
return entry;
......
......@@ -100,6 +100,7 @@ public class UndoLogRecord {
}
}
try {
row.setDeleted(false);
table.removeRow(session, row);
} catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
......@@ -117,6 +118,7 @@ public class UndoLogRecord {
table.addRow(session, row);
// reset session id, otherwise other session think
// that this row was inserted by this session
commit();
row.commit();
} catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
......@@ -133,6 +135,15 @@ public class UndoLogRecord {
}
}
/**
* Go to the right position in the file.
*
* @param file the file
*/
void seek(FileStore file) throws SQLException {
file.seek(filePos * Constants.FILE_BLOCK_SIZE);
}
/**
* Save the row in the file using the data page as a buffer.
*
......@@ -143,6 +154,8 @@ public class UndoLogRecord {
buff.reset();
buff.writeInt(0);
buff.writeInt(operation);
buff.writeByte(row.isDeleted() ? (byte) 1 : (byte) 0);
buff.writeInt(row.getSessionId());
buff.writeInt(row.getColumnCount());
for (int i = 0; i < row.getColumnCount(); i++) {
buff.writeValue(row.getValue(i));
......@@ -156,15 +169,6 @@ public class UndoLogRecord {
state = STORED;
}
/**
* Go to the right position in the file.
*
* @param file the file
*/
void seek(FileStore file) throws SQLException {
file.seek(filePos * Constants.FILE_BLOCK_SIZE);
}
/**
* Load an undo log record row using the data page as a buffer.
*
......@@ -188,12 +192,16 @@ public class UndoLogRecord {
Message.throwInternalError("operation=" + operation + " op=" + op);
}
}
boolean deleted = buff.readByte() == 1;
int sessionId = buff.readInt();
int columnCount = buff.readInt();
Value[] values = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
values[i] = buff.readValue();
}
row = new Row(values, 0);
row.setDeleted(deleted);
row.setSessionId(sessionId);
state = IN_MEMORY_READ_POS;
}
......@@ -224,4 +232,15 @@ public class UndoLogRecord {
public Row getRow() {
return row;
}
/**
* Change the state from IN_MEMORY to IN_MEMORY_READ_POS. This method is
* called if a later record was read from the temporary file, and therefore
* the position could have changed.
*/
void invalidatePos() {
if (this.state == IN_MEMORY) {
state = IN_MEMORY_READ_POS;
}
}
}
......@@ -17,7 +17,6 @@ import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Random;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
......@@ -36,6 +35,7 @@ public class TestCases extends TestBase {
}
public void test() throws Exception {
testLargeRollback();
testConstraintAlterTable();
testJoinWithView();
testLobDecrypt();
......@@ -72,6 +72,18 @@ public class TestCases extends TestBase {
deleteDb("cases");
}
private void testLargeRollback() throws SQLException {
deleteDb("cases");
Connection conn = getConnection("cases");
conn.createStatement().execute("set MAX_MEMORY_UNDO 8");
conn.createStatement().execute("create table test(id number primary key)");
conn.setAutoCommit(false);
conn.createStatement().execute("insert into test select x from system_range(1, 10)");
conn.createStatement().execute("delete from test");
conn.rollback();
conn.close();
}
private void testConstraintAlterTable() throws SQLException {
deleteDb("cases");
Connection conn = getConnection("cases");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论