From: | Robert Haas <robertmhaas(at)gmail(dot)com> |
---|---|
To: | Qingqing Zhou <zhouqq(dot)postgres(at)gmail(dot)com> |
Cc: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: cache invalidation skip logic |
Date: | 2015-08-09 15:24:15 |
Message-ID: | CA+Tgmoa7UoHgFcoyi6S8V4jzdiUV_61wBb-67_Tt0g0QwYY1bQ@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On Thu, Aug 6, 2015 at 2:19 PM, Qingqing Zhou <zhouqq(dot)postgres(at)gmail(dot)com> wrote:
> 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?
In step 1, AcceptInvalidationMessages() should process all pending
invalidation messages. So if step 2 did AcceptInvalidationMessages()
again it would be a no-op, because no messages should remain at that
point.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
From | Date | Subject | |
---|---|---|---|
Next Message | Robert Haas | 2015-08-09 15:39:31 | Re: Freeze avoidance of very large table. |
Previous Message | Robert Haas | 2015-08-09 15:21:44 | Re: statement_timeout affects query results fetching? |