Problem
There's a race condition between beginBarrier and the user's database write. The current implementation uses seq ranges to identify which undolog entries belong to a barrier:
beginBarrier reads max(seq) as startSeq
- ⚠️ Another write could happen here → undolog entries created
- User's write happens → undolog entries created
endBarrier reads max(seq) as endSeq, captures range [startSeq+1, endSeq]
If concurrent writes occur between steps 1 and 3, those unrelated undolog entries are incorrectly included in the barrier's range.
Proposed Solution
Tag undolog entries with a barrier ID rather than relying on seq ranges.
Schema change:
-- Add barrierId column to undolog
ALTER TABLE undolog ADD COLUMN barrierId TEXT;
-- Add currentBarrierId to undoState
ALTER TABLE undoState ADD COLUMN currentBarrierId TEXT;
Trigger change:
INSERT INTO undolog(barrierId, tableName, sql)
VALUES((SELECT currentBarrierId FROM undoState WHERE id = 1), ...);
API change:
beginBarrier sets currentBarrierId in undoState
endBarrier queries WHERE barrierId = ? instead of seq range
- Entries with
barrierId = NULL are ignored (written outside a barrier)
Benefits
- Eliminates race condition entirely
- Works correctly with concurrent database access
- No change to public API
Problem
There's a race condition between
beginBarrierand the user's database write. The current implementation uses seq ranges to identify which undolog entries belong to a barrier:beginBarrierreadsmax(seq)as startSeqendBarrierreadsmax(seq)as endSeq, captures range [startSeq+1, endSeq]If concurrent writes occur between steps 1 and 3, those unrelated undolog entries are incorrectly included in the barrier's range.
Proposed Solution
Tag undolog entries with a barrier ID rather than relying on seq ranges.
Schema change:
Trigger change:
API change:
beginBarriersetscurrentBarrierIdin undoStateendBarrierqueriesWHERE barrierId = ?instead of seq rangebarrierId = NULLare ignored (written outside a barrier)Benefits