Skip to content

CAS BACKUP to S3 fails on AWS when a blob is 5 MiB or smaller #2491

Description

@DimensionWieldr

BACKUP of a table on a CAS disk to an S3(...) destination on the same endpoint fails on AWS S3. The statement throws, and no backup is produced. The table itself is left as it was.

Every MergeTree part hits this. primary.idx, marks (.mrk*), and column files (.bin) are stored as blobs, including when they are tiny. A blob object is a short envelope header plus the file. The backup copies only the file bytes with a ranged UploadPartCopy. AWS accepts a byte range only when the source object is greater than 5 MiB, and answers InvalidRequest ("The specified copy source is not supported as a byte-range copy source") otherwise. primary.idx and the marks of an ordinary part are far below that, so the first such file aborts the BACKUP.

ClickHouse falls back to reading the file and uploading it when multipart copy is disabled, when the store is GCS, or when UploadPartCopy returns AccessDenied. InvalidRequest is not one of those cases, so the refusal fails the statement. A backup that gets past this check is not written with the envelope included; it does not get that far.

Workaround: force the buffer path.

BACKUP TABLE t TO S3('https://s3.amazonaws.com/bucket/path', 'key', 'secret')
SETTINGS s3_allow_multipart_copy = 0

allow_s3_native_copy = 0 does the same. Blobs larger than 5 MiB can still use the server-side copy.

Caused by: #2415

Why the fast path rejects a normal part

partFileMustStayBlob in ContentAddressedTransaction.cpp keeps primary.idx, .bin, and .mrk* out of the manifest. BackupWriterS3::tryNativeCopyFromContentAddressedDisk then copies each of those with copyS3File at payload_offset (the envelope length, never zero). CopyFileHelper::performCopy uses UploadPartCopy for every non-zero offset, and performMultipartUploadCopy falls back only on Aws::S3::S3Errors::ACCESS_DENIED.

AWS documents the size rule on UploadPartCopy: a CopySourceRange is valid only if the source object is greater than 5 MiB. https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html

The integration test test_cas_backup_s3_native_copy runs against RustFS with 100000-row parts. That store accepts a ranged copy of a small object, so the AWS refusal is not covered.

Fix direction

Skip the ranged copy when the blob object is not greater than 5 MiB, and copy that file through buffers. Treating this InvalidRequest as the same fallback as AccessDenied covers a store that enforces the rule when the local size check does not.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions