kvdb/sqlbase: relax bulk migration isolation
What changed, and why it matters
This commit changes a database migration transaction from the strictest isolation level (Serializable) to a more relaxed one (Read Committed) for PostgreSQL bulk migrations. The stated reason is to prevent PostgreSQL from using excessive memory for predicate locks when migrating millions of rows. The developer argues this is safe because the migration is loading into an empty destination database that it exclusively controls. The change is presented as a performance/reliability fix, not a security fix.
Treat as a routine reliability/performance patch. If operating a node that uses PostgreSQL backend migration, ensure the migration runs in a controlled environment with no other concurrent writers to the destination database, as the lowered isolation assumes exclusive migration ownership. No immediate security response is indicated by the commit itself.
Security signals we found
Transaction isolation level lowered from Serializable to Read Committed
Bulk migration operates on an empty destination database owned by the migration
No authentication, authorization, or input-validation changes
No explicit security advisory or CVE referenced in commit
Evidence from the diff
In kvdb/sqlbase/migration_bulk_postgres.go, BeginBulk() now starts PostgreSQL bulk migration transactions with sql.LevelReadCommitted instead of sql.LevelSerializable. The accompanying comment explains that serializable transactions retain predicate locks until commit/rollback, which can exhaust memory during large bulk loads. Read Committed is deemed sufficient because the destination DB is empty and owned by the migration process during loading. This reduces isolation guarantees during the migration window but does not change access controls or authentication.
Changed components
kvdb/sqlbase/migration_bulk_postgres.goPostgreSQL bulk migration path in LNDInspect captured patch +6 / −1
diff --git a/kvdb/sqlbase/migration_bulk_postgres.go b/kvdb/sqlbase/migration_bulk_postgres.go
index a64373e..c3c8b5c 100644
--- a/kvdb/sqlbase/migration_bulk_postgres.go
+++ b/kvdb/sqlbase/migration_bulk_postgres.go
@@ -88,8 +88,13 @@ func (p *postgresDB) BeginBulk(ctx context.Context) (MigrationBulkKVTx, error) {
return nil, err
}
+ // A bulk migration can touch millions of rows in a single transaction.
+ // PostgreSQL retains predicate locks until a serializable transaction
+ // ends, which can make its predicate lock table consume excessive memory.
+ // Read committed is sufficient because the migration owns the empty
+ // destination database while loading it.
tx, err := conn.BeginTx(ctx, &sql.TxOptions{
- Isolation: sql.LevelSerializable,
+ Isolation: sql.LevelReadCommitted,
})
if err != nil {
locker.Unlock()
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.