Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
e3695afe
提交
e3695afe
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore table engine (reduced memory usage and improved performance)
上级
47da2c44
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
192 行增加
和
186 行删除
+192
-186
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
MVPrimaryIndex.java
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
+1
-1
MVTable.java
h2/src/main/org/h2/mvstore/db/MVTable.java
+1
-1
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+167
-150
DataType.java
h2/src/main/org/h2/mvstore/type/DataType.java
+2
-1
RegularTable.java
h2/src/main/org/h2/table/RegularTable.java
+1
-1
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+16
-28
TestTransactionStore.java
h2/src/test/org/h2/test/store/TestTransactionStore.java
+2
-3
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
e3695afe
...
@@ -18,7 +18,8 @@ Change Log
...
@@ -18,7 +18,8 @@ Change Log
<h1>
Change Log
</h1>
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
The optimization for IN(...) queries combined with OR could result
<ul><li>
The auto-analyze feature now only reads 1000 rows per table instead of 10000.
</li><li>
The optimization for IN(...) queries combined with OR could result
in a strange exception of the type "column x must be included in the group by list".
in a strange exception of the type "column x must be included in the group by list".
</li><li>
Issue 454: Use Charset for type-safety.
</li><li>
Issue 454: Use Charset for type-safety.
</li><li>
Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
</li><li>
Queries with both LIMIT and OFFSET could throw an IllegalArgumentException.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/MVPrimaryIndex.java
浏览文件 @
e3695afe
...
@@ -103,7 +103,7 @@ public class MVPrimaryIndex extends BaseIndex {
...
@@ -103,7 +103,7 @@ public class MVPrimaryIndex extends BaseIndex {
row
.
setKey
(++
lastKey
);
row
.
setKey
(++
lastKey
);
}
}
}
else
{
}
else
{
L
ong
c
=
row
.
getValue
(
mainIndexColumn
).
getLong
();
l
ong
c
=
row
.
getValue
(
mainIndexColumn
).
getLong
();
row
.
setKey
(
c
);
row
.
setKey
(
c
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/MVTable.java
浏览文件 @
e3695afe
...
@@ -554,7 +554,7 @@ public class MVTable extends TableBase {
...
@@ -554,7 +554,7 @@ public class MVTable extends TableBase {
if
(
n
>
0
)
{
if
(
n
>
0
)
{
nextAnalyze
=
n
;
nextAnalyze
=
n
;
}
}
int
rows
=
session
.
getDatabase
().
getSettings
().
analyzeSample
;
int
rows
=
session
.
getDatabase
().
getSettings
().
analyzeSample
/
10
;
Analyze
.
analyzeTable
(
session
,
this
,
rows
,
false
);
Analyze
.
analyzeTable
(
session
,
this
,
rows
,
false
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
e3695afe
...
@@ -8,7 +8,6 @@ package org.h2.mvstore.db;
...
@@ -8,7 +8,6 @@ package org.h2.mvstore.db;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -29,6 +28,7 @@ public class TransactionStore {
...
@@ -29,6 +28,7 @@ public class TransactionStore {
private
static
final
String
LAST_TRANSACTION_ID
=
"lastTransactionId"
;
private
static
final
String
LAST_TRANSACTION_ID
=
"lastTransactionId"
;
// TODO should not be hardcoded
private
static
final
int
MAX_UNSAVED_PAGES
=
4
*
1024
;
private
static
final
int
MAX_UNSAVED_PAGES
=
4
*
1024
;
/**
/**
...
@@ -37,16 +37,10 @@ public class TransactionStore {
...
@@ -37,16 +37,10 @@ public class TransactionStore {
final
MVStore
store
;
final
MVStore
store
;
/**
/**
* The persisted map of
open transaction
.
* The persisted map of
prepared transactions
.
* Key: transactionId, value: [ status, name ].
* Key: transactionId, value: [ status, name ].
*/
*/
final
MVMap
<
Long
,
Object
[]>
openTransactions
;
final
MVMap
<
Long
,
Object
[]>
preparedTransactions
;
/**
* The map of open transaction objects.
* Key: transactionId, value: transaction object.
*/
final
HashMap
<
Long
,
Transaction
>
openTransactionMap
=
New
.
hashMap
();
/**
/**
* The undo log.
* The undo log.
...
@@ -60,7 +54,8 @@ public class TransactionStore {
...
@@ -60,7 +54,8 @@ public class TransactionStore {
long
lockTimeout
;
long
lockTimeout
;
/**
/**
* The transaction settings. "lastTransaction" the last transaction id.
* The transaction settings. The entry "lastTransaction" contains the last
* transaction id.
*/
*/
private
final
MVMap
<
String
,
String
>
settings
;
private
final
MVMap
<
String
,
String
>
settings
;
...
@@ -86,14 +81,11 @@ public class TransactionStore {
...
@@ -86,14 +81,11 @@ public class TransactionStore {
public
TransactionStore
(
MVStore
store
,
DataType
keyType
)
{
public
TransactionStore
(
MVStore
store
,
DataType
keyType
)
{
this
.
store
=
store
;
this
.
store
=
store
;
settings
=
store
.
openMap
(
"settings"
);
settings
=
store
.
openMap
(
"settings"
);
open
Transactions
=
store
.
openMap
(
"openTransactions"
,
prepared
Transactions
=
store
.
openMap
(
"openTransactions"
,
new
MVMap
.
Builder
<
Long
,
Object
[]>());
new
MVMap
.
Builder
<
Long
,
Object
[]>());
// commit could be faster if we have one undo log per transaction,
// TODO commit of larger transaction could be faster if we have one undo
// or a range delete operation for maps
// log per transaction, or a range delete operation for maps
ArrayType
oldValueType
=
new
ArrayType
(
new
DataType
[]{
VersionedValueType
oldValueType
=
new
VersionedValueType
(
keyType
);
new
ObjectDataType
(),
new
ObjectDataType
(),
keyType
});
ArrayType
valueType
=
new
ArrayType
(
new
DataType
[]{
ArrayType
valueType
=
new
ArrayType
(
new
DataType
[]{
new
ObjectDataType
(),
new
ObjectDataType
(),
keyType
,
new
ObjectDataType
(),
new
ObjectDataType
(),
keyType
,
oldValueType
oldValueType
...
@@ -112,36 +104,39 @@ public class TransactionStore {
...
@@ -112,36 +104,39 @@ public class TransactionStore {
lastTransactionId
=
Long
.
parseLong
(
s
);
lastTransactionId
=
Long
.
parseLong
(
s
);
lastTransactionIdStored
=
lastTransactionId
;
lastTransactionIdStored
=
lastTransactionId
;
}
}
Long
lastKey
=
open
Transactions
.
lastKey
();
Long
lastKey
=
prepared
Transactions
.
lastKey
();
if
(
lastKey
!=
null
&&
lastKey
.
longValue
()
>
lastTransactionId
)
{
if
(
lastKey
!=
null
&&
lastKey
.
longValue
()
>
lastTransactionId
)
{
throw
DataUtils
.
newIllegalStateException
(
"Last transaction not stored"
);
throw
DataUtils
.
newIllegalStateException
(
"Last transaction not stored"
);
}
}
Cursor
<
Long
>
cursor
=
openTransactions
.
keyIterator
(
null
);
while
(
cursor
.
hasNext
())
{
long
id
=
cursor
.
next
();
Object
[]
data
=
openTransactions
.
get
(
id
);
int
status
=
(
Integer
)
data
[
0
];
String
name
=
(
String
)
data
[
1
];
long
[]
next
=
{
id
+
1
,
-
1
};
long
[]
last
=
undoLog
.
floorKey
(
next
);
if
(
last
==
null
)
{
// no entry
}
else
if
(
last
[
0
]
==
id
)
{
Transaction
t
=
new
Transaction
(
this
,
id
,
status
,
name
,
last
[
1
]);
t
.
setStored
(
true
);
openTransactionMap
.
put
(
id
,
t
);
}
}
}
}
/**
/**
* Get the list of
currently open
transactions that have pending writes.
* Get the list of
unclosed
transactions that have pending writes.
*
*
* @return the list of transactions
* @return the list of transactions
(sorted by id)
*/
*/
public
synchronized
List
<
Transaction
>
getOpenTransactions
()
{
public
synchronized
List
<
Transaction
>
getOpenTransactions
()
{
ArrayList
<
Transaction
>
list
=
New
.
arrayList
();
ArrayList
<
Transaction
>
list
=
New
.
arrayList
();
list
.
addAll
(
openTransactionMap
.
values
());
long
[]
key
=
undoLog
.
firstKey
();
while
(
key
!=
null
)
{
long
transactionId
=
key
[
0
];
long
[]
end
=
{
transactionId
,
Long
.
MAX_VALUE
};
key
=
undoLog
.
floorKey
(
end
);
long
logId
=
key
[
1
]
+
1
;
Object
[]
data
=
preparedTransactions
.
get
(
transactionId
);
int
status
;
String
name
;
if
(
data
==
null
)
{
status
=
Transaction
.
STATUS_OPEN
;
name
=
null
;
}
else
{
status
=
(
Integer
)
data
[
0
];
name
=
(
String
)
data
[
1
];
}
Transaction
t
=
new
Transaction
(
this
,
transactionId
,
status
,
name
,
logId
);
list
.
add
(
t
);
key
=
undoLog
.
higherKey
(
end
);
}
return
list
;
return
list
;
}
}
...
@@ -161,41 +156,33 @@ public class TransactionStore {
...
@@ -161,41 +156,33 @@ public class TransactionStore {
*/
*/
public
synchronized
Transaction
begin
()
{
public
synchronized
Transaction
begin
()
{
long
transactionId
=
lastTransactionId
++;
long
transactionId
=
lastTransactionId
++;
if
(
lastTransactionId
>
lastTransactionIdStored
)
{
lastTransactionIdStored
+=
64
;
settings
.
put
(
LAST_TRANSACTION_ID
,
""
+
lastTransactionIdStored
);
}
int
status
=
Transaction
.
STATUS_OPEN
;
int
status
=
Transaction
.
STATUS_OPEN
;
return
new
Transaction
(
this
,
transactionId
,
status
,
null
,
0
);
return
new
Transaction
(
this
,
transactionId
,
status
,
null
,
0
);
}
}
private
void
storeTransaction
(
Transaction
t
)
{
private
void
commitIfNeeded
(
)
{
if
(
store
.
getUnsavedPageCount
()
>
MAX_UNSAVED_PAGES
)
{
if
(
store
.
getUnsavedPageCount
()
>
MAX_UNSAVED_PAGES
)
{
store
.
commit
();
store
.
commit
();
}
store
.
store
();
if
(
t
.
isStored
())
{
return
;
}
t
.
setStored
(
true
);
long
transactionId
=
t
.
getId
();
Object
[]
v
=
{
t
.
getStatus
(),
null
};
openTransactions
.
put
(
transactionId
,
v
);
openTransactionMap
.
put
(
transactionId
,
t
);
if
(
lastTransactionId
>
lastTransactionIdStored
)
{
lastTransactionIdStored
+=
32
;
settings
.
put
(
LAST_TRANSACTION_ID
,
""
+
lastTransactionIdStored
);
}
}
}
}
/**
/**
*
Prepa
re a transaction.
*
Sto
re a transaction.
*
*
* @param t
ransactionId the transaction id
* @param t
the transaction
*/
*/
void
prepare
(
Transaction
t
)
{
void
storeTransaction
(
Transaction
t
)
{
storeTransaction
(
t
);
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_PREPARED
||
t
.
getName
()
!=
null
)
{
Object
[]
old
=
openTransactions
.
get
(
t
.
getId
());
Object
[]
v
=
{
t
.
getStatus
(),
t
.
getName
()
};
Object
[]
v
=
{
Transaction
.
STATUS_PREPARED
,
old
[
1
]
};
preparedTransactions
.
put
(
t
.
getId
(),
v
);
openTransactions
.
put
(
t
.
getId
(),
v
);
}
store
.
commit
();
}
}
/**
/**
* Log an entry.
* Log an entry.
*
*
...
@@ -208,25 +195,12 @@ public class TransactionStore {
...
@@ -208,25 +195,12 @@ public class TransactionStore {
*/
*/
void
log
(
Transaction
t
,
long
logId
,
int
opType
,
int
mapId
,
void
log
(
Transaction
t
,
long
logId
,
int
opType
,
int
mapId
,
Object
key
,
Object
oldValue
)
{
Object
key
,
Object
oldValue
)
{
storeTransaction
(
t
);
commitIfNeeded
(
);
long
[]
undoKey
=
{
t
.
getId
(),
logId
};
long
[]
undoKey
=
{
t
.
getId
(),
logId
};
Object
[]
log
=
new
Object
[]
{
opType
,
mapId
,
key
,
oldValue
};
Object
[]
log
=
new
Object
[]
{
opType
,
mapId
,
key
,
oldValue
};
undoLog
.
put
(
undoKey
,
log
);
undoLog
.
put
(
undoKey
,
log
);
}
}
/**
* Set the name of a transaction.
*
* @param t the transaction
* @param name the new name
*/
void
setTransactionName
(
Transaction
t
,
String
name
)
{
storeTransaction
(
t
);
Object
[]
old
=
openTransactions
.
get
(
t
.
getId
());
Object
[]
v
=
{
old
[
0
],
name
};
openTransactions
.
put
(
t
.
getId
(),
v
);
}
/**
/**
* Commit a transaction.
* Commit a transaction.
*
*
...
@@ -240,6 +214,7 @@ public class TransactionStore {
...
@@ -240,6 +214,7 @@ public class TransactionStore {
for
(
long
logId
=
0
;
logId
<
maxLogId
;
logId
++)
{
for
(
long
logId
=
0
;
logId
<
maxLogId
;
logId
++)
{
long
[]
undoKey
=
new
long
[]
{
long
[]
undoKey
=
new
long
[]
{
t
.
getId
(),
logId
};
t
.
getId
(),
logId
};
commitIfNeeded
();
Object
[]
op
=
undoLog
.
get
(
undoKey
);
Object
[]
op
=
undoLog
.
get
(
undoKey
);
int
opType
=
(
Integer
)
op
[
0
];
int
opType
=
(
Integer
)
op
[
0
];
if
(
opType
==
Transaction
.
OP_REMOVE
)
{
if
(
opType
==
Transaction
.
OP_REMOVE
)
{
...
@@ -247,12 +222,12 @@ public class TransactionStore {
...
@@ -247,12 +222,12 @@ public class TransactionStore {
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
MVMap
<
Object
,
Object
[]
>
map
=
store
.
openMap
(
mapName
);
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapName
);
Object
key
=
op
[
2
];
Object
key
=
op
[
2
];
Object
[]
value
=
map
.
get
(
key
);
VersionedValue
value
=
map
.
get
(
key
);
// possibly the entry was added later on
// possibly the entry was added later on
// so we have to check
// so we have to check
if
(
value
[
2
]
==
null
)
{
if
(
value
.
value
==
null
)
{
// remove the value
// remove the value
map
.
remove
(
key
);
map
.
remove
(
key
);
}
}
...
@@ -273,9 +248,21 @@ public class TransactionStore {
...
@@ -273,9 +248,21 @@ public class TransactionStore {
endTransaction
(
t
);
endTransaction
(
t
);
}
}
boolean
isTransactionOpen
(
long
transactionId
)
{
int
todoSlow
;
// if (transactionId < firstOpenTransaction) {
// return false;
// }
long
[]
key
=
{
transactionId
,
-
1
};
key
=
undoLog
.
higherKey
(
key
);
return
key
!=
null
&&
key
[
0
]
==
transactionId
;
}
private
void
endTransaction
(
Transaction
t
)
{
private
void
endTransaction
(
Transaction
t
)
{
openTransactions
.
remove
(
t
.
getId
());
if
(
t
.
getStatus
()
==
Transaction
.
STATUS_PREPARED
)
{
openTransactionMap
.
remove
(
t
.
getId
());
preparedTransactions
.
remove
(
t
.
getId
());
}
t
.
setStatus
(
Transaction
.
STATUS_CLOSED
);
}
}
/**
/**
...
@@ -287,15 +274,16 @@ public class TransactionStore {
...
@@ -287,15 +274,16 @@ public class TransactionStore {
*/
*/
void
rollbackTo
(
Transaction
t
,
long
maxLogId
,
long
toLogId
)
{
void
rollbackTo
(
Transaction
t
,
long
maxLogId
,
long
toLogId
)
{
for
(
long
logId
=
maxLogId
-
1
;
logId
>=
toLogId
;
logId
--)
{
for
(
long
logId
=
maxLogId
-
1
;
logId
>=
toLogId
;
logId
--)
{
commitIfNeeded
();
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
t
.
getId
(),
logId
});
t
.
getId
(),
logId
});
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
int
mapId
=
((
Integer
)
op
[
1
]).
intValue
();
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
Map
<
String
,
String
>
meta
=
store
.
getMetaMap
();
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
m
=
meta
.
get
(
"map."
+
mapId
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
String
mapName
=
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
MVMap
<
Object
,
Object
[]
>
map
=
store
.
openMap
(
mapName
);
MVMap
<
Object
,
VersionedValue
>
map
=
store
.
openMap
(
mapName
);
Object
key
=
op
[
2
];
Object
key
=
op
[
2
];
Object
[]
oldValue
=
(
Object
[]
)
op
[
3
];
VersionedValue
oldValue
=
(
VersionedValue
)
op
[
3
];
if
(
oldValue
==
null
)
{
if
(
oldValue
==
null
)
{
// this transaction added the value
// this transaction added the value
map
.
remove
(
key
);
map
.
remove
(
key
);
...
@@ -345,15 +333,13 @@ public class TransactionStore {
...
@@ -345,15 +333,13 @@ public class TransactionStore {
/**
/**
* The transaction id.
* The transaction id.
*/
*/
final
L
ong
transactionId
;
final
l
ong
transactionId
;
long
logId
;
long
logId
;
private
int
status
;
private
int
status
;
private
String
name
;
private
String
name
;
private
boolean
stored
;
Transaction
(
TransactionStore
store
,
long
transactionId
,
int
status
,
String
name
,
long
logId
)
{
Transaction
(
TransactionStore
store
,
long
transactionId
,
int
status
,
String
name
,
long
logId
)
{
this
.
store
=
store
;
this
.
store
=
store
;
...
@@ -364,48 +350,24 @@ public class TransactionStore {
...
@@ -364,48 +350,24 @@ public class TransactionStore {
this
.
logId
=
logId
;
this
.
logId
=
logId
;
}
}
boolean
isStored
()
{
public
long
getId
()
{
return
stored
;
}
void
setStored
(
boolean
stored
)
{
this
.
stored
=
stored
;
}
/**
* Get the transaction id.
*
* @return the transaction id
*/
public
Long
getId
()
{
return
transactionId
;
return
transactionId
;
}
}
/**
* Get the transaction status.
*
* @return the status
*/
public
int
getStatus
()
{
public
int
getStatus
()
{
return
status
;
return
status
;
}
}
void
setStatus
(
int
status
)
{
this
.
status
=
status
;
}
/**
* Set the name of the transaction.
*
* @param name the new name
*/
public
void
setName
(
String
name
)
{
public
void
setName
(
String
name
)
{
checkOpen
();
checkOpen
();
store
.
setTransactionName
(
this
,
name
);
this
.
name
=
name
;
this
.
name
=
name
;
store
.
storeTransaction
(
this
);
}
}
/**
* Get the name of the transaction.
*
* @return name the name
*/
public
String
getName
()
{
public
String
getName
()
{
return
name
;
return
name
;
}
}
...
@@ -486,8 +448,8 @@ public class TransactionStore {
...
@@ -486,8 +448,8 @@ public class TransactionStore {
*/
*/
public
void
prepare
()
{
public
void
prepare
()
{
checkOpen
();
checkOpen
();
store
.
prepare
(
this
);
status
=
STATUS_PREPARED
;
status
=
STATUS_PREPARED
;
store
.
storeTransaction
(
this
);
}
}
/**
/**
...
@@ -496,7 +458,6 @@ public class TransactionStore {
...
@@ -496,7 +458,6 @@ public class TransactionStore {
public
void
commit
()
{
public
void
commit
()
{
if
(
status
!=
STATUS_CLOSED
)
{
if
(
status
!=
STATUS_CLOSED
)
{
store
.
commit
(
this
,
logId
);
store
.
commit
(
this
,
logId
);
status
=
STATUS_CLOSED
;
}
}
}
}
...
@@ -506,7 +467,6 @@ public class TransactionStore {
...
@@ -506,7 +467,6 @@ public class TransactionStore {
public
void
rollback
()
{
public
void
rollback
()
{
if
(
status
!=
STATUS_CLOSED
)
{
if
(
status
!=
STATUS_CLOSED
)
{
store
.
rollback
(
this
,
logId
);
store
.
rollback
(
this
,
logId
);
status
=
STATUS_CLOSED
;
}
}
}
}
...
@@ -539,7 +499,7 @@ public class TransactionStore {
...
@@ -539,7 +499,7 @@ public class TransactionStore {
* Key: key the key of the data.
* Key: key the key of the data.
* Value: { transactionId, oldVersion, value }
* Value: { transactionId, oldVersion, value }
*/
*/
final
MVMap
<
K
,
Object
[]
>
map
;
final
MVMap
<
K
,
VersionedValue
>
map
;
private
Transaction
transaction
;
private
Transaction
transaction
;
...
@@ -556,16 +516,14 @@ public class TransactionStore {
...
@@ -556,16 +516,14 @@ public class TransactionStore {
TransactionMap
(
Transaction
transaction
,
String
name
,
DataType
keyType
,
TransactionMap
(
Transaction
transaction
,
String
name
,
DataType
keyType
,
DataType
valueType
)
{
DataType
valueType
)
{
this
.
transaction
=
transaction
;
this
.
transaction
=
transaction
;
ArrayType
arrayType
=
new
ArrayType
(
new
DataType
[]
{
VersionedValueType
vt
=
new
VersionedValueType
(
valueType
);
new
ObjectDataType
(),
new
ObjectDataType
(),
valueType
MVMap
.
Builder
<
K
,
VersionedValue
>
builder
=
new
MVMap
.
Builder
<
K
,
VersionedValue
>()
});
.
keyType
(
keyType
).
valueType
(
vt
);
MVMap
.
Builder
<
K
,
Object
[]>
builder
=
new
MVMap
.
Builder
<
K
,
Object
[]>()
.
keyType
(
keyType
).
valueType
(
arrayType
);
map
=
transaction
.
store
.
store
.
openMap
(
name
,
builder
);
map
=
transaction
.
store
.
store
.
openMap
(
name
,
builder
);
mapId
=
map
.
getId
();
mapId
=
map
.
getId
();
}
}
private
TransactionMap
(
Transaction
transaction
,
MVMap
<
K
,
Object
[]
>
map
,
int
mapId
)
{
private
TransactionMap
(
Transaction
transaction
,
MVMap
<
K
,
VersionedValue
>
map
,
int
mapId
)
{
this
.
transaction
=
transaction
;
this
.
transaction
=
transaction
;
this
.
map
=
map
;
this
.
map
=
map
;
this
.
mapId
=
mapId
;
this
.
mapId
=
mapId
;
...
@@ -612,10 +570,6 @@ public class TransactionStore {
...
@@ -612,10 +570,6 @@ public class TransactionStore {
return
size
;
return
size
;
}
}
private
void
checkOpen
()
{
transaction
.
checkOpen
();
}
/**
/**
* Remove an entry.
* Remove an entry.
* <p>
* <p>
...
@@ -646,7 +600,7 @@ public class TransactionStore {
...
@@ -646,7 +600,7 @@ public class TransactionStore {
}
}
private
V
set
(
K
key
,
V
value
)
{
private
V
set
(
K
key
,
V
value
)
{
checkOpen
();
transaction
.
checkOpen
();
long
start
=
0
;
long
start
=
0
;
while
(
true
)
{
while
(
true
)
{
V
old
=
get
(
key
);
V
old
=
get
(
key
);
...
@@ -717,18 +671,18 @@ public class TransactionStore {
...
@@ -717,18 +671,18 @@ public class TransactionStore {
* @return true if the value was set
* @return true if the value was set
*/
*/
public
boolean
trySet
(
K
key
,
V
value
,
boolean
onlyIfUnchanged
)
{
public
boolean
trySet
(
K
key
,
V
value
,
boolean
onlyIfUnchanged
)
{
Object
[]
current
=
map
.
get
(
key
);
VersionedValue
current
=
map
.
get
(
key
);
if
(
onlyIfUnchanged
)
{
if
(
onlyIfUnchanged
)
{
Object
[]
old
=
getArray
(
key
,
readLogId
);
VersionedValue
old
=
getValue
(
key
,
readLogId
);
if
(!
map
.
areValuesEqual
(
old
,
current
))
{
if
(!
map
.
areValuesEqual
(
old
,
current
))
{
long
tx
=
(
Long
)
current
[
0
]
;
long
tx
=
current
.
transactionId
;
if
(
tx
==
transaction
.
transactionId
)
{
if
(
tx
==
transaction
.
transactionId
)
{
if
(
value
==
null
)
{
if
(
value
==
null
)
{
// ignore removing an entry
// ignore removing an entry
// if it was added or changed
// if it was added or changed
// in the same statement
// in the same statement
return
true
;
return
true
;
}
else
if
(
current
[
2
]
==
null
)
{
}
else
if
(
current
.
value
==
null
)
{
// add an entry that was removed
// add an entry that was removed
// in the same statement
// in the same statement
}
else
{
}
else
{
...
@@ -740,7 +694,7 @@ public class TransactionStore {
...
@@ -740,7 +694,7 @@ public class TransactionStore {
}
}
}
}
int
opType
;
int
opType
;
if
(
current
==
null
||
current
[
2
]
==
null
)
{
if
(
current
==
null
||
current
.
value
==
null
)
{
if
(
value
==
null
)
{
if
(
value
==
null
)
{
// remove a removed value
// remove a removed value
opType
=
Transaction
.
OP_SET
;
opType
=
Transaction
.
OP_SET
;
...
@@ -754,19 +708,20 @@ public class TransactionStore {
...
@@ -754,19 +708,20 @@ public class TransactionStore {
opType
=
Transaction
.
OP_SET
;
opType
=
Transaction
.
OP_SET
;
}
}
}
}
Object
[]
newValue
=
{
VersionedValue
newValue
=
new
VersionedValue
();
transaction
.
transactionId
,
newValue
.
transactionId
=
transaction
.
transactionId
;
transaction
.
logId
,
value
};
newValue
.
logId
=
transaction
.
logId
;
newValue
.
value
=
value
;
if
(
current
==
null
)
{
if
(
current
==
null
)
{
// a new value
// a new value
Object
[]
old
=
map
.
putIfAbsent
(
key
,
newValue
);
VersionedValue
old
=
map
.
putIfAbsent
(
key
,
newValue
);
if
(
old
==
null
)
{
if
(
old
==
null
)
{
transaction
.
log
(
opType
,
mapId
,
key
,
current
);
transaction
.
log
(
opType
,
mapId
,
key
,
current
);
return
true
;
return
true
;
}
}
return
false
;
return
false
;
}
}
long
tx
=
(
Long
)
current
[
0
]
;
long
tx
=
current
.
transactionId
;
if
(
tx
==
transaction
.
transactionId
)
{
if
(
tx
==
transaction
.
transactionId
)
{
// added or updated by this transaction
// added or updated by this transaction
if
(
map
.
replace
(
key
,
current
,
newValue
))
{
if
(
map
.
replace
(
key
,
current
,
newValue
))
{
...
@@ -778,7 +733,7 @@ public class TransactionStore {
...
@@ -778,7 +733,7 @@ public class TransactionStore {
return
false
;
return
false
;
}
}
// added or updated by another transaction
// added or updated by another transaction
boolean
open
=
transaction
.
store
.
openTransactions
.
containsKey
(
tx
);
boolean
open
=
transaction
.
store
.
isTransactionOpen
(
tx
);
if
(!
open
)
{
if
(!
open
)
{
// the transaction is committed:
// the transaction is committed:
// overwrite the value
// overwrite the value
...
@@ -832,21 +787,21 @@ public class TransactionStore {
...
@@ -832,21 +787,21 @@ public class TransactionStore {
*/
*/
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
V
get
(
K
key
,
long
maxLogId
)
{
public
V
get
(
K
key
,
long
maxLogId
)
{
checkOpen
();
transaction
.
checkOpen
();
Object
[]
data
=
getArray
(
key
,
maxLogId
);
VersionedValue
data
=
getValue
(
key
,
maxLogId
);
return
data
==
null
?
null
:
(
V
)
data
[
2
]
;
return
data
==
null
?
null
:
(
V
)
data
.
value
;
}
}
private
Object
[]
getArray
(
K
key
,
long
maxLog
)
{
private
VersionedValue
getValue
(
K
key
,
long
maxLog
)
{
Object
[]
data
=
map
.
get
(
key
);
VersionedValue
data
=
map
.
get
(
key
);
while
(
true
)
{
while
(
true
)
{
long
tx
;
long
tx
;
if
(
data
==
null
)
{
if
(
data
==
null
)
{
// doesn't exist or deleted by a committed transaction
// doesn't exist or deleted by a committed transaction
return
null
;
return
null
;
}
}
tx
=
(
Long
)
data
[
0
]
;
tx
=
data
.
transactionId
;
long
logId
=
(
Long
)
data
[
1
]
;
long
logId
=
data
.
logId
;
if
(
tx
==
transaction
.
transactionId
)
{
if
(
tx
==
transaction
.
transactionId
)
{
// added by this transaction
// added by this transaction
if
(
logId
<
maxLog
)
{
if
(
logId
<
maxLog
)
{
...
@@ -854,15 +809,15 @@ public class TransactionStore {
...
@@ -854,15 +809,15 @@ public class TransactionStore {
}
}
}
}
// added or updated by another transaction
// added or updated by another transaction
boolean
open
=
transaction
.
store
.
openTransactions
.
containsKey
(
tx
);
boolean
open
=
transaction
.
store
.
isTransactionOpen
(
tx
);
if
(!
open
)
{
if
(!
open
)
{
// it is committed
// it is committed
return
data
;
return
data
;
}
}
// get the value before the uncommitted transaction
// get the value before the uncommitted transaction
long
[]
x
=
new
long
[]
{
tx
,
logId
};
long
[]
x
=
new
long
[]
{
tx
,
logId
};
data
=
transaction
.
store
.
undoLog
.
get
(
x
);
Object
[]
d
=
transaction
.
store
.
undoLog
.
get
(
x
);
data
=
(
Object
[])
data
[
3
];
data
=
(
VersionedValue
)
d
[
3
];
}
}
}
}
...
@@ -1007,6 +962,68 @@ public class TransactionStore {
...
@@ -1007,6 +962,68 @@ public class TransactionStore {
}
}
}
}
/**
* A versioned value (possibly null). It contains a pointer to the old
* value, and the value itself.
*/
static
class
VersionedValue
{
public
long
transactionId
,
logId
;
public
Object
value
;
}
/**
* The value type for a versioned value.
*/
public
static
class
VersionedValueType
implements
DataType
{
private
final
DataType
valueType
;
VersionedValueType
(
DataType
valueType
)
{
this
.
valueType
=
valueType
;
}
@Override
public
int
getMemory
(
Object
obj
)
{
VersionedValue
v
=
(
VersionedValue
)
obj
;
return
valueType
.
getMemory
(
v
.
value
)
+
16
;
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
==
bObj
)
{
return
0
;
}
VersionedValue
a
=
(
VersionedValue
)
aObj
;
VersionedValue
b
=
(
VersionedValue
)
bObj
;
long
comp
=
a
.
transactionId
-
b
.
transactionId
;
if
(
comp
==
0
)
{
comp
=
a
.
logId
-
b
.
logId
;
if
(
comp
==
0
)
{
return
valueType
.
compare
(
a
.
value
,
b
.
value
);
}
}
return
Long
.
signum
(
comp
);
}
@Override
public
ByteBuffer
write
(
ByteBuffer
buff
,
Object
obj
)
{
VersionedValue
v
=
(
VersionedValue
)
obj
;
DataUtils
.
writeVarLong
(
buff
,
v
.
transactionId
);
DataUtils
.
writeVarLong
(
buff
,
v
.
logId
);
return
valueType
.
write
(
buff
,
v
.
value
);
}
@Override
public
Object
read
(
ByteBuffer
buff
)
{
VersionedValue
v
=
new
VersionedValue
();
v
.
transactionId
=
DataUtils
.
readVarLong
(
buff
);
v
.
logId
=
DataUtils
.
readVarLong
(
buff
);
v
.
value
=
valueType
.
read
(
buff
);
return
v
;
}
}
/**
/**
* A data type that contains an array of objects with the specified data
* A data type that contains an array of objects with the specified data
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/type/DataType.java
浏览文件 @
e3695afe
...
@@ -15,10 +15,11 @@ public interface DataType {
...
@@ -15,10 +15,11 @@ public interface DataType {
/**
/**
* Compare two keys.
* Compare two keys.
*
*
* @param a the first key
* @param a the first key
* @param b the second key
* @param b the second key
* @return -1 if the first key is smaller, 1 if larger, and 0 if equal
* @return -1 if the first key is smaller, 1 if larger, and 0 if equal
* @throws UnsupportedOperationException if the type is not orderable
*/
*/
int
compare
(
Object
a
,
Object
b
);
int
compare
(
Object
a
,
Object
b
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/RegularTable.java
浏览文件 @
e3695afe
...
@@ -401,7 +401,7 @@ public class RegularTable extends TableBase {
...
@@ -401,7 +401,7 @@ public class RegularTable extends TableBase {
if
(
n
>
0
)
{
if
(
n
>
0
)
{
nextAnalyze
=
n
;
nextAnalyze
=
n
;
}
}
int
rows
=
session
.
getDatabase
().
getSettings
().
analyzeSample
;
int
rows
=
session
.
getDatabase
().
getSettings
().
analyzeSample
/
10
;
Analyze
.
analyzeTable
(
session
,
this
,
rows
,
false
);
Analyze
.
analyzeTable
(
session
,
this
,
rows
,
false
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
e3695afe
...
@@ -8,7 +8,6 @@ package org.h2.test.store;
...
@@ -8,7 +8,6 @@ package org.h2.test.store;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.PrintWriter
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.sql.Connection
;
import
java.sql.Connection
;
import
java.sql.DriverManager
;
import
java.sql.DriverManager
;
...
@@ -16,12 +15,12 @@ import java.sql.PreparedStatement;
...
@@ -16,12 +15,12 @@ import java.sql.PreparedStatement;
import
java.sql.ResultSet
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
java.sql.Statement
;
import
org.h2.constant.ErrorCode
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Constants
;
import
org.h2.mvstore.db.MVTableEngine
;
import
org.h2.mvstore.db.MVTableEngine
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
import
org.h2.util.Profiler
;
import
org.h2.util.Task
;
import
org.h2.util.Task
;
/**
/**
...
@@ -39,7 +38,7 @@ public class TestMVTableEngine extends TestBase {
...
@@ -39,7 +38,7 @@ public class TestMVTableEngine extends TestBase {
}
}
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
//
testSpeed();
//
testSpeed();
testReopen
();
testReopen
();
testBlob
();
testBlob
();
testExclusiveLock
();
testExclusiveLock
();
...
@@ -95,32 +94,21 @@ int tes;
...
@@ -95,32 +94,21 @@ int tes;
// -mx4g
// -mx4g
// fast size
// fast size
// 10000 / 8000
// 1278 mvstore;LOCK_MODE=0 before
// 1524 mvstore;LOCK_MODE=0 after
// 790 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 before
// 834 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 after
// 1000 / 80000
// 1753 mvstore;LOCK_MODE=0 before
// 1998 mvstore;LOCK_MODE=0 after
// 810 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 before
// 818 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 after
// 100 / 800000
// 2270 mvstore;LOCK_MODE=0 before
// 2841 mvstore;LOCK_MODE=0 after
// 2107 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 before
// 2116 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 after
// 10 / 800000
// 10 / 800000
// 1312 mvstore;LOCK_MODE=0 before
// 1265 mvstore;LOCK_MODE=0 before
// 1500 mvstore;LOCK_MODE=0 after
// 1434 mvstore;LOCK_MODE=0 after
// 1541 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 before
// 1126 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0;LOG=0 before
// 1551 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0 after
// 1136 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0;LOG=0 after
prep
.
setString
(
2
,
new
String
(
new
char
[
100
]).
replace
((
char
)
0
,
'x'
));
// 100 / 800000
for
(
int
i
=
0
;
i
<
200000
;
i
++)
{
// 2010 mvstore;LOCK_MODE=0 before
// 2261 mvstore;LOCK_MODE=0 after
// 1536 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0;LOG=0 before
// 1546 mvstore;DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine;LOCK_MODE=0;LOG=0 after
prep
.
setString
(
2
,
new
String
(
new
char
[
10
]).
replace
((
char
)
0
,
'x'
));
// for (int i = 0; i < 20000; i++) {
for
(
int
i
=
0
;
i
<
800000
;
i
++)
{
prep
.
setInt
(
1
,
i
);
prep
.
setInt
(
1
,
i
);
prep
.
execute
();
prep
.
execute
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestTransactionStore.java
浏览文件 @
e3695afe
...
@@ -40,7 +40,6 @@ public class TestTransactionStore extends TestBase {
...
@@ -40,7 +40,6 @@ public class TestTransactionStore extends TestBase {
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
FileUtils
.
createDirectories
(
getBaseDir
());
FileUtils
.
createDirectories
(
getBaseDir
());
testKeyIterator
();
testKeyIterator
();
testMultiStatement
();
testMultiStatement
();
testTwoPhaseCommit
();
testTwoPhaseCommit
();
...
@@ -205,7 +204,7 @@ public class TestTransactionStore extends TestBase {
...
@@ -205,7 +204,7 @@ public class TestTransactionStore extends TestBase {
list
=
ts
.
getOpenTransactions
();
list
=
ts
.
getOpenTransactions
();
assertEquals
(
1
,
list
.
size
());
assertEquals
(
1
,
list
.
size
());
txOld
=
list
.
get
(
0
);
txOld
=
list
.
get
(
0
);
assertTrue
(
tx
==
txOld
);
assertTrue
(
tx
.
getId
()
==
txOld
.
getId
()
);
s
.
commit
();
s
.
commit
();
ts
.
close
();
ts
.
close
();
s
.
close
();
s
.
close
();
...
@@ -233,7 +232,7 @@ public class TestTransactionStore extends TestBase {
...
@@ -233,7 +232,7 @@ public class TestTransactionStore extends TestBase {
tx
=
ts
.
begin
();
tx
=
ts
.
begin
();
m
=
tx
.
openMap
(
"test"
);
m
=
tx
.
openMap
(
"test"
);
// TransactionStore was not closed, so we lost some ids
// TransactionStore was not closed, so we lost some ids
assertEquals
(
33
,
tx
.
getId
());
assertEquals
(
65
,
tx
.
getId
());
list
=
ts
.
getOpenTransactions
();
list
=
ts
.
getOpenTransactions
();
assertEquals
(
2
,
list
.
size
());
assertEquals
(
2
,
list
.
size
());
txOld
=
list
.
get
(
1
);
txOld
=
list
.
get
(
1
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论