1

I'm following this answer to add a NOT NULL constraint to an existing DB table with ~100M rows. However, when I try running the backend process takes out a ShareLock.

ALTER TABLE mytable VALIDATE CONSTRAINT myfield_not_null;

I confirmed this by checking pg_locks in another session, where I can see the following (5447 is the pid of the backend attempting the VALIDATE CONSTRAINT):

mydb=> select l.pid, l.mode, l.granted, l.waitstart, a.xact_start, a.query_start, a.state from pg_locks l join pg_stat_activity a on l.pid = a.pid;
  pid  |           mode           | granted |           waitstart           |          xact_start           |          query_start          | state  
-------+--------------------------+---------+-------------------------------+-------------------------------+-------------------------------+--------
  5447 | ShareLock                | t       |                               | 2023-10-06 14:58:23.133136+00 | 2023-10-06 14:58:23.355743+00 | active 
  5447 | ShareUpdateExclusiveLock | t       |                               | 2023-10-06 14:58:23.133136+00 | 2023-10-06 14:58:23.355743+00 | active

The docs explicitly say:

a VALIDATE CONSTRAINT command can be issued to verify that existing rows satisfy the constraint. The validation step does not need to lock out concurrent updates, since it knows that other transactions will be enforcing the constraint for rows that they insert or update; only pre-existing rows need to be checked. Hence, validation acquires only a SHARE UPDATE EXCLUSIVE lock on the table being altered.

The ShareLock is blocking some queries that need RowExclusiveLock (update/insert/delete).

How can I validate the constraint without taking a ShareLock?

7
  • 1
    I can't reproduce this. Presumably the ShareLock was taken by some other statement in the same transaction. Do you still get this behavior if every statement is committed separately?
    – jjanes
    Commented Oct 6, 2023 at 16:45
  • I think I ran it that way. Just tried again to make sure and got the same result. Could this be due to the db having started as v10 and being upgraded?
    – Felipe
    Commented Oct 6, 2023 at 17:27
  • I don't see how the upgrade history could cause it. Are you using any "unusual" features, like rules, RLS, event triggers, custom access methods, FDW, 3rd party extensions? Also, the lock query you show doesn't state which relation the lock was on (or if it was even a relation lock); are you sure the ShareLock is on this table and not on something else?
    – jjanes
    Commented Oct 6, 2023 at 18:08
  • Ah fair point. I just tried it again with join pg_class c on l.relation = c.oid c.relname was indeed mytable. The only "weird" things are some row triggers, two custom statistics, a different already validated constraint, and a handful of outbound and inbound FKs
    – Felipe
    Commented Oct 6, 2023 at 18:22
  • FWIW, this is on RDS, using their basic binary replication
    – Felipe
    Commented Oct 6, 2023 at 18:38

1 Answer 1

1

AWS confirmed this is an issue with their version of postgres. I guess they do some sort of internal patching and messed this up. Support confirmed this behavior is present on version 14.7 and 14.8 but not 14.6 or 14.9

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.