Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
1e01a486
提交
1e01a486
authored
16 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Row level locking for MVCC is now enabled.
上级
5ae2eac5
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
85 行增加
和
47 行删除
+85
-47
Command.java
h2/src/main/org/h2/command/Command.java
+25
-9
Constants.java
h2/src/main/org/h2/engine/Constants.java
+0
-13
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+0
-1
TableData.java
h2/src/main/org/h2/table/TableData.java
+2
-2
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+4
-0
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+15
-4
TestRowLocks.java
h2/src/test/org/h2/test/rowlock/TestRowLocks.java
+39
-18
没有找到文件。
h2/src/main/org/h2/command/Command.java
浏览文件 @
1e01a486
...
@@ -191,7 +191,7 @@ public abstract class Command implements CommandInterface {
...
@@ -191,7 +191,7 @@ public abstract class Command implements CommandInterface {
}
}
public
int
executeUpdate
()
throws
SQLException
{
public
int
executeUpdate
()
throws
SQLException
{
startTime
=
System
.
currentTimeMillis
();
long
start
=
startTime
=
System
.
currentTimeMillis
();
Database
database
=
session
.
getDatabase
();
Database
database
=
session
.
getDatabase
();
database
.
allocateReserveMemory
();
database
.
allocateReserveMemory
();
Object
sync
=
database
.
getMultiThreaded
()
?
(
Object
)
session
:
(
Object
)
database
;
Object
sync
=
database
.
getMultiThreaded
()
?
(
Object
)
session
:
(
Object
)
database
;
...
@@ -200,14 +200,30 @@ public abstract class Command implements CommandInterface {
...
@@ -200,14 +200,30 @@ public abstract class Command implements CommandInterface {
int
rollback
=
session
.
getLogId
();
int
rollback
=
session
.
getLogId
();
session
.
setCurrentCommand
(
this
,
startTime
);
session
.
setCurrentCommand
(
this
,
startTime
);
try
{
try
{
database
.
checkPowerOff
();
while
(
true
)
{
try
{
database
.
checkPowerOff
();
return
update
();
try
{
}
catch
(
OutOfMemoryError
e
)
{
return
update
();
database
.
freeReserveMemory
();
}
catch
(
OutOfMemoryError
e
)
{
throw
Message
.
convert
(
e
);
database
.
freeReserveMemory
();
}
catch
(
Throwable
e
)
{
throw
Message
.
convert
(
e
);
throw
Message
.
convert
(
e
);
}
catch
(
SQLException
e
)
{
if
(
e
.
getErrorCode
()
==
ErrorCode
.
CONCURRENT_UPDATE_1
)
{
long
now
=
System
.
currentTimeMillis
();
if
(
now
-
start
>
session
.
getLockTimeout
())
{
throw
e
;
}
try
{
database
.
wait
(
100
);
}
catch
(
InterruptedException
e1
)
{
// ignore
}
continue
;
}
throw
e
;
}
catch
(
Throwable
e
)
{
throw
Message
.
convert
(
e
);
}
}
}
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
database
.
exceptionThrown
(
e
,
sql
);
database
.
exceptionThrown
(
e
,
sql
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Constants.java
浏览文件 @
1e01a486
...
@@ -341,13 +341,6 @@ public class Constants {
...
@@ -341,13 +341,6 @@ 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.
...
@@ -366,12 +359,6 @@ public class Constants {
...
@@ -366,12 +359,6 @@ public class Constants {
* still exists once a database is locked.
* still exists once a database is locked.
*/
*/
public
static
final
int
LOCK_SLEEP
=
1000
;
public
static
final
int
LOCK_SLEEP
=
1000
;
/**
* The divider used to calculate the minimum log file size as a function of
* the largest file (data file or index file).
*/
public
static
final
long
LOG_SIZE_DIVIDER
=
10
;
/**
/**
* The file header used for binary files.
* The file header used for binary files.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
1e01a486
...
@@ -696,7 +696,6 @@ public class JdbcConnection extends TraceObject implements Connection {
...
@@ -696,7 +696,6 @@ 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
:
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableData.java
浏览文件 @
1e01a486
...
@@ -274,7 +274,6 @@ public class TableData extends Table implements RecordReader {
...
@@ -274,7 +274,6 @@ public class TableData extends Table implements RecordReader {
}
}
public
void
removeRow
(
Session
session
,
Row
row
)
throws
SQLException
{
public
void
removeRow
(
Session
session
,
Row
row
)
throws
SQLException
{
lastModificationId
=
database
.
getNextModificationDataId
();
if
(
database
.
isMultiVersion
())
{
if
(
database
.
isMultiVersion
())
{
if
(
row
.
getDeleted
())
{
if
(
row
.
getDeleted
())
{
throw
Message
.
getSQLException
(
ErrorCode
.
CONCURRENT_UPDATE_1
,
getName
());
throw
Message
.
getSQLException
(
ErrorCode
.
CONCURRENT_UPDATE_1
,
getName
());
...
@@ -287,6 +286,7 @@ public class TableData extends Table implements RecordReader {
...
@@ -287,6 +286,7 @@ public class TableData extends Table implements RecordReader {
throw
Message
.
getSQLException
(
ErrorCode
.
CONCURRENT_UPDATE_1
,
getName
());
throw
Message
.
getSQLException
(
ErrorCode
.
CONCURRENT_UPDATE_1
,
getName
());
}
}
}
}
lastModificationId
=
database
.
getNextModificationDataId
();
int
i
=
indexes
.
size
()
-
1
;
int
i
=
indexes
.
size
()
-
1
;
try
{
try
{
for
(;
i
>=
0
;
i
--)
{
for
(;
i
>=
0
;
i
--)
{
...
@@ -377,7 +377,7 @@ public class TableData extends Table implements RecordReader {
...
@@ -377,7 +377,7 @@ public class TableData extends Table implements RecordReader {
}
}
}
else
{
}
else
{
if
(
lockExclusive
==
null
)
{
if
(
lockExclusive
==
null
)
{
if
(
lockMode
==
Constants
.
LOCK_MODE_READ_COMMITTED
||
lockMode
==
Constants
.
LOCK_MODE_ROW
)
{
if
(
lockMode
==
Constants
.
LOCK_MODE_READ_COMMITTED
)
{
if
(!
database
.
getMultiThreaded
()
&&
!
database
.
isMultiVersion
())
{
if
(!
database
.
getMultiThreaded
()
&&
!
database
.
isMultiVersion
())
{
// READ_COMMITTED: a read lock is acquired,
// READ_COMMITTED: a read lock is acquired,
// but released immediately after the operation
// but released immediately after the operation
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
1e01a486
...
@@ -75,6 +75,7 @@ import org.h2.test.jdbcx.TestXASimple;
...
@@ -75,6 +75,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.mvcc.TestMvccMultiThreaded
;
import
org.h2.test.rowlock.TestRowLocks
;
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
;
...
@@ -272,6 +273,8 @@ java org.h2.test.TestAll timer
...
@@ -272,6 +273,8 @@ java org.h2.test.TestAll timer
/*
/*
row level locking for mvcc
Run benchmark with the newest versions of other databases.
Run benchmark with the newest versions of other databases.
documentation: use 'server mode' not 'remote mode'.
documentation: use 'server mode' not 'remote mode'.
...
@@ -540,6 +543,7 @@ http://www.w3schools.com/sql/
...
@@ -540,6 +543,7 @@ http://www.w3schools.com/sql/
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
TestMvccMultiThreaded
().
runTest
(
this
);
new
TestRowLocks
().
runTest
(
this
);
new
TestRowLocks
().
runTest
(
this
);
// synth
// synth
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
1e01a486
...
@@ -60,6 +60,17 @@ public abstract class TestBase {
...
@@ -60,6 +60,17 @@ public abstract class TestBase {
config
.
beforeTest
();
config
.
beforeTest
();
}
}
/**
* Initialize the test configuration using the default settings.
*
* @return itself
*/
public
TestBase
init
()
throws
Exception
{
baseDir
=
getTestDir
(
""
);
this
.
config
=
new
TestAll
();
return
this
;
}
/**
/**
* Initialize the test configuration.
* Initialize the test configuration.
*
*
...
@@ -483,11 +494,11 @@ public abstract class TestBase {
...
@@ -483,11 +494,11 @@ public abstract class TestBase {
}
}
int
al
=
expected
.
length
();
int
al
=
expected
.
length
();
int
bl
=
actual
.
length
();
int
bl
=
actual
.
length
();
if
(
al
>
400
)
{
if
(
al
>
400
0
)
{
expected
=
expected
.
substring
(
0
,
400
);
expected
=
expected
.
substring
(
0
,
400
0
);
}
}
if
(
bl
>
400
)
{
if
(
bl
>
400
0
)
{
actual
=
actual
.
substring
(
0
,
400
);
actual
=
actual
.
substring
(
0
,
400
0
);
}
}
fail
(
"Expected: "
+
expected
+
" ("
+
al
+
") actual: "
+
actual
+
" ("
+
bl
+
")"
);
fail
(
"Expected: "
+
expected
+
" ("
+
al
+
") actual: "
+
actual
+
" ("
+
bl
+
")"
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/rowlock/TestRowLocks.java
浏览文件 @
1e01a486
...
@@ -18,8 +18,12 @@ import org.h2.test.TestBase;
...
@@ -18,8 +18,12 @@ import org.h2.test.TestBase;
*/
*/
public
class
TestRowLocks
extends
TestBase
{
public
class
TestRowLocks
extends
TestBase
{
Statement
s1
,
s2
;
private
Connection
c1
,
c2
;
private
Connection
c1
,
c2
;
private
Statement
s1
,
s2
;
public
static
void
main
(
String
[]
a
)
throws
Exception
{
new
TestRowLocks
().
init
().
test
();
}
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
testSetMode
();
testSetMode
();
...
@@ -30,10 +34,10 @@ public class TestRowLocks extends TestBase {
...
@@ -30,10 +34,10 @@ public class TestRowLocks extends TestBase {
deleteDb
(
"rowLocks"
);
deleteDb
(
"rowLocks"
);
c1
=
getConnection
(
"rowLocks"
);
c1
=
getConnection
(
"rowLocks"
);
Statement
stat
=
c1
.
createStatement
();
Statement
stat
=
c1
.
createStatement
();
stat
.
execute
(
"SET LOCK_MODE
4
"
);
stat
.
execute
(
"SET LOCK_MODE
2
"
);
ResultSet
rs
=
stat
.
executeQuery
(
"call lock_mode()"
);
ResultSet
rs
=
stat
.
executeQuery
(
"call lock_mode()"
);
rs
.
next
();
rs
.
next
();
assertEquals
(
"
4
"
,
rs
.
getString
(
1
));
assertEquals
(
"
2
"
,
rs
.
getString
(
1
));
c1
.
close
();
c1
.
close
();
}
}
...
@@ -41,40 +45,57 @@ public class TestRowLocks extends TestBase {
...
@@ -41,40 +45,57 @@ public class TestRowLocks extends TestBase {
deleteDb
(
"rowLocks"
);
deleteDb
(
"rowLocks"
);
c1
=
getConnection
(
"rowLocks;MVCC=TRUE"
);
c1
=
getConnection
(
"rowLocks;MVCC=TRUE"
);
s1
=
c1
.
createStatement
();
s1
=
c1
.
createStatement
();
s1
.
execute
(
"SET LOCK_
MODE 4
"
);
s1
.
execute
(
"SET LOCK_
TIMEOUT 10000
"
);
s1
.
execute
(
"CREATE TABLE TEST AS SELECT X ID, 'Hello' NAME FROM SYSTEM_RANGE(1, 3)"
);
s1
.
execute
(
"CREATE TABLE TEST AS SELECT X ID, 'Hello' NAME FROM SYSTEM_RANGE(1, 3)"
);
c1
.
commit
();
c1
.
commit
();
c1
.
setAutoCommit
(
false
);
c1
.
setAutoCommit
(
false
);
s1
.
execute
(
"UPDATE TEST SET NAME='Hallo' WHERE ID=1"
);
s1
.
execute
(
"UPDATE TEST SET NAME='Hallo' WHERE ID=1"
);
c2
=
getConnection
(
"rowLocks"
);
c2
=
getConnection
(
"rowLocks"
);
c2
.
setAutoCommit
(
false
);
c2
.
setAutoCommit
(
false
);
s2
=
c2
.
createStatement
();
s2
=
c2
.
createStatement
();
ResultSet
rs
=
s1
.
executeQuery
(
"SELECT NAME FROM TEST WHERE ID=1"
);
assertEquals
(
"Hallo"
,
getSingleValue
(
s1
,
"SELECT NAME FROM TEST WHERE ID=1"
));
rs
.
next
();
assertEquals
(
"Hello"
,
getSingleValue
(
s2
,
"SELECT NAME FROM TEST WHERE ID=1"
));
assertEquals
(
"Hallo"
,
rs
.
getString
(
1
));
rs
=
s2
.
executeQuery
(
"SELECT NAME FROM TEST WHERE ID=1"
);
rs
.
next
();
assertEquals
(
"Hello"
,
rs
.
getString
(
1
));
s2
.
execute
(
"UPDATE TEST SET NAME='Hallo' WHERE ID=2"
);
s2
.
execute
(
"UPDATE TEST SET NAME='Hallo' WHERE ID=2"
);
try
{
try
{
s2
.
executeUpdate
(
"UPDATE TEST SET NAME='H
allo2
' WHERE ID=1"
);
s2
.
executeUpdate
(
"UPDATE TEST SET NAME='H
i
' WHERE ID=1"
);
fail
();
fail
();
}
catch
(
SQLException
e
)
{
}
catch
(
SQLException
e
)
{
assertKnownException
(
e
);
assertKnownException
(
e
);
}
}
c1
.
commit
();
c1
.
commit
();
c2
.
commit
();
c2
.
commit
();
rs
=
s1
.
executeQuery
(
"SELECT NAME FROM TEST WHERE ID=1"
);
rs
.
next
();
assertEquals
(
"Hallo"
,
getSingleValue
(
s1
,
"SELECT NAME FROM TEST WHERE ID=1"
));
assertEquals
(
"Hallo"
,
rs
.
getString
(
1
));
assertEquals
(
"Hallo"
,
getSingleValue
(
s2
,
"SELECT NAME FROM TEST WHERE ID=1"
));
rs
=
s2
.
executeQuery
(
"SELECT NAME FROM TEST WHERE ID=1"
);
rs
.
next
();
s2
.
execute
(
"UPDATE TEST SET NAME='H1' WHERE ID=1"
);
assertEquals
(
"Hallo"
,
rs
.
getString
(
1
));
Thread
thread
=
new
Thread
()
{
public
void
run
()
{
try
{
s1
.
execute
(
"UPDATE TEST SET NAME='H2' WHERE ID=1"
);
}
catch
(
SQLException
e
)
{
e
.
printStackTrace
();
}
}
};
thread
.
start
();
Thread
.
sleep
(
100
);
c2
.
commit
();
thread
.
join
();
c1
.
commit
();
assertEquals
(
"H2"
,
getSingleValue
(
s1
,
"SELECT NAME FROM TEST WHERE ID=1"
));
assertEquals
(
"H2"
,
getSingleValue
(
s2
,
"SELECT NAME FROM TEST WHERE ID=1"
));
c1
.
close
();
c1
.
close
();
c2
.
close
();
c2
.
close
();
}
}
private
String
getSingleValue
(
Statement
stat
,
String
sql
)
throws
Exception
{
ResultSet
rs
=
stat
.
executeQuery
(
sql
);
return
rs
.
next
()
?
rs
.
getString
(
1
)
:
null
;
}
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论