Re: Alter index rename concurrently to

From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: Peter Eisentraut <peter(dot)eisentraut(at)2ndquadrant(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Andrey Klychkov <aaklychkov(at)mail(dot)ru>, Victor Yegorov <vyegorov(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Alter index rename concurrently to
Date: 2018-08-02 20:30:42
Message-ID: CA+Tgmoa=6M5tdXDgLM3YxXF6ogGy=QOJ8zj6oogetp=zCE+3hQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Aug 2, 2018 at 4:02 PM, Andres Freund <andres(at)anarazel(dot)de> wrote:
>> Inserting AcceptInvalidationMessages() in some location that
>> guarantees it will be executed at least once per SQL statement. I
>> tentatively propose the beginning of parse_analyze(), but I am open to
>> suggestions.
>
> I'm inclined to think that that doesn't really actually solve anything,
> but makes locking issues harder to find, because the window is smaller,
> but decidedly non-zero. Can you describe why this'd make things more
> "predictable" precisely?

Sure. I'd like to be able to explain in the documentation in simple
words when a given DDL change is likely to take effect. For changes
made under AccessExclusiveLock, there's really nothing to say: the
change will definitely take effect immediately. If you're able to do
anything at all with the relevant table, you must have got some kind
of lock on it, and that means you must have done
AcceptInvalidationMessages(), and so you will definitely see the
change. With DDL changes made under less than AccessExclusiveLock,
the situation is more complicated. Right now, we can say that a new
transaction will definitely see the changes, because it will have to
acquire a lock on that relation which it doesn't already have and will
thus have to do AcceptInvalidationMessages(). A new statement within
the same transaction may see the changes, or it may not. If it
mentions any relations not previously mentioned or if it does
something like UPDATE a relation where we previously only did a
SELECT, thus triggering a new lock acquisition, it will see the
changes. If a catchup interrupt gets sent to it, it will see the
changes. Otherwise, it won't. It's even possible that we'll start to
see the changes in the middle of a statement, because of a sinval
reset or something. To summarize, at present, all we can really say
is that changes made by concurrent DDL which doesn't take AEL may or
may not affect already-running queries, may or may not affect new
queries, and will affect new transactions.

With this change, we'd be able to say that new statements will
definitely see the results of concurrent DDL. That's a clear, easy to
understand rule which I think users will like. It would be even
better if we could say something stronger, e.g. "Concurrent DDL will
affect new SQL statements, but not those already in progress." Or
"Concurrent DDL will affect new SQL statements, but SQL statements
that are already running may take up to 10 seconds to react to the
changes". Or whatever. I'm not sure there's really a way to get to a
really solid guarantee, but being able to tell users that, at a
minimum, the next SQL statement will notice that things have changed
would be good. Otherwise, we'll have conversations like this:

User: I have a usage pattern where I run a DDL command to rename an
object, and then in another session I tried to refer to it by the new
name, and it sometimes it works and sometimes it doesn't. Why does
that happen?

Postgres Expert: Well, there are several possible reasons. If you
already had a transaction in progress in the second window and it
already had a lock on the object strong enough for the operation you
attempted to perform and no sinval resets occurred and nothing else
triggered invalidation processing, then it would still know that
object under the old name. Otherwise it would know about it under the
new name.

User: Well, I did have a transaction open and it may have had some
kind of lock on that object already, but how do I know whether
invalidation processing happened?

Postgres Expert: There's really know way to know. If something else
on the system were doing a lot of DDL operations, then it might fill
up the invalidation queue enough to trigger catchup interrupts or
sinval resets, but if not, it could be deferred for an arbitrarily
long period of time.

User: So you're saying that if I have two PostgreSQL sessions, and I
execute the same commands in those sessions in the same order, just
like the isolationtester does, I can get different answers depending
on whether some third session creates a lot of unrelated temporary
tables in a different database while that's happening?

Postgres Expert: Yes.

I leave it to your imagination to fill in what this imaginary user
will say next, but I bet it will be snarky.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Geoghegan 2018-08-02 20:32:46 Re: "Write amplification" is made worse by "getting tired" while inserting into nbtree secondary indexes (Was: Why B-Tree suffix truncation matters)
Previous Message Tom Lane 2018-08-02 20:29:36 Re: Alter index rename concurrently to