提交 803781b5 authored 作者: Thomas Mueller's avatar Thomas Mueller

start to implement row level locks

上级 4908d970
...@@ -176,8 +176,10 @@ public abstract class Command implements CommandInterface { ...@@ -176,8 +176,10 @@ public abstract class Command implements CommandInterface {
session.commit(false); session.commit(false);
} else if (session.getDatabase().getMultiThreaded()) { } else if (session.getDatabase().getMultiThreaded()) {
Database db = session.getDatabase(); Database db = session.getDatabase();
if (db != null && db.getLockMode() == Constants.LOCK_MODE_READ_COMMITTED) { if (db != null) {
session.unlockReadLocks(); if (db.getLockMode() == Constants.LOCK_MODE_READ_COMMITTED) {
session.unlockReadLocks();
}
} }
} }
if (trace.isInfoEnabled()) { if (trace.isInfoEnabled()) {
......
...@@ -334,6 +334,13 @@ public class Constants { ...@@ -334,6 +334,13 @@ public class Constants {
*/ */
public static final int LOCK_MODE_READ_COMMITTED = 3; public static final int LOCK_MODE_READ_COMMITTED = 3;
/**
* The lock mode that means row level locks are used if possible.
* This lock mode is similar to read committed, but row level locks are
* used instead of table level locks.
*/
public static final int LOCK_MODE_ROW = 4;
/** /**
* The lock mode that means table level locking is used for reads and * The lock mode that means table level locking is used for reads and
* writes. * writes.
......
...@@ -1741,7 +1741,17 @@ public class Database implements DataHandler { ...@@ -1741,7 +1741,17 @@ public class Database implements DataHandler {
return maxMemoryUndo; return maxMemoryUndo;
} }
public void setLockMode(int lockMode) { public void setLockMode(int lockMode) throws SQLException {
switch (lockMode) {
case Constants.LOCK_MODE_OFF:
case Constants.LOCK_MODE_READ_COMMITTED:
case Constants.LOCK_MODE_TABLE:
case Constants.LOCK_MODE_TABLE_GC:
case Constants.LOCK_MODE_ROW:
break;
default:
throw Message.getInvalidValueException("lock mode", "" + lockMode);
}
this.lockMode = lockMode; this.lockMode = lockMode;
} }
......
...@@ -684,6 +684,7 @@ public class JdbcConnection extends TraceObject implements Connection { ...@@ -684,6 +684,7 @@ public class JdbcConnection extends TraceObject implements Connection {
transactionIsolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED; transactionIsolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
break; break;
case Constants.LOCK_MODE_READ_COMMITTED: case Constants.LOCK_MODE_READ_COMMITTED:
case Constants.LOCK_MODE_ROW:
transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED; transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED;
break; break;
case Constants.LOCK_MODE_TABLE: case Constants.LOCK_MODE_TABLE:
......
...@@ -377,13 +377,17 @@ public class TableData extends Table implements RecordReader { ...@@ -377,13 +377,17 @@ public class TableData extends Table implements RecordReader {
} }
} else { } else {
if (lockExclusive == null) { if (lockExclusive == null) {
if (lockMode == Constants.LOCK_MODE_READ_COMMITTED && !database.getMultiThreaded() && !database.isMultiVersion()) { if (lockMode == Constants.LOCK_MODE_READ_COMMITTED || lockMode == Constants.LOCK_MODE_ROW) {
// READ_COMMITTED read locks are acquired but they if (!database.getMultiThreaded() && !database.isMultiVersion()) {
// are released immediately // READ_COMMITTED read locks are acquired but they
// when allowing only one thread, no read locks are // are released immediately
// required // when allowing only one thread, no read locks are
return; // required
} else if (!lockShared.contains(session)) { // row level locks work like read committed
return;
}
}
if (!lockShared.contains(session)) {
traceLock(session, exclusive, "ok"); traceLock(session, exclusive, "ok");
session.addLock(this); session.addLock(this);
lockShared.add(session); lockShared.add(session);
......
...@@ -72,6 +72,7 @@ import org.h2.test.jdbcx.TestXASimple; ...@@ -72,6 +72,7 @@ import org.h2.test.jdbcx.TestXASimple;
import org.h2.test.mvcc.TestMvcc1; import org.h2.test.mvcc.TestMvcc1;
import org.h2.test.mvcc.TestMvcc2; import org.h2.test.mvcc.TestMvcc2;
import org.h2.test.mvcc.TestMvcc3; import org.h2.test.mvcc.TestMvcc3;
import org.h2.test.rowlock.TestRowLocks;
import org.h2.test.server.TestNestedLoop; import org.h2.test.server.TestNestedLoop;
import org.h2.test.server.TestPgServer; import org.h2.test.server.TestPgServer;
import org.h2.test.server.TestWeb; import org.h2.test.server.TestWeb;
...@@ -266,6 +267,8 @@ java org.h2.test.TestAll timer ...@@ -266,6 +267,8 @@ java org.h2.test.TestAll timer
/* /*
row level locking
run the performance tests as part of the unit test run the performance tests as part of the unit test
switch to JDK 1.6 by default switch to JDK 1.6 by default
...@@ -611,10 +614,11 @@ Roadmap: ...@@ -611,10 +614,11 @@ Roadmap:
new TestWeb().runTest(this); new TestWeb().runTest(this);
new TestPgServer().runTest(this); new TestPgServer().runTest(this);
// mvcc // mvcc & row level locking
new TestMvcc1().runTest(this); new TestMvcc1().runTest(this);
new TestMvcc2().runTest(this); new TestMvcc2().runTest(this);
new TestMvcc3().runTest(this); new TestMvcc3().runTest(this);
new TestRowLocks().runTest(this);
// synth // synth
new TestCrashAPI().runTest(this); new TestCrashAPI().runTest(this);
......
...@@ -74,7 +74,7 @@ public class TestCases extends TestBase { ...@@ -74,7 +74,7 @@ public class TestCases extends TestBase {
sql = "delete from " + table; sql = "delete from " + table;
} }
stat.execute(sql); stat.execute(sql);
stat.execute("script to 'test.sql'"); stat.execute("script to '" + baseDir + "/test.sql'");
} }
conn.close(); conn.close();
} }
......
...@@ -104,11 +104,11 @@ public class TestCsv extends TestBase { ...@@ -104,11 +104,11 @@ public class TestCsv extends TestBase {
list.add(new String[]{a, b}); list.add(new String[]{a, b});
prep.execute(); prep.execute();
} }
stat.execute("CALL CSVWRITE('test.csv', 'SELECT * FROM test', 'UTF-8', '|', '#')"); stat.execute("CALL CSVWRITE('" + baseDir + "/test.csv', 'SELECT * FROM test', 'UTF-8', '|', '#')");
Csv csv = Csv.getInstance(); Csv csv = Csv.getInstance();
csv.setFieldSeparatorRead('|'); csv.setFieldSeparatorRead('|');
csv.setFieldDelimiter('#'); csv.setFieldDelimiter('#');
ResultSet rs = csv.read("test.csv", null, "UTF-8"); ResultSet rs = csv.read(baseDir + "/test.csv", null, "UTF-8");
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
assertTrue(rs.next()); assertTrue(rs.next());
String[] pair = (String[]) list.get(i); String[] pair = (String[]) list.get(i);
......
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.rowlock;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
/**
* Row level locking tests.
*/
public class TestRowLocks extends TestBase {
private Connection c1, c2;
private Statement s1;
public void test() throws Exception {
testSetMode();
testCases();
}
private void testSetMode() throws Exception {
DeleteDbFiles.execute(null, "test", true);
Class.forName("org.h2.Driver");
c1 = DriverManager.getConnection("jdbc:h2:test", "sa", "sa");
Statement stat = c1.createStatement();
stat.execute("SET LOCK_MODE 4");
ResultSet rs = stat.executeQuery("call lock_mode()");
rs.next();
assertEquals("4", rs.getString(1));
c1.close();
}
private void testCases() throws Exception {
deleteDb("rowLocks");
c1 = getConnection("rowLocks");
s1 = c1.createStatement();
s1.execute("SET LOCK_MODE 4");
c2 = getConnection("rowLocks");
// s2 = c2.createStatement();
c1.setAutoCommit(false);
c2.setAutoCommit(false);
c1.close();
c2.close();
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License, Version 1.0,,
and under the Eclipse Public License, Version 1.0
(http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;">
Row level locking tests.
</body></html>
\ No newline at end of file
--- special grammar and test cases --------------------------------------------------------------------------------------------- --- special grammar and test cases ---------------------------------------------------------------------------------------------
CREATE TABLE T(A NULL);
> exception
CREATE TABLE T(A INT);
> ok
ALTER TABLE T ALTER COLUMN A NULL;
> exception
DROP TABLE T;
> ok
CREATE ROLE TEST_A; CREATE ROLE TEST_A;
> ok > ok
......
create table test (id varchar(36) as random_uuid() primary key);
insert into test() values();
delete from test where id = select id from test;
drop table test;
create table test (id varchar(36) as now() primary key);
insert into test() values();
delete from test where id = select id from test;
drop table test;
SELECT SOME(X>4) FROM SYSTEM_RANGE(1,6); SELECT SOME(X>4) FROM SYSTEM_RANGE(1,6);
> TRUE; > TRUE;
SELECT EVERY(X>4) FROM SYSTEM_RANGE(1,6); SELECT EVERY(X>4) FROM SYSTEM_RANGE(1,6);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论