Fix possible deadlocks with MergeTreeData::Transaction

This commit is contained in:
alesapin 2022-07-01 15:16:32 +02:00
parent 016176dc02
commit 57284e6a9d
3 changed files with 17 additions and 9 deletions

View File

@ -139,6 +139,9 @@ void MergeTreeSink::finishDelayedChunk()
bool added = false;
/// It's important to create it outside of lock scope because
/// otherwise it can lock parts in desctructor and deadlock is possible.
MergeTreeData::Transaction transaction(storage, context->getCurrentTransaction().get());
{
auto lock = storage.lockParts();
storage.fillNewPartName(part, lock);
@ -155,19 +158,15 @@ void MergeTreeSink::finishDelayedChunk()
}
else
{
MergeTreeData::Transaction transaction(storage, context->getCurrentTransaction().get());
added = storage.renameTempPartAndAdd(part, transaction, lock);
transaction.commit(&lock);
}
}
else
{
MergeTreeData::Transaction transaction(storage, context->getCurrentTransaction().get());
added = storage.renameTempPartAndAdd(part, transaction, lock);
transaction.commit(&lock);
}
}
/// Part can be deduplicated, so increment counters and add to part log only if it's really added

View File

@ -471,6 +471,8 @@ void ReplicatedMergeTreeSink::commitPart(
/// Information about the part.
storage.getCommitPartOps(ops, part, block_id_path);
/// It's important to create it outside of lock scope because
/// otherwise it can lock parts in desctructor and deadlock is possible.
MergeTreeData::Transaction transaction(storage, NO_TRANSACTION_RAW); /// If you can not add a part to ZK, we'll remove it back from the working set.
bool renamed = false;

View File

@ -1540,9 +1540,11 @@ PartitionCommandsResultInfo StorageMergeTree::attachPartition(
loaded_parts[i]->storeVersionMetadata();
String old_name = renamed_parts.old_and_new_names[i].old_name;
/// It's important to create it outside of lock scope because
/// otherwise it can lock parts in desctructor and deadlock is possible.
MergeTreeData::Transaction transaction(*this, local_context->getCurrentTransaction().get());
{
auto lock = lockParts();
MergeTreeData::Transaction transaction(*this, local_context->getCurrentTransaction().get());
fillNewPartName(loaded_parts[i], lock);
renameTempPartAndAdd(loaded_parts[i], transaction, lock);
transaction.commit(&lock);
@ -1797,13 +1799,18 @@ CheckResults StorageMergeTree::checkData(const ASTPtr & query, ContextPtr local_
void StorageMergeTree::attachRestoredParts(MutableDataPartsVector && parts)
{
for (auto part : parts)
{
auto lock = lockParts();
/// It's important to create it outside of lock scope because
/// otherwise it can lock parts in desctructor and deadlock is possible.
MergeTreeData::Transaction transaction(*this, NO_TRANSACTION_RAW);
fillNewPartName(part, lock);
renameTempPartAndAdd(part, transaction, lock);
transaction.commit(&lock);
{
auto lock = lockParts();
fillNewPartName(part, lock);
renameTempPartAndAdd(part, transaction, lock);
transaction.commit(&lock);
}
}
}