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

View File

@ -27,12 +27,19 @@ public:
/// Return relative path (without disk)
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:
DiskPtr disk;
/// Relative path in disk to the temporary file or directory
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;
/// Specified if we know what for file is used (sort/aggregate/join).

View File

@ -5549,12 +5549,17 @@ public:
attachIfAllPartsRestored();
}
String getTemporaryDirectory(const DiskPtr & disk)
String getTemporaryDirectory(const DiskPtr & disk, const String & part_name)
{
std::lock_guard lock{mutex};
auto it = temp_dirs.find(disk);
if (it == temp_dirs.end())
it = temp_dirs.emplace(disk, std::make_shared<TemporaryFileOnDisk>(disk, "tmp/")).first;
auto it = temp_part_dirs.find(part_name);
if (it == temp_part_dirs.end())
{
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();
}
@ -5572,7 +5577,7 @@ private:
storage->attachRestoredParts(std::move(parts));
parts.clear();
temp_dirs.clear();
temp_part_dirs.clear();
num_parts = 0;
}
@ -5581,7 +5586,7 @@ private:
size_t num_parts = 0;
size_t num_broken_parts = 0;
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;
};
@ -5648,11 +5653,9 @@ void MergeTreeData::restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> r
/// Calculate paths, for example:
/// part_name = 0_1_1_0
/// part_path_in_backup = /data/test/table/0_1_1_0
/// tmp_dir = tmp/1aaaaaa
/// tmp_part_dir = tmp/1aaaaaa/data/test/table/0_1_1_0
/// temp_part_dir = /var/lib/clickhouse/data/test/table/tmp_restore_all_0_1_1_0-XXXXXXXX
auto disk = reservation->getDisk();
fs::path temp_dir = restored_parts_holder->getTemporaryDirectory(disk);
fs::path temp_part_dir = temp_dir / part_path_in_backup_fs.relative_path();
fs::path temp_part_dir = restored_parts_holder->getTemporaryDirectory(disk, part_name);
/// Subdirectories in the part's directory. It's used to restore projections.
std::unordered_set<String> subdirs;
@ -5679,22 +5682,25 @@ void MergeTreeData::restorePartFromBackup(std::shared_ptr<RestoredPartsHolder> r
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);
else
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;
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 = [&]
{
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();
part = std::move(builder).build();
part->version.setCreationTID(Tx::PrehistoricTID, nullptr);
@ -5709,7 +5715,7 @@ MergeTreeData::MutableDataPartPtr MergeTreeData::loadPartRestoredFromBackup(cons
if (!part)
{
/// 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)
.withPartType(MergeTreeDataPartType::Wide)
.build();

View File

@ -1473,7 +1473,7 @@ protected:
/// Restores the parts of this table from backup.
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;
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.
virtual void attachRestoredParts(MutableDataPartsVector && parts) = 0;