Plain merge tree partition exports - #2290
Conversation
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 240da8173c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| catch (...) | ||
| { | ||
| replicated_error = std::current_exception(); | ||
| tryLogCurrentException(getLogger("InterpreterKillQueryQuery"), | ||
| "KILL EXPORT PARTITION: could not read system.replicated_partition_exports (the WHERE may " | ||
| "reference columns that only exist for plain MergeTree); ignoring ReplicatedMergeTree tables"); |
There was a problem hiding this comment.
Propagate system-table read failures during KILL
If either system-table query fails for an operational reason such as a memory limit, timeout, or internal exception, this broad catch treats it like an engine-specific unknown column and continues with the other table. The command can therefore report successful results while silently leaving matching exports from the failed table running. Only suppress the specific predicate-resolution error that proves the filter belongs exclusively to the other table; propagate all other failures.
AGENTS.md reference: AGENTS.md:L153-L153
Useful? React with 👍 / 👎.
…ya-26.6/export-partition-plain-merge-tree
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c8d038d350
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…n-plain-merge-tree
…n-plain-merge-tree Keep the skip-policy commit-file short-circuit from antalya-26.6 together with lazy first-sink creation, and port the new skip-policy tests into the unified object-storage suite. Co-authored-by: Cursor <cursoragent@cursor.com>
…n-plain-merge-tree
|
|
||
| ### Pending mutations {#plain-merge-tree-pending-mutations} | ||
|
|
||
| The pending-mutation gate is more conservative than on a `Replicated*MergeTree`. A plain `MergeTree` does not scope its mutation snapshot by partition, so a mutation restricted with `IN PARTITION` still marks the parts of every other partition as having pending mutations, and exporting an unaffected partition is refused with `PENDING_MUTATIONS_NOT_ALLOWED`. The gate fails closed - it never exports data that a pending mutation would have changed - so the effect is that you may have to wait for an unrelated mutation to finish, or set `export_merge_tree_part_throw_on_pending_mutations` to `false`. |
There was a problem hiding this comment.
I should check ways around this later
| ### Commit info columns | ||
|
|
||
| These columns surface paths produced by the destination storage during commit, so it is possible to inspect what was written without consulting the destination directly: | ||
| These columns surface paths produced by the destination storage during commit, so it is possible to inspect what was written without consulting the destination directly. They are populated for `Replicated*MergeTree` sources only; a plain `MergeTree` does not persist the commit paths, so they stay empty there even after a successful commit. |
There was a problem hiding this comment.
This shall be implemented for plain merge tree as well
There was a problem hiding this comment.
Is this going to be covered in another PR?
There was a problem hiding this comment.
I plan to cover it in this pr unless it is too complex (I doubt it is).
For now I am reviewing my own code (AI code :D)
|
Iceberg export partition regression suite is fully passing on no/ice/glue catalogs with plain merge tree tables. I will wait for dev review and the CI run to do a final CI triage to confirm no PR caused failures. |
mkmkme
left a comment
There was a problem hiding this comment.
Overall looks good and worth an approval. I left some comments, I'll let you decide what to do about them
| The partition export tasks of both engines can be observed through `system.partition_exports`. | ||
|
|
||
| The export task can be killed by issuing the kill command: `KILL EXPORT PARTITION <where predicate for system.replicated_partition_exports>`. | ||
| `system.replicated_partition_exports` is kept as an alias of `system.partition_exports` for backwards compatibility. It returns exactly the same rows, including exports of plain `MergeTree` tables. Filter on `source_table` (or join against `system.tables`) if you need only one engine. |
There was a problem hiding this comment.
That's a bit counter-intuitive IMHO. But I don't have a good and simple solution for that. I can suggest one of two things:
- Make
replicated_partition_exportsonly return exports from RMT (but it will likely require quite a bit of work for not exactly a great result) - Mark
system.replicated_partition_exportsexplicitly as deprecated (but I am not sure we have such a mechanism for system tables)
| ### Exception columns | ||
|
|
||
| - `last_exception_per_replica` is an `Array(Tuple(replica String, message String, part String, time DateTime, count UInt64))`. Each tuple is the most recent exception observed by a single replica plus a best-effort within-replica `count`. Replicas that have never reported an exception are omitted. | ||
| - `last_exception_per_replica` is an `Array(Tuple(replica String, message String, part String, time DateTime, count UInt64))`. Each tuple is the most recent exception observed by a single replica plus a best-effort within-replica `count`. Replicas that have never reported an exception are omitted. A plain `MergeTree` export runs on a single node, so it contributes at most one tuple and its `replica` is empty. |
There was a problem hiding this comment.
Haven't found (yet) in the documentation, but wanted to ask: does it make sense for EXPORT PARTITION on a plain MergeTree to be synchronous? And instead of finding the exception in the system table, it would raise the exception as a response?
| if (!iceberg_metadata) | ||
| throw Exception(ErrorCodes::BAD_ARGUMENTS, "Destination storage {} is a data lake but not an iceberg table", dest_storage->getName()); | ||
|
|
||
| if (!context->getSettingsRef()[Setting::allow_insert_into_iceberg]) |
There was a problem hiding this comment.
Nitpick: I would probably move this check before checking for iceberg_metadata being nullptr, but it's not a biggie
| auto & entry = it->second; | ||
|
|
||
| if (entry.getDescriptor().status != MergeTreePartitionExportTask::Status::PENDING) | ||
| return CancellationCode::CancelCannotBeSent; |
There was a problem hiding this comment.
I'd say this also deserves a LOG_INFO
| std::lock_guard lock(mutex); | ||
| auto it = findByTransactionId(transaction_id); | ||
| if (it == tasks.end()) | ||
| return; |
There was a problem hiding this comment.
Maybe a LOG_DEBUG here? Why can this happen?
| expected_status="COMPLETED", | ||
| timeout=60, | ||
| poll_interval=0.5, | ||
| system_table="partition_exports", |
There was a problem hiding this comment.
Is this argument (here and below) is actually used in a way that replicated_partition_exports is passed explicitly?
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2662683255
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return ExportPartitionUtils::compositeKey( | ||
| manifest.partition_id, manifest.destination_database, manifest.destination_table); |
There was a problem hiding this comment.
Preserve or migrate the previous ZooKeeper task keys
After upgrading with an existing replicated export, its ZooKeeper child still uses the old <partition>_<database>.<table> key, while this method now derives the escaped dot-separated key. Although poll reads the old child, the inserted entry is indexed by this new derived key and removeStaleEntries immediately removes it because that key is absent from the ZooKeeper child list; the scheduler therefore cannot resume its remaining parts, and a new export also misses the old path during duplicate detection. Migrate existing nodes or retain the actual ZooKeeper child key in the entry.
Useful? React with 👍 / 👎.
| entry.part_references = std::move(part_references); | ||
| entry.setDescriptor(std::move(descriptor)); | ||
| persist(composite_key, entry.getDescriptor().toJsonString()); | ||
| tasks.insert_or_assign(composite_key, std::move(entry)); |
There was a problem hiding this comment.
Block force replacement while the prior commit is running
When a forced re-export arrives while the existing entry has committing == true, this replacement proceeds even though KILL explicitly refuses that state. killExportPart cannot cancel the destination commit, so the old commit can publish successfully and then find its registry entry replaced, while the new transaction subsequently exports and commits the same partition again; for an Iceberg destination this can produce duplicate rows under two transaction IDs. Reject or defer the replacement until the existing commit lease is released.
Useful? React with 👍 / 👎.
List of changes:
system.partition_exportstable that keeps track of both plain and replicated cases. The oldsystem.replicated_partition_exportsis aliased to this new one for backwards compatibility.Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Export partition on plain merge tree. Should close #1908
User facing & functional changes:
system.partition_exportstable that covers both the previousreplicated_partition_exportsand the new one for plain merge treeDocumentation entry for user-facing changes
...
CI/CD Options
Exclude tests:
Regression jobs to run: