Re: [HACKERS] SERIALIZABLE with parallel query

From: Thomas Munro <thomas(dot)munro(at)enterprisedb(dot)com>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: Haribabu Kommi <kommi(dot)haribabu(at)gmail(dot)com>, Michael Paquier <michael(dot)paquier(at)gmail(dot)com>, Andres Freund <andres(at)anarazel(dot)de>, Kevin Grittner <kgrittn(at)gmail(dot)com>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: [HACKERS] SERIALIZABLE with parallel query
Date: 2018-02-22 12:54:45
Message-ID: CAEepm=09Mht4gSY==DEALCcx1TwJ=dQJ4gj6xmtQNEHVnWNmxw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox
Thread:
Lists: pgsql-hackers

On Fri, Jan 26, 2018 at 4:24 AM, Robert Haas <robertmhaas(at)gmail(dot)com> wrote:
> I took a look at this today and thought it might be OK to commit,

Thank you for looking at this!

> modulo a few minor issues: (1) you didn't document the new tranche and

Fixed.

> (2) I prefer to avoid if (blah) { Assert(thing) } in favor of
> Assert(!blah || thing).

Done.

> But then I got a little bit concerned about ReleasePredicateLocks().
> Suppose that in the middle of a read-only transaction,
> SXACT_FLAG_RO_SAFE becomes true. The next call to
> SerializationNeededForRead in each process will call
> ReleasePredicateLocks. In the workers, this won't do anything, so
> we'll just keep coming back there. But in the leader, we'll go ahead
> do all that stuff, including MySerializableXact =
> InvalidSerializableXact. But in the workers, it's still set. Maybe
> that's OK, but I'm not sure that it's OK...

Ouch. Yeah. It's not OK. If the leader gives up its
SERIALIZABLEXACT object early due to that safe-read-only optimisation,
the workers are left with a dangling pointer to a SERIALIZABLEXACT
object that has been pushed onto FinishedSerializableTransactions.
From there it will move to PredXact->availableTransactions and might
be handed out to some other transaction, so it is not safe to retain a
pointer to that object.

The best solution I have come up with so far is to add a reference
count to SERIALIZABLEXACT. I toyed with putting the refcount into the
DSM instead, but then I ran into problems making that work when you
have a query with multiple Gather nodes. Since the refcount is in
SERIALIZABLEXACT I also had to add a generation counter so that I
could detect the case where you try to attach too late (the leader has
already errored out, the refcount has reached 0 and the
SERIALIZABLEXACT object has been recycled).

The attached is a draft patch only, needing some testing and polish.
Brickbats, better ideas?

FWIW I also considered a couple of other ideas: (1) Keeping the
object alive on the FinishedSerializableTransactions list until the
leader's transaction is finished seems broken because we need to be
able to spill that list to the SLRU at any time, and if we somehow
made them sticky we could run out of memory. (2) Anything involving
the leader having sole control of the object lifetime seems
problematic... well, it might work if you disabled the
SXACT_FLAG_RO_SAFE optimisation so that ReleasePredicateLocks() always
happens after all workers have finished, but that seems like cheating.

PS I noticed that for BecomeLockGroupMember() we say "If we can't
join the lock group, the leader has gone away, so just exit quietly"
but for various other similar things we spew errors (most commonly
seen one being "ERROR: could not map dynamic shared memory segment").
Intentional?

--
Thomas Munro
http://www.enterprisedb.com

Attachment Content-Type Size
ssi-parallel-v11.patch application/octet-stream 31.3 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Thomas Munro 2018-02-22 13:18:28 Re: [HACKERS] SERIALIZABLE with parallel query
Previous Message Ashutosh Bapat 2018-02-22 12:41:36 PlaceHolderVars in pushed down child-join cause error