20.12.5.14 `alter table ... drop part ...` removes from ZooKeeper all blocks for the partition.
The same thing happens when CH cleans empty parts:
```
CREATE TABLE empty_parts 
(
  `k`   Int8,
  `v`   Int8
)
ENGINE = ReplicatedSummingMergeTree ('/clickhouse/empty_parts','replica1')
ORDER BY k;

insert into empty_parts values (1, 15);
insert into empty_parts values (1, -15);
optimize table empty_parts;
insert into empty_parts values (2, -15);

select name, active, rows, modification_time from system.parts where table like 'empty_parts'

name        | active | rows | modification_time  
------------+--------+------+--------------------
all_15_15_0 |      0 |    1 | 2021-01-07 21:54:05
all_16_16_0 |      0 |    1 | 2021-01-08 20:13:00
all_15_16_1 |      1 |    0 | 2021-01-08 20:13:46
all_17_17_0 |      1 |    1 | 2021-01-08 20:13:47


select name, value from system.zookeeper where path='/clickhouse/empty_parts/blocks/'

name                                         | value      
---------------------------------------------+------------
all_9295045124109325217_14756667786308374723 | all_16_16_0
all_18396465411487747783_4385790938943258888 | all_17_17_0
```
The next insert of the same block is deduplicated:
```
insert into empty_parts values (2, -15);

2021.01.08 20:13:53.267392 <Information> empty_parts (Replicated OutputStream): Block with ID all_18396465411487747783_4385790938943258888 already exists locally as part all_17_17_0; ignoring it.
```
The empty part is getting dropped in background
```
2021.01.08 20:14:19.103462 <Trace> empty_parts: Will try to insert a log entry to DROP_RANGE for part: all_15_16_1
```
The next insert of the same block is NOT deduplicated:
```
insert into empty_parts values (2, -15);

2021.01.08 20:16:19.145203 <Debug> executeQuery: (from [::1]:40824) insert into empty_parts values
2021.01.08 20:16:19.146681 <Debug> empty_parts (Replicated OutputStream): Wrote block with ID 'all_18396465411487747783_4385790938943258888', 1 rows
2021.01.08 20:16:19.181508 <Trace> empty_parts: Renaming temporary part tmp_insert_all_23_23_0 to all_18_18_0.


select name, active, rows, modification_time from system.parts where table like 'empty_parts'

name        | active | rows | modification_time  
------------+--------+------+--------------------
all_17_17_0 |      1 |    1 | 2021-01-08 16:13:47
all_18_18_0 |      1 |    1 | 2021-01-08 16:16:19


select name, value from system.zookeeper where path='/clickhouse/empty_parts/blocks/'

name                                         | value      
---------------------------------------------+------------
all_18396465411487747783_4385790938943258888 | all_18_18_0

SELECT _part, * FROM empty_parts

┌─_part───────┬─k─┬──v─┐
│ all_17_17_0 │ 1 │ 15 │
└─────────────┴───┴────┘
┌─_part───────┬─k─┬──v─┐
│ all_18_18_0 │ 1 │ 15 │
└─────────────┴───┴────┘
```

if (MergeTreeDataPartChecksums::isBadChecksumsErrorCode(e.code()))
            {
                transaction.rollback();
                ProfileEvents::increment(ProfileEvents::DataAfterMergeDiffersFromReplica);
                LOG_ERROR(log, "{}. Data after merge is not byte-identical to data on another replicas. There could be several reasons: 1. Using newer version of compression library after server update. 2. Using another compression method. 3. Non-deterministic compression algorithm (highly unlikely). 4. Non-deterministic merge algorithm due to logical error in code. 5. Data corruption in memory due to bug in code. 6. Data corruption in memory due to hardware issue. 7. Manual modification of source data after server startup. 8. Manual modification of checksums stored in ZooKeeper. 9. Part format related settings like 'enable_mixed_granularity_parts' are different on different replicas. We will download merged part from replica to force byte-identical result.", getCurrentExceptionMessage(false));
                write_part_log(ExecutionStatus::fromCurrentException());
                tryRemovePartImmediately(std::move(part));
                
                
                return false;
            }
            throw;
        }
        /** Removing old parts from ZK and from the disk is delayed - see ReplicatedMergeTreeCleanupThread, clearOldParts.
          */
        /** With `ZSESSIONEXPIRED` or `ZOPERATIONTIMEOUT`, we can inadvertently roll back local changes to the parts.
          * This is not a problem, because in this case the merge will remain in the queue, and we will try again.
          */
        merge_selecting_task->schedule();
        ProfileEvents::increment(ProfileEvents::ReplicatedPartMerges);
        write_part_log({});
        return true;
    }
    catch (...)
    {
        write_part_log(ExecutionStatus::fromCurrentException());
        throw;
    }
}
bool StorageReplicatedMergeTree::tryExecutePartMutation(const StorageReplicatedMergeTree::LogEntry & entry)