This commit is contained in:
Michael Kolupaev 2014-07-25 15:15:11 +04:00
parent a6e8c35ba8
commit 85c722caf3
4 changed files with 106 additions and 67 deletions

View File

@ -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 отображает файлы-столбцы на выходе выражения в новые файлы таблицы.

View File

@ -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:

View File

@ -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);

View File

@ -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
{ {
/// Если у нас есть покрывающий кусок, игнорируем все проблемы с этим куском. /// Если у нас есть покрывающий кусок, игнорируем все проблемы с этим куском.