mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 16:50:48 +00:00
Merge pull request #25783 from ClickHouse/followup_drop_part_fix
Relax check during DROP PART
This commit is contained in:
commit
94d4d32e4c
@ -2332,10 +2332,33 @@ MergeTreeData::DataPartsVector MergeTreeData::removePartsInRangeFromWorkingSet(c
|
||||
throw Exception("Unexpected partition_id of part " + part->name + ". This is a bug.", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
/// It's a DROP PART and it's already executed by fetching some covering part
|
||||
if (part->info != drop_range && part->info.contains(drop_range))
|
||||
bool is_drop_part = !drop_range.isFakeDropRangePart() && drop_range.min_block;
|
||||
|
||||
if (is_drop_part && (part->info.min_block != drop_range.min_block || part->info.max_block != drop_range.max_block))
|
||||
{
|
||||
LOG_INFO(log, "Skipping drop range for part {} because covering part {} already exists", drop_range.getPartName(), part->name);
|
||||
return {};
|
||||
/// Why we check only min and max blocks here without checking merge
|
||||
/// level? It's a tricky situation which can happen on a stale
|
||||
/// replica. For example, we have parts all_1_1_0, all_2_2_0 and
|
||||
/// all_3_3_0. Fast replica assign some merges (OPTIMIZE FINAL or
|
||||
/// TTL) all_2_2_0 -> all_2_2_1 -> all_2_2_2. So it has set of parts
|
||||
/// all_1_1_0, all_2_2_2 and all_3_3_0. After that it decides to
|
||||
/// drop part all_2_2_2. Now set of parts is all_1_1_0 and
|
||||
/// all_3_3_0. Now fast replica assign merge all_1_1_0 + all_3_3_0
|
||||
/// to all_1_3_1 and finishes it. Slow replica pulls the queue and
|
||||
/// have two contradictory tasks -- drop all_2_2_2 and merge/fetch
|
||||
/// all_1_3_1. If this replica will fetch all_1_3_1 first and then tries
|
||||
/// to drop all_2_2_2 after that it will receive the LOGICAL ERROR.
|
||||
/// So here we just check that all_1_3_1 covers blocks from drop
|
||||
/// all_2_2_2.
|
||||
///
|
||||
/// NOTE: this helps only to avoid logical error during drop part.
|
||||
/// We still get intersecting "parts" in queue.
|
||||
bool is_covered_by_min_max_block = part->info.min_block <= drop_range.min_block && part->info.max_block >= drop_range.max_block;
|
||||
if (is_covered_by_min_max_block)
|
||||
{
|
||||
LOG_INFO(log, "Skipping drop range for part {} because covering part {} already exists", drop_range.getPartName(), part->name);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (part->info.min_block < drop_range.min_block)
|
||||
|
Loading…
Reference in New Issue
Block a user