Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
5d19ed04
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5d19ed04
编写于
9月 29, 2020
作者:
A
Alexander Tokmakov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
allow synchronous drop/detach table for Atomic
上级
51b9aaf4
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
66 addition
and
14 deletion
+66
-14
src/Databases/DatabaseAtomic.cpp
src/Databases/DatabaseAtomic.cpp
+29
-7
src/Databases/DatabaseAtomic.h
src/Databases/DatabaseAtomic.h
+3
-1
src/Interpreters/DatabaseCatalog.cpp
src/Interpreters/DatabaseCatalog.cpp
+16
-0
src/Interpreters/DatabaseCatalog.h
src/Interpreters/DatabaseCatalog.h
+5
-0
src/Interpreters/InterpreterDropQuery.cpp
src/Interpreters/InterpreterDropQuery.cpp
+13
-0
tests/integration/test_merge_tree_s3/test.py
tests/integration/test_merge_tree_s3/test.py
+0
-3
tests/integration/test_rename_column/test.py
tests/integration/test_rename_column/test.py
+0
-1
tests/integration/test_ttl_move/test.py
tests/integration/test_ttl_move/test.py
+0
-1
tests/integration/test_ttl_replicated/test.py
tests/integration/test_ttl_replicated/test.py
+0
-1
未找到文件。
src/Databases/DatabaseAtomic.cpp
浏览文件 @
5d19ed04
...
...
@@ -83,7 +83,7 @@ void DatabaseAtomic::attachTable(const String & name, const StoragePtr & table,
assert
(
relative_table_path
!=
data_path
&&
!
relative_table_path
.
empty
());
DetachedTables
not_in_use
;
std
::
unique_lock
lock
(
mutex
);
not_in_use
=
cle
e
nupDetachedTables
();
not_in_use
=
cle
a
nupDetachedTables
();
auto
table_id
=
table
->
getStorageID
();
assertDetachedTableNotInUse
(
table_id
.
uuid
);
DatabaseWithDictionaries
::
attachTableUnlocked
(
name
,
table
,
lock
);
...
...
@@ -97,7 +97,7 @@ StoragePtr DatabaseAtomic::detachTable(const String & name)
auto
table
=
DatabaseWithDictionaries
::
detachTableUnlocked
(
name
,
lock
);
table_name_to_path
.
erase
(
name
);
detached_tables
.
emplace
(
table
->
getStorageID
().
uuid
,
table
);
not_in_use
=
cle
e
nupDetachedTables
();
not_in_use
=
cle
a
nupDetachedTables
();
return
table
;
}
...
...
@@ -263,7 +263,7 @@ void DatabaseAtomic::commitCreateTable(const ASTCreateQuery & query, const Stora
if
(
query
.
database
!=
database_name
)
throw
Exception
(
ErrorCodes
::
UNKNOWN_DATABASE
,
"Database was renamed to `{}`, cannot create table in `{}`"
,
database_name
,
query
.
database
);
not_in_use
=
cle
e
nupDetachedTables
();
not_in_use
=
cle
a
nupDetachedTables
();
assertDetachedTableNotInUse
(
query
.
uuid
);
renameNoReplace
(
table_metadata_tmp_path
,
table_metadata_path
);
attachTableUnlocked
(
query
.
table
,
table
,
lock
);
/// Should never throw
...
...
@@ -306,7 +306,7 @@ void DatabaseAtomic::assertDetachedTableNotInUse(const UUID & uuid)
", because it was detached but still used by some query. Retry later."
,
ErrorCodes
::
TABLE_ALREADY_EXISTS
);
}
DatabaseAtomic
::
DetachedTables
DatabaseAtomic
::
cle
e
nupDetachedTables
()
DatabaseAtomic
::
DetachedTables
DatabaseAtomic
::
cle
a
nupDetachedTables
()
{
DetachedTables
not_in_use
;
auto
it
=
detached_tables
.
begin
();
...
...
@@ -324,14 +324,14 @@ DatabaseAtomic::DetachedTables DatabaseAtomic::cleenupDetachedTables()
return
not_in_use
;
}
void
DatabaseAtomic
::
assertCanBeDetached
(
bool
cle
e
nup
)
void
DatabaseAtomic
::
assertCanBeDetached
(
bool
cle
a
nup
)
{
if
(
cle
e
nup
)
if
(
cle
a
nup
)
{
DetachedTables
not_in_use
;
{
std
::
lock_guard
lock
(
mutex
);
not_in_use
=
cle
e
nupDetachedTables
();
not_in_use
=
cle
a
nupDetachedTables
();
}
}
std
::
lock_guard
lock
(
mutex
);
...
...
@@ -500,6 +500,28 @@ void DatabaseAtomic::renameDictionaryInMemoryUnlocked(const StorageID & old_name
const
auto
&
dict
=
dynamic_cast
<
const
IDictionaryBase
&>
(
*
result
.
object
);
dict
.
updateDictionaryName
(
new_name
);
}
void
DatabaseAtomic
::
waitDetachedTableNotInUse
(
const
UUID
&
uuid
)
{
{
std
::
lock_guard
lock
{
mutex
};
if
(
detached_tables
.
count
(
uuid
)
==
0
)
return
;
}
/// Table is in use while its shared_ptr counter is greater than 1.
/// We cannot trigger condvar on shared_ptr destruction, so it's busy wait.
while
(
true
)
{
DetachedTables
not_in_use
;
{
std
::
lock_guard
lock
{
mutex
};
not_in_use
=
cleanupDetachedTables
();
if
(
detached_tables
.
count
(
uuid
)
==
0
)
return
;
}
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
500
));
}
}
}
src/Databases/DatabaseAtomic.h
浏览文件 @
5d19ed04
...
...
@@ -58,6 +58,8 @@ public:
void
tryCreateSymlink
(
const
String
&
table_name
,
const
String
&
actual_data_path
);
void
tryRemoveSymlink
(
const
String
&
table_name
);
void
waitDetachedTableNotInUse
(
const
UUID
&
uuid
);
private:
void
commitAlterTable
(
const
StorageID
&
table_id
,
const
String
&
table_metadata_tmp_path
,
const
String
&
table_metadata_path
)
override
;
void
commitCreateTable
(
const
ASTCreateQuery
&
query
,
const
StoragePtr
&
table
,
...
...
@@ -65,7 +67,7 @@ private:
void
assertDetachedTableNotInUse
(
const
UUID
&
uuid
);
typedef
std
::
unordered_map
<
UUID
,
StoragePtr
>
DetachedTables
;
[[
nodiscard
]]
DetachedTables
cle
e
nupDetachedTables
();
[[
nodiscard
]]
DetachedTables
cle
a
nupDetachedTables
();
void
tryCreateMetadataSymlink
();
...
...
src/Interpreters/DatabaseCatalog.cpp
浏览文件 @
5d19ed04
...
...
@@ -701,6 +701,7 @@ void DatabaseCatalog::enqueueDroppedTableCleanup(StorageID table_id, StoragePtr
tables_marked_dropped
.
push_front
({
table_id
,
table
,
dropped_metadata_path
,
0
});
else
tables_marked_dropped
.
push_back
({
table_id
,
table
,
dropped_metadata_path
,
drop_time
});
tables_marked_dropped_ids
.
insert
(
table_id
.
uuid
);
/// If list of dropped tables was empty, start a drop task
if
(
drop_task
&&
tables_marked_dropped
.
size
()
==
1
)
(
*
drop_task
)
->
schedule
();
...
...
@@ -742,6 +743,9 @@ void DatabaseCatalog::dropTableDataTask()
try
{
dropTableFinally
(
table
);
std
::
lock_guard
lock
(
tables_marked_dropped_mutex
);
auto
removed
=
tables_marked_dropped_ids
.
erase
(
table
.
table_id
.
uuid
);
assert
(
removed
);
}
catch
(...)
{
...
...
@@ -755,6 +759,8 @@ void DatabaseCatalog::dropTableDataTask()
need_reschedule
=
true
;
}
}
wait_table_finally_dropped
.
notify_all
();
}
/// Do not schedule a task if there is no tables to drop
...
...
@@ -814,6 +820,16 @@ String DatabaseCatalog::resolveDictionaryName(const String & name) const
return
toString
(
db_and_table
.
second
->
getStorageID
().
uuid
);
}
void
DatabaseCatalog
::
waitTableFinallyDropped
(
const
UUID
&
uuid
)
{
if
(
uuid
==
UUIDHelpers
::
Nil
)
return
;
std
::
unique_lock
lock
{
tables_marked_dropped_mutex
};
wait_table_finally_dropped
.
wait
(
lock
,
[
&
](){
return
tables_marked_dropped_ids
.
count
(
uuid
)
==
0
;
});
}
DDLGuard
::
DDLGuard
(
Map
&
map_
,
std
::
shared_mutex
&
db_mutex_
,
std
::
unique_lock
<
std
::
mutex
>
guards_lock_
,
const
String
&
elem
)
:
map
(
map_
),
db_mutex
(
db_mutex_
),
guards_lock
(
std
::
move
(
guards_lock_
))
...
...
src/Interpreters/DatabaseCatalog.h
浏览文件 @
5d19ed04
...
...
@@ -9,6 +9,7 @@
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <mutex>
#include <shared_mutex>
#include <array>
...
...
@@ -179,6 +180,8 @@ public:
/// Try convert qualified dictionary name to persistent UUID
String
resolveDictionaryName
(
const
String
&
name
)
const
;
void
waitTableFinallyDropped
(
const
UUID
&
uuid
);
private:
// The global instance of database catalog. unique_ptr is to allow
// deferred initialization. Thought I'd use std::optional, but I can't
...
...
@@ -249,11 +252,13 @@ private:
mutable
std
::
mutex
ddl_guards_mutex
;
TablesMarkedAsDropped
tables_marked_dropped
;
std
::
unordered_set
<
UUID
>
tables_marked_dropped_ids
;
mutable
std
::
mutex
tables_marked_dropped_mutex
;
std
::
unique_ptr
<
BackgroundSchedulePoolTaskHolder
>
drop_task
;
static
constexpr
time_t
default_drop_delay_sec
=
8
*
60
;
time_t
drop_delay_sec
=
default_drop_delay_sec
;
std
::
condition_variable
wait_table_finally_dropped
;
};
}
src/Interpreters/InterpreterDropQuery.cpp
浏览文件 @
5d19ed04
...
...
@@ -124,6 +124,19 @@ BlockIO InterpreterDropQuery::executeToTable(
}
}
table
.
reset
();
ddl_guard
=
{};
if
(
query
.
no_delay
)
{
if
(
query
.
kind
==
ASTDropQuery
::
Kind
::
Drop
)
DatabaseCatalog
::
instance
().
waitTableFinallyDropped
(
table_id
.
uuid
);
else
if
(
query
.
kind
==
ASTDropQuery
::
Kind
::
Detach
)
{
if
(
auto
*
atomic
=
typeid_cast
<
DatabaseAtomic
*>
(
database
.
get
()))
atomic
->
waitDetachedTableNotInUse
(
table_id
.
uuid
);
}
}
return
{};
}
...
...
tests/integration/test_merge_tree_s3/test.py
浏览文件 @
5d19ed04
...
...
@@ -75,7 +75,6 @@ def drop_table(cluster):
minio
=
cluster
.
minio_client
node
.
query
(
"DROP TABLE IF EXISTS s3_test NO DELAY"
)
time
.
sleep
(
1
)
try
:
assert
len
(
list
(
minio
.
list_objects
(
cluster
.
minio_bucket
,
'data/'
)))
==
0
finally
:
...
...
@@ -317,7 +316,6 @@ def test_move_replace_partition_to_another_table(cluster):
minio
.
list_objects
(
cluster
.
minio_bucket
,
'data/'
)))
==
FILES_OVERHEAD
*
2
+
FILES_OVERHEAD_PER_PART_WIDE
*
4
node
.
query
(
"DROP TABLE s3_clone NO DELAY"
)
time
.
sleep
(
1
)
assert
node
.
query
(
"SELECT sum(id) FROM s3_test FORMAT Values"
)
==
"(0)"
assert
node
.
query
(
"SELECT count(*) FROM s3_test FORMAT Values"
)
==
"(16384)"
# Data should remain in S3
...
...
@@ -330,7 +328,6 @@ def test_move_replace_partition_to_another_table(cluster):
list
(
minio
.
list_objects
(
cluster
.
minio_bucket
,
'data/'
)))
==
FILES_OVERHEAD
+
FILES_OVERHEAD_PER_PART_WIDE
*
4
node
.
query
(
"DROP TABLE s3_test NO DELAY"
)
time
.
sleep
(
1
)
# Backup data should remain in S3.
assert
len
(
list
(
minio
.
list_objects
(
cluster
.
minio_bucket
,
'data/'
)))
==
FILES_OVERHEAD_PER_PART_WIDE
*
4
...
...
tests/integration/test_rename_column/test.py
浏览文件 @
5d19ed04
...
...
@@ -37,7 +37,6 @@ def started_cluster():
def
drop_table
(
nodes
,
table_name
):
for
node
in
nodes
:
node
.
query
(
"DROP TABLE IF EXISTS {} NO DELAY"
.
format
(
table_name
))
time
.
sleep
(
1
)
def
create_table
(
nodes
,
table_name
,
with_storage_policy
=
False
,
with_time_column
=
False
,
...
...
tests/integration/test_ttl_move/test.py
浏览文件 @
5d19ed04
...
...
@@ -403,7 +403,6 @@ def test_moves_to_disk_eventually_work(started_cluster, name, engine):
node1
.
query
(
"DROP TABLE {} NO DELAY"
.
format
(
name_temp
))
time
.
sleep
(
2
)
used_disks
=
get_used_disks_for_table
(
node1
,
name
)
assert
set
(
used_disks
)
==
{
"jbod2"
}
...
...
tests/integration/test_ttl_replicated/test.py
浏览文件 @
5d19ed04
...
...
@@ -27,7 +27,6 @@ def started_cluster():
def
drop_table
(
nodes
,
table_name
):
for
node
in
nodes
:
node
.
query
(
"DROP TABLE IF EXISTS {} NO DELAY"
.
format
(
table_name
))
time
.
sleep
(
1
)
# Column TTL works only with wide parts, because it's very expensive to apply it for compact parts
def
test_ttl_columns
(
started_cluster
):
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录