CAS: remove a part with one ref drop - #2452
Conversation
`DataPartStorageOnDiskBase::remove` renames a part to `delete_tmp_<part>`, unlinks its files and removes the directory in separate disk transactions. On a `cas` disk a part is one ref, and the rename and the unlink batch each published a new manifest before the final drop: two extra manifest writes and five extra ref-log records per removed part, more with projections. Dropping a ref is atomic, so a `cas` disk does not need the rename. `remove` now calls `removeSharedRecursive` on the part directory for content-addressed disks: one ref-log record, no manifest write. Detached parts keep the generic path. Create/insert/drop cycle (3 parts per table, 8 workers, RustFS), per cycle on a `cas` disk: PUT 64 -> 28, GET 83 -> 47, wall time 30.3 -> 17.0 ms. Signed-off-by: Mikhail Filimonov <mfilimonov@altinity.com>
PR #2452 CI TriageFive jobs failed. Six other red statuses are the report links for those same jobs. The pull request is already merged. Summary
Nothing in the diff is a demonstrated regression. pre-existing-flaky
This is issue #2332, opened 2026-09-09 on PR #2300, three weeks before this run. A note there records infrastructure
unknown
What would resolve it: the 60-day fail rate of this exact scenario on
What would resolve it: the 60-day fail rate of Recommendations
|
|
Looked into the unknown section fails: Lightweight delete fail is ClickHouse#122083. ASAN CAS stress fails are not related to this PR. The hung check is a single cancelled INSERT in the ASAN CAS stress job, and that job passed on the MasterCI run of the merge commit. LGTM |
Removing a part from a
casdisk now writes one ref-log record and no manifest. Before, every removed part cost two extra manifest writes and five extra ref-log records, more with projections.DataPartStorageOnDiskBase::removerenames a part todelete_tmp_<part>, unlinks its files and removes the directory in separate disk transactions. On acasdisk a part is one ref, so the rename and the unlink batch each published a new manifest before the final drop. Dropping a ref is atomic, so the rename has nothing to protect: for content-addressed disksremovecallsremoveSharedRecursiveon the part directory and returns. Detached parts keep the generic path.Measured
Create/insert/drop cycle:
CREATE TABLE, 3 inserts of 1000 rows,SELECT,DROP TABLE SYNC; 8 workers, 48 cycles per run, RustFS, two runs per side. Base isantalya-26.6at e2dd0f5.casdiskcasdiskcasdisk, first passcasdisk, second passcas/s3diskcas/s3diskcas/s3disk, first passRequest counts of workloads that remove no parts in the measured window (inserts, attach, selects, mutations) are the same on both sides.
Events in
system.cas_logper removed part:manifest_putref_repointref_dropBehaviour
casdisk keeps its name until its ref is dropped; nodelete_tmp_<part>ref appears.Related: #2429
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Removing a data part from a
casdisk writes one ref-log record instead of two manifests and six ref-log records. A create/insert/drop cycle issues 56% fewer PUT and 43% fewer GET requests and takes 44% less time.Documentation entry for user-facing changes
CI/CD Options
Exclude tests:
Regression jobs to run:
🤖 Generated with Claude Code