Change paths of temporary part directories during RESTORE

use "/var/lib/clickhouse/data/test/table/tmp_restore_all_0_1_1_0-XXXXXXXX"
instead of "/tmp/XXXXXXXX/data/test/table/0_1_1_0"
(because directories can only be renamed in s3_plain_rewritable, and not moved to another parent directory).
This commit is contained in:
Vitaly Baranov 2024-07-20 15:01:47 +02:00
parent a3a4548d96
commit eb519c5016
4 changed files with 31 additions and 17 deletions

View File

@ -58,7 +58,8 @@ TemporaryFileOnDisk::~TemporaryFileOnDisk()
if (!disk->exists(relative_path)) if (!disk->exists(relative_path))
{ {
LOG_WARNING(getLogger("TemporaryFileOnDisk"), "Temporary path '{}' does not exist in '{}'", relative_path, disk->getPath()); if (show_warning_if_removed)
LOG_WARNING(getLogger("TemporaryFileOnDisk"), "Temporary path '{}' does not exist in '{}'", relative_path, disk->getPath());
return; return;
} }

View File

@ -27,12 +27,19 @@ public:
/// Return relative path (without disk) /// Return relative path (without disk)
const String & getRelativePath() const { return relative_path; } const String & getRelativePath() const { return relative_path; }
/// Sets whether the destructor should show a warning if the temporary file has been already removed.
/// By default a warning is shown.
void setShowWarningIfRemoved(bool show_warning_if_removed_) { show_warning_if_removed = show_warning_if_removed_; }
private: private:
DiskPtr disk; DiskPtr disk;
/// Relative path in disk to the temporary file or directory /// Relative path in disk to the temporary file or directory
String relative_path; String relative_path;
/// Whether the destructor should show a warning if the temporary file has been already removed.
bool show_warning_if_removed = true;
CurrentMetrics::Increment metric_increment; CurrentMetrics::Increment metric_increment;
/// Specified if we know what for file is used (sort/aggregate/join). /// Specified if we know what for file is used (sort/aggregate/join).

View File

@ -5549,12 +5549,17 @@ public:
attachIfAllPartsRestored(); attachIfAllPartsRestored();
} }
String getTemporaryDirectory(const DiskPtr & disk) String getTemporaryDirectory(const DiskPtr & disk, const String & part_name)
{ {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
auto it = temp_dirs.find(disk); auto it = temp_part_dirs.find(part_name);
if (it == temp_dirs.end()) if (it == temp_part_dirs.end())
it = temp_dirs.emplace(disk, std::make_shared<TemporaryFileOnDisk>(disk, "tmp/")).first; {
auto temp_part_dir = std::make_shared<TemporaryFileOnDisk>(disk, fs::path{storage->getRelativeDataPath()} / ("tmp_restore_" + part_name + "-"));
/// Attaching parts will rename them so it's expected for a temporary part directory not to exist anymore in the end.
temp_part_dir->setShowWarningIfRemoved(false);
it = temp_part_dirs.emplace(part_name, temp_part_dir).first;
}
return it->second->getRelativePath(); return it->second->getRelativePath();
} }
@ -5572,7 +5577,7 @@ private:
storage->attachRestoredParts(std::move(parts)); storage->attachRestoredParts(std::move(parts));
parts.clear(); parts.clear();
temp_dirs.clear(); temp_part_dirs.clear();
num_parts = 0; num_parts = 0;
} }
@ -5581,7 +5586,7 @@ private:
size_t num_parts = 0; size_t num_parts = 0;
size_t num_broken_parts = 0; size_t num_broken_parts = 0;
MutableDataPartsVector parts; MutableDataPartsVector parts;
std::map<DiskPtr, std::shared_ptr<TemporaryFileOnDisk>> temp_dirs; std::map<String /* part_name*/, std::shared_ptr<TemporaryFileOnDisk>> temp_part_dirs;
mutable std::mutex mutex; mutable std::mutex mutex;
}; };
@ -5648,11 +5653,9 @@ void MergeTreeData::restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> r
/// Calculate paths, for example: /// Calculate paths, for example:
/// part_name = 0_1_1_0 /// part_name = 0_1_1_0
/// part_path_in_backup = /data/test/table/0_1_1_0 /// part_path_in_backup = /data/test/table/0_1_1_0
/// tmp_dir = tmp/1aaaaaa /// temp_part_dir = /var/lib/clickhouse/data/test/table/tmp_restore_all_0_1_1_0-XXXXXXXX
/// tmp_part_dir = tmp/1aaaaaa/data/test/table/0_1_1_0
auto disk = reservation->getDisk(); auto disk = reservation->getDisk();
fs::path temp_dir = restored_parts_holder->getTemporaryDirectory(disk); fs::path temp_part_dir = restored_parts_holder->getTemporaryDirectory(disk, part_name);
fs::path temp_part_dir = temp_dir / part_path_in_backup_fs.relative_path();
/// Subdirectories in the part's directory. It's used to restore projections. /// Subdirectories in the part's directory. It's used to restore projections.
std::unordered_set<String> subdirs; std::unordered_set<String> subdirs;
@ -5679,22 +5682,25 @@ void MergeTreeData::restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> r
reservation->update(reservation->getSize() - file_size); reservation->update(reservation->getSize() - file_size);
} }
if (auto part = loadPartRestoredFromBackup(disk, temp_part_dir.parent_path(), part_name, detach_if_broken)) if (auto part = loadPartRestoredFromBackup(part_name, disk, temp_part_dir, detach_if_broken))
restored_parts_holder->addPart(part); restored_parts_holder->addPart(part);
else else
restored_parts_holder->increaseNumBrokenParts(); restored_parts_holder->increaseNumBrokenParts();
} }
MergeTreeData::MutableDataPartPtr MergeTreeData::loadPartRestoredFromBackup(const DiskPtr & disk, const String & temp_dir, const String & part_name, bool detach_if_broken) const MergeTreeData::MutableDataPartPtr MergeTreeData::loadPartRestoredFromBackup(const String & part_name, const DiskPtr & disk, const String & temp_part_dir, bool detach_if_broken) const
{ {
MutableDataPartPtr part; MutableDataPartPtr part;
auto single_disk_volume = std::make_shared<SingleDiskVolume>(disk->getName(), disk, 0); auto single_disk_volume = std::make_shared<SingleDiskVolume>(disk->getName(), disk, 0);
fs::path full_part_dir{temp_part_dir};
String parent_part_dir = full_part_dir.parent_path();
String part_dir_name = full_part_dir.filename();
/// Load this part from the directory `tmp_part_dir`. /// Load this part from the directory `temp_part_dir`.
auto load_part = [&] auto load_part = [&]
{ {
MergeTreeDataPartBuilder builder(*this, part_name, single_disk_volume, temp_dir, part_name); MergeTreeDataPartBuilder builder(*this, part_name, single_disk_volume, parent_part_dir, part_dir_name);
builder.withPartFormatFromDisk(); builder.withPartFormatFromDisk();
part = std::move(builder).build(); part = std::move(builder).build();
part->version.setCreationTID(Tx::PrehistoricTID, nullptr); part->version.setCreationTID(Tx::PrehistoricTID, nullptr);
@ -5709,7 +5715,7 @@ MergeTreeData::MutableDataPartPtr MergeTreeData::loadPartRestoredFromBackup(cons
if (!part) if (!part)
{ {
/// Make a fake data part only to copy its files to /detached/. /// Make a fake data part only to copy its files to /detached/.
part = MergeTreeDataPartBuilder{*this, part_name, single_disk_volume, temp_dir, part_name} part = MergeTreeDataPartBuilder{*this, part_name, single_disk_volume, parent_part_dir, part_dir_name}
.withPartStorageType(MergeTreeDataPartStorageType::Full) .withPartStorageType(MergeTreeDataPartStorageType::Full)
.withPartType(MergeTreeDataPartType::Wide) .withPartType(MergeTreeDataPartType::Wide)
.build(); .build();

View File

@ -1473,7 +1473,7 @@ protected:
/// Restores the parts of this table from backup. /// Restores the parts of this table from backup.
void restorePartsFromBackup(RestorerFromBackup & restorer, const String & data_path_in_backup, const std::optional<ASTs> & partitions); void restorePartsFromBackup(RestorerFromBackup & restorer, const String & data_path_in_backup, const std::optional<ASTs> & partitions);
void restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> restored_parts_holder, const MergeTreePartInfo & part_info, const String & part_path_in_backup, bool detach_if_broken) const; void restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> restored_parts_holder, const MergeTreePartInfo & part_info, const String & part_path_in_backup, bool detach_if_broken) const;
MutableDataPartPtr loadPartRestoredFromBackup(const DiskPtr & disk, const String & temp_dir, const String & part_name, bool detach_if_broken) const; MutableDataPartPtr loadPartRestoredFromBackup(const String & part_name, const DiskPtr & disk, const String & temp_part_dir, bool detach_if_broken) const;
/// Attaches restored parts to the storage. /// Attaches restored parts to the storage.
virtual void attachRestoredParts(MutableDataPartsVector && parts) = 0; virtual void attachRestoredParts(MutableDataPartsVector && parts) = 0;