mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge
This commit is contained in:
parent
2ff0b62529
commit
88644b2377
@ -303,6 +303,52 @@ public:
|
||||
assertEOF(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
void checkNotBroken()
|
||||
{
|
||||
String path = storage.full_path + name;
|
||||
|
||||
if (!checksums.empty())
|
||||
{
|
||||
checksums.checkSizes(path + "/");
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Проверяем, что первичный ключ непуст.
|
||||
|
||||
Poco::File index_file(path + "/primary.idx");
|
||||
|
||||
if (!index_file.exists() || index_file.getSize() == 0)
|
||||
throw Exception("Part " + path + " is broken: primary key is empty.", ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART);
|
||||
|
||||
/// Проверяем, что все засечки непусты и имеют одинаковый размер.
|
||||
|
||||
ssize_t marks_size = -1;
|
||||
for (NamesAndTypesList::const_iterator it = storage.columns->begin(); it != storage.columns->end(); ++it)
|
||||
{
|
||||
Poco::File marks_file(path + "/" + escapeForFileName(it->first) + ".mrk");
|
||||
|
||||
/// При добавлении нового столбца в таблицу файлы .mrk не создаются. Не будем ничего удалять.
|
||||
if (!marks_file.exists())
|
||||
continue;
|
||||
|
||||
if (marks_size == -1)
|
||||
{
|
||||
marks_size = marks_file.getSize();
|
||||
|
||||
if (0 == marks_size)
|
||||
throw Exception("Part " + path + " is broken: " + marks_file.path() + " is empty.",
|
||||
ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<ssize_t>(marks_file.getSize()) != marks_size)
|
||||
throw Exception("Part " + path + " is broken: marks have different sizes.",
|
||||
ErrorCodes::BAD_SIZE_OF_FILE_IN_DATA_PART);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<DataPart> MutableDataPartPtr;
|
||||
|
@ -177,6 +177,8 @@ void MergeTreeData::loadDataParts()
|
||||
}
|
||||
}
|
||||
|
||||
DataPartsVector broken_parts_to_remove;
|
||||
|
||||
Poco::RegularExpression::MatchVec matches;
|
||||
for (const String & file_name : part_file_names)
|
||||
{
|
||||
@ -187,14 +189,28 @@ void MergeTreeData::loadDataParts()
|
||||
parsePartName(file_name, *part, &matches);
|
||||
part->name = file_name;
|
||||
|
||||
bool broken = false;
|
||||
|
||||
try
|
||||
{
|
||||
part->loadIndex();
|
||||
part->loadChecksums();
|
||||
part->checkNotBroken();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
broken = true;
|
||||
tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
/// Игнорируем и, возможно, удаляем битые куски, которые могут образовываться после грубого перезапуска сервера.
|
||||
if (isBrokenPart(full_path + file_name))
|
||||
if (broken)
|
||||
{
|
||||
if (part->level == 0)
|
||||
{
|
||||
/// Восстановить куски нулевого уровня невозможно.
|
||||
LOG_ERROR(log, "Removing broken part " << full_path + file_name << " because is't impossible to repair.");
|
||||
part->remove();
|
||||
broken_parts_to_remove.push_back(part);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -222,7 +238,7 @@ void MergeTreeData::loadDataParts()
|
||||
if (contained_parts >= 2)
|
||||
{
|
||||
LOG_ERROR(log, "Removing broken part " << full_path + file_name << " because it covers at least 2 other parts");
|
||||
Poco::File(full_path + file_name).remove(true);
|
||||
broken_parts_to_remove.push_back(part);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -236,21 +252,16 @@ void MergeTreeData::loadDataParts()
|
||||
|
||||
part->modification_time = Poco::File(full_path + file_name).getLastModified().epochTime();
|
||||
|
||||
try
|
||||
{
|
||||
part->loadIndex();
|
||||
part->loadChecksums();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/// Не будем вставлять в набор кусок с битым индексом. Пропустим кусок и позволим серверу запуститься.
|
||||
tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
|
||||
data_parts.insert(part);
|
||||
}
|
||||
|
||||
if (broken_parts_to_remove.size() > 2)
|
||||
throw Exception("Suspiciously many (" + toString(broken_parts_to_remove.size()) + ") broken parts to remove.",
|
||||
ErrorCodes::TOO_MANY_UNEXPECTED_DATA_PARTS);
|
||||
|
||||
for (const auto & part : broken_parts_to_remove)
|
||||
part->remove();
|
||||
|
||||
all_data_parts = data_parts;
|
||||
|
||||
/** Удаляем из набора актуальных кусков куски, которые содержатся в другом куске (которые были склеены),
|
||||
@ -627,55 +638,6 @@ bool MergeTreeData::isPartDirectory(const String & dir_name, Poco::RegularExpres
|
||||
}
|
||||
|
||||
|
||||
bool MergeTreeData::isBrokenPart(const String & path)
|
||||
{
|
||||
/// Проверяем, что первичный ключ непуст.
|
||||
|
||||
Poco::File index_file(path + "/primary.idx");
|
||||
|
||||
if (!index_file.exists() || index_file.getSize() == 0)
|
||||
{
|
||||
LOG_ERROR(log, "Part " << path << " is broken: primary key is empty.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Проверяем, что все засечки непусты и имеют одинаковый размер.
|
||||
|
||||
ssize_t marks_size = -1;
|
||||
for (NamesAndTypesList::const_iterator it = columns->begin(); it != columns->end(); ++it)
|
||||
{
|
||||
Poco::File marks_file(path + "/" + escapeForFileName(it->first) + ".mrk");
|
||||
|
||||
/// при добавлении нового столбца в таблицу файлы .mrk не создаются. Не будем ничего удалять.
|
||||
if (!marks_file.exists())
|
||||
continue;
|
||||
|
||||
if (marks_size == -1)
|
||||
{
|
||||
marks_size = marks_file.getSize();
|
||||
|
||||
if (0 == marks_size)
|
||||
{
|
||||
LOG_ERROR(log, "Part " << path << " is broken: " << marks_file.path() << " is empty.");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<ssize_t>(marks_file.getSize()) != marks_size)
|
||||
{
|
||||
LOG_ERROR(log, "Part " << path << " is broken: marks have different sizes.");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MergeTreeData::renameTempPartAndAdd(MutableDataPartPtr part, Increment * increment)
|
||||
{
|
||||
auto removed = renameTempPartAndReplace(part, increment);
|
||||
|
Loading…
Reference in New Issue
Block a user