From d598775e337dd0e35f115826e0e4b4b520e8ffd5 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Sun, 14 Sep 2025 23:29:14 +0300 Subject: [PATCH] mvcc: properly remove mutations of rolled back tx mvstore was not removing deletions made by a tx that rolled back. deletions are removed by clearing the `end` mark from the row version. --- core/mvcc/database/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/mvcc/database/mod.rs b/core/mvcc/database/mod.rs index 9a243ae52..130f95d76 100644 --- a/core/mvcc/database/mod.rs +++ b/core/mvcc/database/mod.rs @@ -1403,6 +1403,13 @@ impl MvStore { for ref id in write_set { if let Some(row_versions) = self.rows.get(id) { let mut row_versions = row_versions.value().write(); + for rv in row_versions.iter_mut() { + if rv.end == Some(TxTimestampOrID::TxID(tx_id)) { + // undo deletions by this transaction + rv.end = None; + } + } + // remove insertions by this transaction row_versions.retain(|rv| rv.begin != TxTimestampOrID::TxID(tx_id)); if row_versions.is_empty() { self.rows.remove(id); @@ -1779,7 +1786,9 @@ fn is_end_visible( match row_version.end { Some(TxTimestampOrID::Timestamp(rv_end_ts)) => current_tx.begin_ts < rv_end_ts, Some(TxTimestampOrID::TxID(rv_end)) => { - let other_tx = txs.get(&rv_end).unwrap(); + let other_tx = txs + .get(&rv_end) + .unwrap_or_else(|| panic!("Transaction {rv_end} not found")); let other_tx = other_tx.value(); let visible = match other_tx.state.load() { // V's sharp mind discovered an issue with the hekaton paper which basically states that a