In cache invalidation logic, we have the following comment: /* * Now that we have the lock, check for invalidation messages, so that we * will update or flush any stale relcache entry before we try to use it. * RangeVarGetRelid() specifically relies on us for this. We can skip * this in the not-uncommon case that we already had the same type of lock * being requested, since then no one else could have modified the * relcache entry in an undesirable way. (In the case where our own xact * modifies the rel, the relcache update happens via * CommandCounterIncrement, not here.) */ if (res != LOCKACQUIRE_ALREADY_HELD) AcceptInvalidationMessages();
It is true after we hold the lock, nobody will further modify it but there could be some left-over invalidation message we shall accept before we can continue. This is can be demonstrated with the following invalidation sequence: { 1: inval A; 2: inval B; ...; 10: inval pg_class } After step 10, another session may encounter a lock and replays this sequence: step 1: RelationBuildDesc(A), it heap_open(pg_class), pg_class lock not acquired yet, so it acquires the lock and recursively replay the sequence, goto step 2. step 2: RelationBuildDesc(B), it heap_open(pg_class), but this time we already have LOCKACQUIRE_ALREADY_HELD with pg_class, so we now access pg_class but it is wrong. User may ends up with a "could not open file ..." error. Is above sequence possible? Regards, Qingqing -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers