Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
384e5195
提交
384e5195
authored
6 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove MultiVersionIndex (PageStore+MVCC)
上级
acf1f91e
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
3 行增加
和
627 行删除
+3
-627
MultiVersionCursor.java
h2/src/main/org/h2/index/MultiVersionCursor.java
+0
-188
MultiVersionIndex.java
h2/src/main/org/h2/index/MultiVersionIndex.java
+0
-406
PageStore.java
h2/src/main/org/h2/store/PageStore.java
+1
-8
MetaTable.java
h2/src/main/org/h2/table/MetaTable.java
+1
-8
RegularTable.java
h2/src/main/org/h2/table/RegularTable.java
+1
-17
没有找到文件。
h2/src/main/org/h2/index/MultiVersionCursor.java
deleted
100644 → 0
浏览文件 @
acf1f91e
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
index
;
import
org.h2.engine.Session
;
import
org.h2.engine.SysProperties
;
import
org.h2.message.DbException
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
/**
* The cursor implementation for the multi-version index.
*/
public
class
MultiVersionCursor
implements
Cursor
{
private
final
MultiVersionIndex
index
;
private
final
Session
session
;
private
final
Cursor
baseCursor
,
deltaCursor
;
private
final
Object
sync
;
private
SearchRow
baseRow
;
private
Row
deltaRow
;
private
boolean
onBase
;
private
boolean
end
;
private
boolean
needNewDelta
,
needNewBase
;
private
boolean
reverse
;
MultiVersionCursor
(
Session
session
,
MultiVersionIndex
index
,
Cursor
base
,
Cursor
delta
,
Object
sync
)
{
this
.
session
=
session
;
this
.
index
=
index
;
this
.
baseCursor
=
base
;
this
.
deltaCursor
=
delta
;
this
.
sync
=
sync
;
needNewDelta
=
true
;
needNewBase
=
true
;
}
/**
* Load the current row.
*/
void
loadCurrent
()
{
synchronized
(
sync
)
{
baseRow
=
baseCursor
.
getSearchRow
();
deltaRow
=
deltaCursor
.
get
();
needNewDelta
=
false
;
needNewBase
=
false
;
}
}
private
void
loadNext
(
boolean
base
)
{
synchronized
(
sync
)
{
if
(
base
)
{
if
(
step
(
baseCursor
))
{
baseRow
=
baseCursor
.
getSearchRow
();
}
else
{
baseRow
=
null
;
}
}
else
{
if
(
step
(
deltaCursor
))
{
deltaRow
=
deltaCursor
.
get
();
}
else
{
deltaRow
=
null
;
}
}
}
}
private
boolean
step
(
Cursor
cursor
)
{
return
reverse
?
cursor
.
previous
()
:
cursor
.
next
();
}
@Override
public
Row
get
()
{
synchronized
(
sync
)
{
if
(
end
)
{
return
null
;
}
return
onBase
?
baseCursor
.
get
()
:
deltaCursor
.
get
();
}
}
@Override
public
SearchRow
getSearchRow
()
{
synchronized
(
sync
)
{
if
(
end
)
{
return
null
;
}
return
onBase
?
baseCursor
.
getSearchRow
()
:
deltaCursor
.
getSearchRow
();
}
}
@Override
public
boolean
next
()
{
synchronized
(
sync
)
{
if
(
SysProperties
.
CHECK
&&
end
)
{
DbException
.
throwInternalError
();
}
while
(
true
)
{
if
(
needNewDelta
)
{
loadNext
(
false
);
needNewDelta
=
false
;
}
if
(
needNewBase
)
{
loadNext
(
true
);
needNewBase
=
false
;
}
if
(
deltaRow
==
null
)
{
if
(
baseRow
==
null
)
{
end
=
true
;
return
false
;
}
onBase
=
true
;
needNewBase
=
true
;
return
true
;
}
int
sessionId
=
deltaRow
.
getSessionId
();
boolean
isThisSession
=
sessionId
==
session
.
getId
();
boolean
isDeleted
=
deltaRow
.
isDeleted
();
if
(
isThisSession
&&
isDeleted
)
{
needNewDelta
=
true
;
continue
;
}
if
(
baseRow
==
null
)
{
if
(
isDeleted
)
{
if
(
isThisSession
)
{
end
=
true
;
return
false
;
}
// the row was deleted by another session: return it
onBase
=
false
;
needNewDelta
=
true
;
return
true
;
}
DbException
.
throwInternalError
();
}
int
compare
=
index
.
compareRows
(
deltaRow
,
baseRow
);
if
(
compare
==
0
)
{
// can't use compareKeys because the
// version would be compared as well
long
k1
=
deltaRow
.
getKey
();
long
k2
=
baseRow
.
getKey
();
compare
=
Long
.
compare
(
k1
,
k2
);
}
if
(
compare
==
0
)
{
if
(
isDeleted
)
{
if
(
isThisSession
)
{
DbException
.
throwInternalError
();
}
// another session updated the row
}
else
{
if
(
isThisSession
)
{
onBase
=
false
;
needNewBase
=
true
;
needNewDelta
=
true
;
return
true
;
}
// another session inserted the row: ignore
needNewBase
=
true
;
needNewDelta
=
true
;
continue
;
}
}
if
(
compare
>
0
)
{
onBase
=
true
;
needNewBase
=
true
;
return
true
;
}
onBase
=
false
;
needNewDelta
=
true
;
return
true
;
}
}
}
@Override
public
boolean
previous
()
{
reverse
=
true
;
try
{
return
next
();
}
finally
{
reverse
=
false
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/MultiVersionIndex.java
deleted
100644 → 0
浏览文件 @
acf1f91e
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
index
;
import
java.util.ArrayList
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.dml.AllColumnsForPlan
;
import
org.h2.engine.Database
;
import
org.h2.engine.DbObject
;
import
org.h2.engine.Session
;
import
org.h2.message.DbException
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SortOrder
;
import
org.h2.schema.Schema
;
import
org.h2.table.Column
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.RegularTable
;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.value.Value
;
import
org.h2.value.ValueNull
;
/**
* A multi-version index is a combination of a regular index,
* and a in-memory tree index that contains uncommitted changes.
* Uncommitted changes can include new rows, and deleted rows.
*/
public
class
MultiVersionIndex
implements
Index
{
private
final
Index
base
;
private
final
TreeIndex
delta
;
private
final
RegularTable
table
;
private
final
Object
sync
;
private
final
Column
firstColumn
;
public
MultiVersionIndex
(
Index
base
,
RegularTable
table
)
{
this
.
base
=
base
;
this
.
table
=
table
;
IndexType
deltaIndexType
=
IndexType
.
createNonUnique
(
false
);
if
(
base
instanceof
SpatialIndex
)
{
throw
DbException
.
get
(
ErrorCode
.
FEATURE_NOT_SUPPORTED_1
,
"MVCC & spatial index"
);
}
this
.
delta
=
new
TreeIndex
(
table
,
-
1
,
"DELTA"
,
base
.
getIndexColumns
(),
deltaIndexType
);
delta
.
setMultiVersion
(
true
);
this
.
sync
=
base
.
getDatabase
();
this
.
firstColumn
=
base
.
getColumns
()[
0
];
}
@Override
public
void
add
(
Session
session
,
Row
row
)
{
synchronized
(
sync
)
{
base
.
add
(
session
,
row
);
if
(
removeIfExists
(
session
,
row
))
{
// for example rolling back a delete operation
}
else
if
(
row
.
getSessionId
()
!=
0
)
{
// don't insert rows that are added when creating an index
delta
.
add
(
session
,
row
);
}
}
}
@Override
public
void
close
(
Session
session
)
{
synchronized
(
sync
)
{
base
.
close
(
session
);
}
}
@Override
public
boolean
isFindUsingFullTableScan
()
{
return
base
.
isFindUsingFullTableScan
();
}
@Override
public
Cursor
find
(
TableFilter
filter
,
SearchRow
first
,
SearchRow
last
)
{
synchronized
(
sync
)
{
Cursor
baseCursor
=
base
.
find
(
filter
,
first
,
last
);
Cursor
deltaCursor
=
delta
.
find
(
filter
,
first
,
last
);
return
new
MultiVersionCursor
(
filter
.
getSession
(),
this
,
baseCursor
,
deltaCursor
,
sync
);
}
}
@Override
public
Cursor
find
(
Session
session
,
SearchRow
first
,
SearchRow
last
)
{
synchronized
(
sync
)
{
Cursor
baseCursor
=
base
.
find
(
session
,
first
,
last
);
Cursor
deltaCursor
=
delta
.
find
(
session
,
first
,
last
);
return
new
MultiVersionCursor
(
session
,
this
,
baseCursor
,
deltaCursor
,
sync
);
}
}
@Override
public
Cursor
findNext
(
Session
session
,
SearchRow
first
,
SearchRow
last
)
{
throw
DbException
.
throwInternalError
(
toString
());
}
@Override
public
boolean
canFindNext
()
{
// TODO possible, but more complicated
return
false
;
}
@Override
public
boolean
canGetFirstOrLast
()
{
return
base
.
canGetFirstOrLast
()
&&
delta
.
canGetFirstOrLast
();
}
@Override
public
Cursor
findFirstOrLast
(
Session
session
,
boolean
first
)
{
if
(
first
)
{
// TODO optimization: this loops through NULL elements
Cursor
cursor
=
find
(
session
,
null
,
null
);
while
(
cursor
.
next
())
{
SearchRow
row
=
cursor
.
getSearchRow
();
Value
v
=
row
.
getValue
(
firstColumn
.
getColumnId
());
if
(
v
!=
ValueNull
.
INSTANCE
)
{
return
cursor
;
}
}
return
cursor
;
}
Cursor
baseCursor
=
base
.
findFirstOrLast
(
session
,
false
);
Cursor
deltaCursor
=
delta
.
findFirstOrLast
(
session
,
false
);
MultiVersionCursor
cursor
=
new
MultiVersionCursor
(
session
,
this
,
baseCursor
,
deltaCursor
,
sync
);
cursor
.
loadCurrent
();
// TODO optimization: this loops through NULL elements
while
(
cursor
.
previous
())
{
SearchRow
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
break
;
}
Value
v
=
row
.
getValue
(
firstColumn
.
getColumnId
());
if
(
v
!=
ValueNull
.
INSTANCE
)
{
return
cursor
;
}
}
return
cursor
;
}
@Override
public
double
getCost
(
Session
session
,
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
,
AllColumnsForPlan
allColumnsSet
)
{
return
base
.
getCost
(
session
,
masks
,
filters
,
filter
,
sortOrder
,
allColumnsSet
);
}
@Override
public
boolean
needRebuild
()
{
return
base
.
needRebuild
();
}
/**
* Check if there is an uncommitted row with the given key
* within a different session.
*
* @param session the original session
* @param row the row (only the key is checked)
* @return true if there is an uncommitted row
*/
public
boolean
isUncommittedFromOtherSession
(
Session
session
,
Row
row
)
{
Cursor
c
=
delta
.
find
(
session
,
row
,
row
);
while
(
c
.
next
())
{
Row
r
=
c
.
get
();
return
r
.
getSessionId
()
!=
session
.
getId
();
}
return
false
;
}
private
boolean
removeIfExists
(
Session
session
,
Row
row
)
{
// maybe it was inserted by the same session just before
Cursor
c
=
delta
.
find
(
session
,
row
,
row
);
while
(
c
.
next
())
{
Row
r
=
c
.
get
();
if
(
r
.
getKey
()
==
row
.
getKey
()
&&
r
.
getVersion
()
==
row
.
getVersion
())
{
if
(
r
!=
row
&&
table
.
getScanIndex
(
session
).
compareRows
(
r
,
row
)
!=
0
)
{
row
.
setVersion
(
r
.
getVersion
()
+
1
);
}
else
{
delta
.
remove
(
session
,
r
);
return
true
;
}
}
}
return
false
;
}
@Override
public
void
remove
(
Session
session
,
Row
row
)
{
synchronized
(
sync
)
{
base
.
remove
(
session
,
row
);
if
(
removeIfExists
(
session
,
row
))
{
// added and deleted in the same transaction: no change
}
else
{
delta
.
add
(
session
,
row
);
}
}
}
@Override
public
void
remove
(
Session
session
)
{
synchronized
(
sync
)
{
base
.
remove
(
session
);
}
}
@Override
public
void
truncate
(
Session
session
)
{
synchronized
(
sync
)
{
delta
.
truncate
(
session
);
base
.
truncate
(
session
);
}
}
@Override
public
void
commit
(
int
operation
,
Row
row
)
{
synchronized
(
sync
)
{
removeIfExists
(
null
,
row
);
}
}
@Override
public
int
compareRows
(
SearchRow
rowData
,
SearchRow
compare
)
{
return
base
.
compareRows
(
rowData
,
compare
);
}
@Override
public
int
getColumnIndex
(
Column
col
)
{
return
base
.
getColumnIndex
(
col
);
}
@Override
public
boolean
isFirstColumn
(
Column
column
)
{
return
base
.
isFirstColumn
(
column
);
}
@Override
public
Column
[]
getColumns
()
{
return
base
.
getColumns
();
}
@Override
public
IndexColumn
[]
getIndexColumns
()
{
return
base
.
getIndexColumns
();
}
@Override
public
String
getCreateSQL
()
{
return
base
.
getCreateSQL
();
}
@Override
public
String
getCreateSQLForCopy
(
Table
forTable
,
String
quotedName
)
{
return
base
.
getCreateSQLForCopy
(
forTable
,
quotedName
);
}
@Override
public
String
getDropSQL
()
{
return
base
.
getDropSQL
();
}
@Override
public
IndexType
getIndexType
()
{
return
base
.
getIndexType
();
}
@Override
public
String
getPlanSQL
()
{
return
base
.
getPlanSQL
();
}
@Override
public
long
getRowCount
(
Session
session
)
{
return
base
.
getRowCount
(
session
);
}
@Override
public
Table
getTable
()
{
return
base
.
getTable
();
}
@Override
public
int
getType
()
{
return
base
.
getType
();
}
@Override
public
void
removeChildrenAndResources
(
Session
session
)
{
synchronized
(
sync
)
{
table
.
removeIndex
(
this
);
remove
(
session
);
}
}
@Override
public
String
getSQL
()
{
return
base
.
getSQL
();
}
@Override
public
Schema
getSchema
()
{
return
base
.
getSchema
();
}
@Override
public
void
checkRename
()
{
base
.
checkRename
();
}
@Override
public
ArrayList
<
DbObject
>
getChildren
()
{
return
base
.
getChildren
();
}
@Override
public
String
getComment
()
{
return
base
.
getComment
();
}
@Override
public
Database
getDatabase
()
{
return
base
.
getDatabase
();
}
@Override
public
int
getId
()
{
return
base
.
getId
();
}
@Override
public
String
getName
()
{
return
base
.
getName
();
}
@Override
public
boolean
isTemporary
()
{
return
base
.
isTemporary
();
}
@Override
public
void
rename
(
String
newName
)
{
base
.
rename
(
newName
);
}
@Override
public
void
setComment
(
String
comment
)
{
base
.
setComment
(
comment
);
}
@Override
public
void
setTemporary
(
boolean
temporary
)
{
base
.
setTemporary
(
temporary
);
}
@Override
public
long
getRowCountApproximation
()
{
return
base
.
getRowCountApproximation
();
}
@Override
public
long
getDiskSpaceUsed
()
{
return
base
.
getDiskSpaceUsed
();
}
public
Index
getBaseIndex
()
{
return
base
;
}
@Override
public
Row
getRow
(
Session
session
,
long
key
)
{
return
base
.
getRow
(
session
,
key
);
}
@Override
public
boolean
isHidden
()
{
return
base
.
isHidden
();
}
@Override
public
boolean
isRowIdIndex
()
{
return
base
.
isRowIdIndex
()
&&
delta
.
isRowIdIndex
();
}
@Override
public
boolean
canScan
()
{
return
base
.
canScan
();
}
@Override
public
void
setSortedInsertMode
(
boolean
sortedInsertMode
)
{
base
.
setSortedInsertMode
(
sortedInsertMode
);
delta
.
setSortedInsertMode
(
sortedInsertMode
);
}
@Override
public
IndexLookupBatch
createLookupBatch
(
TableFilter
[]
filters
,
int
filter
)
{
// Lookup batching is not supported.
return
null
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/PageStore.java
浏览文件 @
384e5195
...
...
@@ -24,7 +24,6 @@ import org.h2.engine.SysProperties;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.index.IndexType
;
import
org.h2.index.MultiVersionIndex
;
import
org.h2.index.PageBtreeIndex
;
import
org.h2.index.PageBtreeLeaf
;
import
org.h2.index.PageBtreeNode
;
...
...
@@ -1731,13 +1730,7 @@ public class PageStore implements CacheWriter {
}
meta
=
table
.
addIndex
(
session
,
"I"
+
id
,
id
,
cols
,
indexType
,
false
,
null
);
}
PageIndex
index
;
if
(
meta
instanceof
MultiVersionIndex
)
{
index
=
(
PageIndex
)
((
MultiVersionIndex
)
meta
).
getBaseIndex
();
}
else
{
index
=
(
PageIndex
)
meta
;
}
metaObjects
.
put
(
id
,
index
);
metaObjects
.
put
(
id
,
(
PageIndex
)
meta
);
}
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/MetaTable.java
浏览文件 @
384e5195
...
...
@@ -42,7 +42,6 @@ import org.h2.expression.ValueExpression;
import
org.h2.index.Index
;
import
org.h2.index.IndexType
;
import
org.h2.index.MetaIndex
;
import
org.h2.index.MultiVersionIndex
;
import
org.h2.jdbc.JdbcSQLException
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.FileStore
;
...
...
@@ -935,13 +934,7 @@ public class MetaTable extends Table {
}
}
IndexColumn
[]
cols
=
index
.
getIndexColumns
();
String
indexClass
;
if
(
index
instanceof
MultiVersionIndex
)
{
indexClass
=
((
MultiVersionIndex
)
index
).
getBaseIndex
().
getClass
().
getName
();
}
else
{
indexClass
=
index
.
getClass
().
getName
();
}
String
indexClass
=
index
.
getClass
().
getName
();
for
(
int
k
=
0
;
k
<
cols
.
length
;
k
++)
{
IndexColumn
idxCol
=
cols
[
k
];
Column
column
=
idxCol
.
column
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/RegularTable.java
浏览文件 @
384e5195
...
...
@@ -26,7 +26,6 @@ import org.h2.index.Cursor;
import
org.h2.index.HashIndex
;
import
org.h2.index.Index
;
import
org.h2.index.IndexType
;
import
org.h2.index.MultiVersionIndex
;
import
org.h2.index.NonUniqueHashIndex
;
import
org.h2.index.PageBtreeIndex
;
import
org.h2.index.PageDataIndex
;
...
...
@@ -141,19 +140,7 @@ public class RegularTable extends TableBase {
trace
.
error
(
e2
,
"could not undo operation"
);
throw
e2
;
}
DbException
de
=
DbException
.
convert
(
e
);
if
(
de
.
getErrorCode
()
==
ErrorCode
.
DUPLICATE_KEY_1
)
{
for
(
Index
index
:
indexes
)
{
if
(
index
.
getIndexType
().
isUnique
()
&&
index
instanceof
MultiVersionIndex
)
{
MultiVersionIndex
mv
=
(
MultiVersionIndex
)
index
;
if
(
mv
.
isUncommittedFromOtherSession
(
session
,
row
))
{
throw
DbException
.
get
(
ErrorCode
.
CONCURRENT_UPDATE_1
,
index
.
getName
());
}
}
}
}
throw
de
;
throw
DbException
.
convert
(
e
);
}
analyzeIfRequired
(
session
);
}
...
...
@@ -259,9 +246,6 @@ public class RegularTable extends TableBase {
index
=
new
TreeIndex
(
this
,
indexId
,
indexName
,
cols
,
indexType
);
}
}
if
(
database
.
isMVStore
())
{
index
=
new
MultiVersionIndex
(
index
,
this
);
}
if
(
index
.
needRebuild
()
&&
rowCount
>
0
)
{
try
{
Index
scan
=
getScanIndex
(
session
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论