Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
f0a009bd
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,发现更多精彩内容 >>
提交
f0a009bd
编写于
1月 30, 2016
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dbms: attempt to fix an error [#METR-19399].
上级
061306d0
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
97 addition
and
17 deletion
+97
-17
dbms/include/DB/Storages/MergeTree/MergeTreeData.h
dbms/include/DB/Storages/MergeTree/MergeTreeData.h
+11
-0
dbms/src/Storages/MergeTree/MergeTreeData.cpp
dbms/src/Storages/MergeTree/MergeTreeData.cpp
+38
-1
dbms/src/Storages/StorageReplicatedMergeTree.cpp
dbms/src/Storages/StorageReplicatedMergeTree.cpp
+48
-16
未找到文件。
dbms/include/DB/Storages/MergeTree/MergeTreeData.h
浏览文件 @
f0a009bd
...
...
@@ -752,6 +752,15 @@ public:
*/
size_t
getMaxPartsCountForMonth
()
const
;
/** Минимальный номер блока в указанном месяце.
* Возвращает также bool - есть ли хоть один кусок.
*/
std
::
pair
<
Int64
,
bool
>
getMinBlockNumberForMonth
(
DayNum_t
month
)
const
;
/** Есть ли указанный номер блока в каком-нибудь куске указанного месяца.
*/
bool
hasBlockNumberInMonth
(
Int64
block_number
,
DayNum_t
month
)
const
;
/** Если в таблице слишком много активных кусков, спит некоторое время, чтобы дать им возможность смерджиться.
* Если передано until - проснуться раньше, если наступило событие.
*/
...
...
@@ -878,6 +887,8 @@ public:
static
String
getMonthName
(
DayNum_t
month
);
static
DayNum_t
getMonthDayNum
(
const
Field
&
partition
);
static
DayNum_t
getMonthFromName
(
const
String
&
month_name
);
/// Получить месяц из имени куска или достаточной его части.
static
DayNum_t
getMonthFromPartPrefix
(
const
String
&
part_prefix
);
Context
&
context
;
const
String
date_column_name
;
...
...
dbms/src/Storages/MergeTree/MergeTreeData.cpp
浏览文件 @
f0a009bd
...
...
@@ -117,8 +117,10 @@ MergeTreeData::MergeTreeData(
Int64
MergeTreeData
::
getMaxDataPartIndex
()
{
std
::
lock_guard
<
std
::
mutex
>
lock_all
(
all_data_parts_mutex
);
Int64
max_part_id
=
0
;
for
(
const
auto
&
part
:
data_parts
)
for
(
const
auto
&
part
:
all_
data_parts
)
max_part_id
=
std
::
max
(
max_part_id
,
part
->
right
);
return
max_part_id
;
...
...
@@ -967,6 +969,36 @@ size_t MergeTreeData::getMaxPartsCountForMonth() const
return
res
;
}
std
::
pair
<
Int64
,
bool
>
MergeTreeData
::
getMinBlockNumberForMonth
(
DayNum_t
month
)
const
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
data_parts_mutex
);
for
(
const
auto
&
part
:
data_parts
)
/// Поиск можно сделать лучше.
if
(
part
->
month
==
month
)
return
{
part
->
left
,
true
};
/// Блоки в data_parts упорядочены по month и left.
return
{
0
,
false
};
}
bool
MergeTreeData
::
hasBlockNumberInMonth
(
Int64
block_number
,
DayNum_t
month
)
const
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
data_parts_mutex
);
for
(
const
auto
&
part
:
data_parts
)
/// Поиск можно сделать лучше.
{
if
(
part
->
month
==
month
&&
part
->
left
<=
block_number
&&
part
->
right
>=
block_number
)
return
true
;
if
(
part
->
month
>
month
)
break
;
}
return
false
;
}
void
MergeTreeData
::
delayInsertIfNeeded
(
Poco
::
Event
*
until
)
{
size_t
parts_count
=
getMaxPartsCountForMonth
();
...
...
@@ -1419,4 +1451,9 @@ DayNum_t MergeTreeData::getMonthFromName(const String & month_name)
return
date
;
}
DayNum_t
MergeTreeData
::
getMonthFromPartPrefix
(
const
String
&
part_prefix
)
{
return
getMonthFromName
(
part_prefix
.
substr
(
0
,
strlen
(
"YYYYMM"
)));
}
}
dbms/src/Storages/StorageReplicatedMergeTree.cpp
浏览文件 @
f0a009bd
...
...
@@ -88,6 +88,27 @@ const auto WAIT_FOR_REPLICA_QUEUE_MS = 10 * 1000;
const
auto
MERGE_SELECTING_SLEEP_MS
=
5
*
1000
;
/** Добавляемым блокам данных присваиваются некоторые номера - целые числа.
* Для добавляемых обычным способом (INSERT) блоков, номера выделяются по возрастанию.
* Слияния делаются для диапазонов номеров блоков на числовой прямой:
* если в слиянии участвуют номера блоков x, z, и есть блок с номером y, что x < y < z, то блок с номером y тоже участвует в слиянии.
* Это требуется для сохранения свойств некоторых операций, которые могут производиться при слиянии - например, в CollapsingMergeTree.
* В частности, это позволяет во время слияния знать, что в одном куске все данные были добавлены раньше, чем все данные в другом куске.
*
* Изредка возникает необходимость добавить в таблицу какой-то заведомо старый кусок данных,
* чтобы он воспринимался как старый в логике работы CollapsingMergeTree.
* Такой кусок данных можно добавить с помощью специального запроса ATTACH.
* И в этом случае, мы должны выделить этому куску номера меньшие, чем номера всех остальных кусков.
* В связи с этим, номера обычных кусков, добавляемых INSERT-ом, начинаются не с нуля, а с большего числа,
* а меньшие номера считаются "зарезервированными".
*
* Почему это число равно 200?
* Дело в том, что раньше не поддерживались отрицательные номера блоков.
* А также, слияние сделано так, что при увеличении количества кусков, вставка новых кусков специально замедляется,
* пока слияния не успеют уменьшить число кусков; и это было рассчитано примерно для 200 кусков.
* А значит, что при вставке в таблицу всех кусков из другой таблицы, 200 номеров наверняка достаточно.
* В свою очередь, это число выбрано почти наугад.
*/
const
Int64
RESERVED_BLOCK_NUMBERS
=
200
;
...
...
@@ -1455,15 +1476,30 @@ void StorageReplicatedMergeTree::mergeSelectingThread()
}
/// Можно слить куски, если все номера между ними заброшены - не соответствуют никаким блокам.
/// Номера до RESERVED_BLOCK_NUMBERS всегда не соответствуют никаким блокам.
for
(
Int64
number
=
std
::
max
(
RESERVED_BLOCK_NUMBERS
,
left
->
right
+
1
);
number
<=
right
->
left
-
1
;
++
number
)
{
String
path1
=
zookeeper_path
+
"/block_numbers/"
+
month_name
+
"/block-"
+
padIndex
(
number
);
String
path2
=
zookeeper_path
+
"/nonincrement_block_numbers/"
+
month_name
+
"/block-"
+
padIndex
(
number
);
for
(
Int64
number
=
left
->
right
+
1
;
number
<=
right
->
left
-
1
;
++
number
)
{
/** Для номеров до RESERVED_BLOCK_NUMBERS не используется AbandonableLock
* - такие номера не могут быть "заброшены" - то есть, не использованными для кусков.
* Это номера кусков, которые были добавлены с помощью ALTER ... ATTACH.
* Они должны идти без пропусков (для каждого номера должен быть кусок).
* Проверяем, что для всех таких номеров есть куски,
* иначе, через "дыры" - отсутствующие куски, нельзя мерджить.
*/
if
(
AbandonableLockInZooKeeper
::
check
(
path1
,
*
zookeeper
)
!=
AbandonableLockInZooKeeper
::
ABANDONED
&&
AbandonableLockInZooKeeper
::
check
(
path2
,
*
zookeeper
)
!=
AbandonableLockInZooKeeper
::
ABANDONED
)
return
false
;
if
(
number
<
RESERVED_BLOCK_NUMBERS
)
{
if
(
!
data
.
hasBlockNumberInMonth
(
number
,
left
->
month
))
return
false
;
}
else
{
String
path1
=
zookeeper_path
+
"/block_numbers/"
+
month_name
+
"/block-"
+
padIndex
(
number
);
String
path2
=
zookeeper_path
+
"/nonincrement_block_numbers/"
+
month_name
+
"/block-"
+
padIndex
(
number
);
if
(
AbandonableLockInZooKeeper
::
check
(
path1
,
*
zookeeper
)
!=
AbandonableLockInZooKeeper
::
ABANDONED
&&
AbandonableLockInZooKeeper
::
check
(
path2
,
*
zookeeper
)
!=
AbandonableLockInZooKeeper
::
ABANDONED
)
return
false
;
}
}
memoized_parts_that_could_be_merged
.
insert
(
key
);
...
...
@@ -2821,15 +2857,11 @@ void StorageReplicatedMergeTree::attachPartition(ASTPtr query, const Field & fie
/// Выделим добавляемым кускам максимальные свободные номера, меньшие RESERVED_BLOCK_NUMBERS.
/// NOTE: Проверка свободности номеров никак не синхронизируется. Выполнять несколько запросов ATTACH/DETACH/DROP одновременно нельзя.
Int64
min_used_number
=
RESERVED_BLOCK_NUMBERS
;
DayNum_t
month
=
DateLUT
::
instance
().
makeDayNum
(
parse
<
UInt16
>
(
partition
.
substr
(
0
,
4
)),
parse
<
UInt8
>
(
partition
.
substr
(
4
,
2
)),
1
);
DayNum_t
month
=
MergeTreeData
::
getMonthFromPartPrefix
(
partition
);
{
/// Немного неоптимально.
auto
existing_parts
=
data
.
getAllDataParts
();
for
(
const
auto
&
part
:
existing_parts
)
if
(
part
->
month
==
month
)
min_used_number
=
std
::
min
(
min_used_number
,
part
->
left
);
}
auto
num_and_exists
=
data
.
getMinBlockNumberForMonth
(
month
);
if
(
num_and_exists
.
second
)
min_used_number
=
num_and_exists
.
first
;
/// Добавим записи в лог.
std
::
reverse
(
parts
.
begin
(),
parts
.
end
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录