Skip to content

Commit 5061046

Browse files
committed
Fix a nasty data loss/corruption bug from the sql_pop query.
It is not safe to assume that we can bulk-delete all entries from the log table based on their "id" being less than the largest "id" we have processed so far, as we may unintentionally delete some tuples from the log which we haven't actually processed yet in the case of concurrent transactions adding tuples into the log table.
1 parent 53906c4 commit 5061046

File tree

2 files changed

+9
-6
lines changed

2 files changed

+9
-6
lines changed

lib/pg_repack.sql.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ CREATE VIEW repack.tables AS
190190
'INSERT INTO repack.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert,
191191
'DELETE FROM repack.table_' || R.oid || ' WHERE ' || repack.get_compare_pkey(PK.indexrelid, '$1') AS sql_delete,
192192
'UPDATE repack.table_' || R.oid || ' SET ' || repack.get_assign(R.oid, '$2') || ' WHERE ' || repack.get_compare_pkey(PK.indexrelid, '$1') AS sql_update,
193-
'DELETE FROM repack.log_' || R.oid || ' WHERE id <= $1' AS sql_pop
193+
'DELETE FROM repack.log_' || R.oid || ' WHERE id = $1' AS sql_pop
194194
FROM pg_class R
195195
LEFT JOIN pg_class T ON R.reltoastrelid = T.oid
196196
LEFT JOIN repack.primary_keys PK

lib/repack.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,16 @@ repack_apply(PG_FUNCTION_ARGS)
282282
plan_update = repack_prepare(sql_update, 2, &argtypes[1]);
283283
execute_plan(SPI_OK_UPDATE, plan_update, &values[1], &nulls[1]);
284284
}
285+
/* Delete tuple in log.
286+
* XXX It would be a lot more efficient to perform
287+
* this DELETE in bulk, but be careful to only
288+
* delete log entries we have actually processed.
289+
*/
290+
if (plan_pop == NULL)
291+
plan_pop = repack_prepare(sql_pop, 1, argtypes);
292+
execute_plan(SPI_OK_DELETE, plan_pop, values, nulls);
285293
}
286294

287-
/* delete tuple in log */
288-
if (plan_pop == NULL)
289-
plan_pop = repack_prepare(sql_pop, 1, argtypes);
290-
execute_plan(SPI_OK_DELETE, plan_pop, values, nulls);
291-
292295
SPI_freetuptable(tuptable);
293296
}
294297

0 commit comments

Comments
 (0)