diff --git a/dbms/include/DB/Storages/MergeTree/MergeTreeData.h b/dbms/include/DB/Storages/MergeTree/MergeTreeData.h index d7ed68eb2d9..c7cf7667c05 100644 --- a/dbms/include/DB/Storages/MergeTree/MergeTreeData.h +++ b/dbms/include/DB/Storages/MergeTree/MergeTreeData.h @@ -494,6 +494,8 @@ private: /// Используется, чтобы не выполнять одновременно функцию grabOldParts. std::mutex grab_old_parts_mutex; + /// То же самое для clearOldTemporaryDirectories. + std::mutex clear_old_temporary_directories_mutex; /** Для каждого шарда множество шардированных кусков. */ diff --git a/dbms/src/Storages/MergeTree/MergeTreeData.cpp b/dbms/src/Storages/MergeTree/MergeTreeData.cpp index a962224a7cb..40667cac5ef 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeData.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeData.cpp @@ -371,6 +371,11 @@ void MergeTreeData::loadDataParts(bool skip_sanity_checks) void MergeTreeData::clearOldTemporaryDirectories() { + /// Если метод уже вызван из другого потока, то можно ничего не делать. + std::unique_lock lock(clear_old_temporary_directories_mutex, std::defer_lock); + if (!lock.try_lock()) + return; + /// Удаляем временные директории старше суток. Poco::DirectoryIterator end; for (Poco::DirectoryIterator it{full_path}; it != end; ++it) @@ -379,10 +384,17 @@ void MergeTreeData::clearOldTemporaryDirectories() { Poco::File tmp_dir(full_path + it.name()); - if (tmp_dir.isDirectory() && tmp_dir.getLastModified().epochTime() + 86400 < time(0)) + try { - LOG_WARNING(log, "Removing temporary directory " << full_path << it.name()); - Poco::File(full_path + it.name()).remove(true); + if (tmp_dir.isDirectory() && tmp_dir.getLastModified().epochTime() + 86400 < time(0)) + { + LOG_WARNING(log, "Removing temporary directory " << full_path << it.name()); + Poco::File(full_path + it.name()).remove(true); + } + } + catch (const Poco::FileNotFoundException &) + { + /// Ничего не делаем, если файл уже удалён. } } }