Locking issues under transaction on Postgres
It sounds like the code might be using SAVEPOINTs to handle errors, and not releasing the savepoints before proceeding. That would explain the large number of virtual xid locks.

RELEASE SAVEPOINT after you're done with a step.

You might also want to consider batching the work into smaller chunks, as the:


SAVEPOINT
Try it
ROLLBACK TO SAVEPOINT if it fails, RELEASE SAVEPOINT if it succeeds


pattern works, but has some performance costs that scale with number of savepoints in a transaction.

This applies to PL/PgSQL BEGIN ... EXCEPTION blocks too.