Skip to content

fix(transaction): commit a COPY only once its checkpoint can run - #1507

Merged
adsharma merged 1 commit into
LadybugDB:mainfrom
aikins01:fix/copy-commit-waits-for-writers
Nov 4, 2026
Merged

adsharma merged 1 commit into
LadybugDB:mainfrom
aikins01:fix/copy-commit-waits-for-writers

Conversation

@aikins01

@aikins01 aikins01 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Description

Follow-up to #1435. COPY FROM and CREATE INDEX on a large ART don't write their data to the WAL. They become durable only through the checkpoint that runs right after their commit, and that checkpoint needs every other write transaction gone. With multi-writer mode on by default, b6649b7 turned a checkpoint that timed out waiting for another writer into a warning on stderr, and the statement reported success. A COPY run beside another connection's open transaction then lost all of its rows if the process stopped before a later checkpoint: reopening the database without a checkpoint showed an empty table.

This makes a statement that needs the forced checkpoint wait for the other write transactions to finish before it commits, instead of after:

  • While it waits, new write transactions wait at BEGIN until its commit and checkpoint finish, so none can start in between and block the checkpoint. Read-only transactions aren't held.
  • If another writer is still open after the checkpoint wait timeout, the transaction is rolled back and the statement fails, so nothing is committed and running it again is safe. Inside an explicit transaction it's the COMMIT that fails, and the whole transaction is rolled back.
  • If a second such transaction reaches commit while the first is waiting, the second is rolled back right away. The first is waiting for it to leave, so letting both wait would only stall them until the timeout.

A forced checkpoint that still fails after the commit, for example on an I/O error, throws CheckpointException again, as before b6649b7. The message now says to run CHECKPOINT rather than the statement, since the statement's rows are already committed.

The trade-off is that a COPY or large CREATE INDEX can now fail when another write transaction stays open longer than the checkpoint wait timeout (5 s by default), and new write transactions are held for up to that long while it waits. Before b6649b7 the same COPY also failed, but only after it had committed, so running it again tried to insert rows that were already there.

Types of changes

  • Bug fix
  • New feature
  • Breaking change
  • Documentation Update

Checklist

  • I have changed storage version if on disk format has changed.
    Not needed: the on-disk format is unchanged.
  • I have requested a review from a maintainer.
  • I have updated the documentation (if needed).

COPY FROM and CREATE INDEX on a large ART skip the WAL and are durable
only through the checkpoint after their commit, which needs every other
write transaction gone. A checkpoint that timed out waiting for another
writer was downgraded to a warning, so the statement reported success
and its rows were lost if the process stopped before a later checkpoint.

Such a transaction now waits for the other write transactions to leave
before it commits, and new write transactions wait at BEGIN until its
commit and checkpoint finish. If another writer is still open after the
checkpoint wait timeout, the transaction is rolled back and nothing is
committed. A second such transaction reaching commit while one waits is
rolled back at once, since the first is waiting for it to leave.

A forced checkpoint that still fails after the commit throws
CheckpointException again.
@adsharma

adsharma commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Liveness: wait throws without rolling back, so failed waiter still holds activeWriteCount and first waiter stalls to timeout — should rollback move into the manager?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants