mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-11 18:14:03 +00:00
Merge
This commit is contained in:
parent
a6e8c35ba8
commit
85c722caf3
@ -617,9 +617,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
void renameAndDetachPart(DataPartPtr part, const String & prefix);
|
void renameAndDetachPart(DataPartPtr part, const String & prefix);
|
||||||
|
|
||||||
/** Удалить неактуальные куски. Возвращает имена удаленных кусков.
|
/** Возвращает старые неактуальные куски, которые можно удалить. Одновременно удаляет их из списка кусков, но не с диска.
|
||||||
*/
|
*/
|
||||||
Strings clearOldParts();
|
DataPartsVector grabOldParts();
|
||||||
|
|
||||||
|
/** Обращает изменения, сделанные grabOldParts().
|
||||||
|
*/
|
||||||
|
void addOldParts(const DataPartsVector & parts);
|
||||||
|
|
||||||
|
/** Удалить неактуальные куски.
|
||||||
|
*/
|
||||||
|
void clearOldParts();
|
||||||
|
|
||||||
/** После вызова dropAllData больше ничего вызывать нельзя.
|
/** После вызова dropAllData больше ничего вызывать нельзя.
|
||||||
* Удаляет директорию с данными и сбрасывает кеши разжатых блоков и засечек.
|
* Удаляет директорию с данными и сбрасывает кеши разжатых блоков и засечек.
|
||||||
@ -703,9 +711,6 @@ private:
|
|||||||
/// Загрузить множество кусков с данными с диска. Вызывается один раз - при создании объекта.
|
/// Загрузить множество кусков с данными с диска. Вызывается один раз - при создании объекта.
|
||||||
void loadDataParts();
|
void loadDataParts();
|
||||||
|
|
||||||
/// Определить, не битые ли данные в директории. Проверяет индекс и засечеки, но не сами данные.
|
|
||||||
bool isBrokenPart(const String & path);
|
|
||||||
|
|
||||||
/** Выражение, преобразующее типы столбцов.
|
/** Выражение, преобразующее типы столбцов.
|
||||||
* Если преобразований типов нет, out_expression=nullptr.
|
* Если преобразований типов нет, out_expression=nullptr.
|
||||||
* out_rename_map отображает файлы-столбцы на выходе выражения в новые файлы таблицы.
|
* out_rename_map отображает файлы-столбцы на выходе выражения в новые файлы таблицы.
|
||||||
|
@ -86,6 +86,8 @@ public:
|
|||||||
zkutil::CreateMode::PersistentSequential));
|
zkutil::CreateMode::PersistentSequential));
|
||||||
block_number_lock.getUnlockOps(ops);
|
block_number_lock.getUnlockOps(ops);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
auto code = storage.zookeeper->tryMulti(ops);
|
auto code = storage.zookeeper->tryMulti(ops);
|
||||||
if (code == ZOK)
|
if (code == ZOK)
|
||||||
{
|
{
|
||||||
@ -118,6 +120,20 @@ public:
|
|||||||
+ zkutil::ZooKeeper::error2string(code), ErrorCodes::UNEXPECTED_ZOOKEEPER_ERROR);
|
+ zkutil::ZooKeeper::error2string(code), ErrorCodes::UNEXPECTED_ZOOKEEPER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (zkutil::KeeperException & e)
|
||||||
|
{
|
||||||
|
/** Если потерялось соединение, и мы не знаем, применились ли изменения, нельзя удалять локальный кусок:
|
||||||
|
* если изменения применились, в /blocks/ появился вставленный блок, и его нельзя будет вставить снова.
|
||||||
|
*/
|
||||||
|
if (e.code == ZOPERATIONTIMEOUT ||
|
||||||
|
e.code == ZCONNECTIONLOSS)
|
||||||
|
{
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -251,34 +251,14 @@ void MergeTreeData::loadDataParts()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Strings MergeTreeData::clearOldParts()
|
MergeTreeData::DataPartsVector MergeTreeData::grabOldParts()
|
||||||
{
|
{
|
||||||
Poco::ScopedTry<Poco::FastMutex> lock;
|
Poco::ScopedTry<Poco::FastMutex> lock;
|
||||||
Strings res;
|
DataPartsVector res;
|
||||||
|
|
||||||
/// Если метод уже вызван из другого потока (или если all_data_parts прямо сейчас меняют), то можно ничего не делать.
|
/// Если метод уже вызван из другого потока (или если all_data_parts прямо сейчас меняют), то можно ничего не делать.
|
||||||
if (!lock.lock(&all_data_parts_mutex))
|
if (!lock.lock(&all_data_parts_mutex))
|
||||||
{
|
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
|
|
||||||
time_t now = time(0);
|
|
||||||
for (DataParts::iterator it = all_data_parts.begin(); it != all_data_parts.end();)
|
|
||||||
{
|
|
||||||
int ref_count = it->use_count();
|
|
||||||
if (ref_count == 1 && /// После этого ref_count не может увеличиться.
|
|
||||||
(*it)->remove_time < now &&
|
|
||||||
now - (*it)->remove_time > settings.old_parts_lifetime)
|
|
||||||
{
|
|
||||||
LOG_DEBUG(log, "Removing part " << (*it)->name);
|
|
||||||
|
|
||||||
res.push_back((*it)->name);
|
|
||||||
(*it)->remove();
|
|
||||||
all_data_parts.erase(it++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Удаляем временные директории старше суток.
|
/// Удаляем временные директории старше суток.
|
||||||
Strings all_file_names;
|
Strings all_file_names;
|
||||||
@ -302,9 +282,41 @@ Strings MergeTreeData::clearOldParts()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t now = time(0);
|
||||||
|
for (DataParts::iterator it = all_data_parts.begin(); it != all_data_parts.end();)
|
||||||
|
{
|
||||||
|
int ref_count = it->use_count();
|
||||||
|
if (ref_count == 1 && /// После этого ref_count не может увеличиться.
|
||||||
|
(*it)->remove_time < now &&
|
||||||
|
now - (*it)->remove_time > settings.old_parts_lifetime)
|
||||||
|
{
|
||||||
|
res.push_back(*it);
|
||||||
|
all_data_parts.erase(it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MergeTreeData::addOldParts(const MergeTreeData::DataPartsVector & parts)
|
||||||
|
{
|
||||||
|
Poco::ScopedLock<Poco::FastMutex> lock(all_data_parts_mutex);
|
||||||
|
all_data_parts.insert(parts.begin(), parts.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MergeTreeData::clearOldParts()
|
||||||
|
{
|
||||||
|
auto parts_to_remove = grabOldParts();
|
||||||
|
|
||||||
|
for (DataPartPtr part : parts_to_remove)
|
||||||
|
{
|
||||||
|
LOG_DEBUG(log, "Removing part " << part->name);
|
||||||
|
part->remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MergeTreeData::setPath(const String & new_full_path)
|
void MergeTreeData::setPath(const String & new_full_path)
|
||||||
{
|
{
|
||||||
Poco::File(full_path).renameTo(new_full_path);
|
Poco::File(full_path).renameTo(new_full_path);
|
||||||
|
@ -522,21 +522,35 @@ void StorageReplicatedMergeTree::checkPartAndAddToZooKeeper(MergeTreeData::DataP
|
|||||||
|
|
||||||
void StorageReplicatedMergeTree::clearOldParts()
|
void StorageReplicatedMergeTree::clearOldParts()
|
||||||
{
|
{
|
||||||
Strings parts = data.clearOldParts();
|
MergeTreeData::DataPartsVector parts = data.grabOldParts();
|
||||||
|
size_t count = parts.size();
|
||||||
|
|
||||||
for (const String & name : parts)
|
if (!count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
while (!parts.empty())
|
||||||
|
{
|
||||||
|
MergeTreeData::DataPartPtr part = parts.back();
|
||||||
|
|
||||||
zkutil::Ops ops;
|
zkutil::Ops ops;
|
||||||
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + name + "/columns", -1));
|
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + part->name + "/columns", -1));
|
||||||
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + name + "/checksums", -1));
|
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + part->name + "/checksums", -1));
|
||||||
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + name, -1));
|
ops.push_back(new zkutil::Op::Remove(replica_path + "/parts/" + part->name, -1));
|
||||||
int32_t code = zookeeper->tryMulti(ops);
|
zookeeper->multi(ops);
|
||||||
if (code != ZOK)
|
|
||||||
LOG_DEBUG(log, "Couldn't remove part " << name << " from ZooKeeper: " << zkutil::ZooKeeper::error2string(code));
|
part->remove();
|
||||||
|
parts.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
data.addOldParts(parts);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parts.empty())
|
LOG_DEBUG(log, "Removed " << count << " old parts");
|
||||||
LOG_DEBUG(log, "Removed " << parts.size() << " old parts");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StorageReplicatedMergeTree::clearOldLogs()
|
void StorageReplicatedMergeTree::clearOldLogs()
|
||||||
@ -1462,18 +1476,10 @@ void StorageReplicatedMergeTree::partCheckThread()
|
|||||||
{
|
{
|
||||||
ProfileEvents::increment(ProfileEvents::ReplicatedPartChecksFailed);
|
ProfileEvents::increment(ProfileEvents::ReplicatedPartChecksFailed);
|
||||||
|
|
||||||
/// Если этот кусок еще и получен в результате слияния, это уже чересчур странно.
|
|
||||||
if (part->left != part->right)
|
|
||||||
{
|
|
||||||
LOG_ERROR(log, "Unexpected part " << part_name << " is a result of a merge. You have to resolve this manually.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR(log, "Unexpected part " << part_name << ". Removing.");
|
LOG_ERROR(log, "Unexpected part " << part_name << ". Removing.");
|
||||||
data.renameAndDetachPart(part, "unexpected_");
|
data.renameAndDetachPart(part, "unexpected_");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/// Если у нас есть покрывающий кусок, игнорируем все проблемы с этим куском.
|
/// Если у нас есть покрывающий кусок, игнорируем все проблемы с этим куском.
|
||||||
|
Loading…
Reference in New Issue
Block a user